2 # Pyrex - Parse tree nodes for expressions
7 from Errors import error, warning, warn_once, InternalError
8 from Errors import hold_errors, release_errors, held_errors, report_error
9 from Code import UtilityCode
13 from Nodes import Node
15 from PyrexTypes import py_object_type, c_long_type, typecast, error_type, \
17 from Builtin import list_type, tuple_type, set_type, dict_type, \
18 unicode_type, str_type, bytes_type, type_type
22 from Annotate import AnnotationItem
23 from Cython import Utils
25 from Cython.Debugging import print_call_chain
26 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
32 from sets import Set as set
34 class NotConstant(object): pass # just for the name
35 not_a_constant = NotConstant()
36 constant_value_not_set = object()
38 # error messages when coercing from key[0] to key[1]
39 find_coercion_error = {
40 # string related errors
41 (Builtin.unicode_type, Builtin.bytes_type) : "Cannot convert Unicode string to 'bytes' implicitly, encoding required.",
42 (Builtin.unicode_type, Builtin.str_type) : "Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding.",
43 (Builtin.unicode_type, PyrexTypes.c_char_ptr_type) : "Unicode objects do not support coercion to C types.",
44 (Builtin.bytes_type, Builtin.unicode_type) : "Cannot convert 'bytes' object to unicode implicitly, decoding required",
45 (Builtin.bytes_type, Builtin.str_type) : "Cannot convert 'bytes' object to str implicitly. This is not portable to Py3.",
46 (Builtin.str_type, Builtin.unicode_type) : "str objects do not support coercion to unicode, use a unicode string literal instead (u'')",
47 (Builtin.str_type, Builtin.bytes_type) : "Cannot convert 'str' to 'bytes' implicitly. This is not portable.",
48 (Builtin.str_type, PyrexTypes.c_char_ptr_type) : "'str' objects do not support coercion to C types (use 'bytes'?).",
49 (PyrexTypes.c_char_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
50 (PyrexTypes.c_uchar_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
55 # subexprs [string] Class var holding names of subexpr node attrs
56 # type PyrexType Type of the result
57 # result_code string Code fragment
58 # result_ctype string C type of result_code if different from type
59 # is_temp boolean Result is in a temporary variable
60 # is_sequence_constructor
61 # boolean Is a list or tuple constructor expression
62 # is_starred boolean Is a starred expression (e.g. '*a')
64 # [ExprNode or [ExprNode or None] or None]
65 # Cached result of subexpr_nodes()
66 # use_managed_ref boolean use ref-counted temps/assignments/etc.
71 old_temp = None # error checker for multiple frees etc.
72 use_managed_ref = True # can be set by optimisation transforms
74 # The Analyse Expressions phase for expressions is split
75 # into two sub-phases:
78 # Determines the result type of the expression based
79 # on the types of its sub-expressions, and inserts
80 # coercion nodes into the expression tree where needed.
81 # Marks nodes which will need to have temporary variables
85 # Allocates temporary variables where needed, and fills
86 # in the result_code field of each node.
88 # ExprNode provides some convenience routines which
89 # perform both of the above phases. These should only
90 # be called from statement nodes, and only when no
91 # coercion nodes need to be added around the expression
92 # being analysed. In that case, the above two phases
93 # should be invoked separately.
95 # Framework code in ExprNode provides much of the common
96 # processing for the various phases. It makes use of the
97 # 'subexprs' class attribute of ExprNodes, which should
98 # contain a list of the names of attributes which can
99 # hold sub-nodes or sequences of sub-nodes.
101 # The framework makes use of a number of abstract methods.
102 # Their responsibilities are as follows.
104 # Declaration Analysis phase
106 # analyse_target_declaration
107 # Called during the Analyse Declarations phase to analyse
108 # the LHS of an assignment or argument of a del statement.
109 # Nodes which cannot be the LHS of an assignment need not
112 # Expression Analysis phase
115 # - Call analyse_types on all sub-expressions.
116 # - Check operand types, and wrap coercion nodes around
117 # sub-expressions where needed.
118 # - Set the type of this node.
119 # - If a temporary variable will be required for the
120 # result, set the is_temp flag of this node.
122 # analyse_target_types
123 # Called during the Analyse Types phase to analyse
124 # the LHS of an assignment or argument of a del
125 # statement. Similar responsibilities to analyse_types.
128 # Called by the default implementation of allocate_target_temps.
129 # Should return a C lvalue for assigning to the node. The default
130 # implementation calls calculate_result_code.
133 # - Check that this node and its subnodes form a
134 # legal constant expression. If so, do nothing,
135 # otherwise call not_const.
137 # The default implementation of check_const
138 # assumes that the expression is not constant.
141 # - Same as check_const, except check that the
142 # expression is a C lvalue whose address is
143 # constant. Otherwise, call addr_not_const.
145 # The default implementation of calc_const_addr
146 # assumes that the expression is not a constant
149 # Code Generation phase
151 # generate_evaluation_code
152 # - Call generate_evaluation_code for sub-expressions.
153 # - Perform the functions of generate_result_code
155 # - If result is temporary, call generate_disposal_code
156 # on all sub-expressions.
158 # A default implementation of generate_evaluation_code
159 # is provided which uses the following abstract methods:
161 # generate_result_code
162 # - Generate any C statements necessary to calculate
163 # the result of this node from the results of its
166 # calculate_result_code
167 # - Should return a C code fragment evaluating to the
168 # result. This is only called when the result is not
171 # generate_assignment_code
172 # Called on the LHS of an assignment.
173 # - Call generate_evaluation_code for sub-expressions.
174 # - Generate code to perform the assignment.
175 # - If the assignment absorbed a reference, call
176 # generate_post_assignment_code on the RHS,
177 # otherwise call generate_disposal_code on it.
179 # generate_deletion_code
180 # Called on an argument of a del statement.
181 # - Call generate_evaluation_code for sub-expressions.
182 # - Generate code to perform the deletion.
183 # - Call generate_disposal_code on all sub-expressions.
187 is_sequence_constructor = 0
190 saved_subexpr_nodes = None
195 constant_result = constant_value_not_set
198 _get_child_attrs = operator.attrgetter('subexprs')
199 except AttributeError:
201 def _get_child_attrs(self):
203 child_attrs = property(fget=_get_child_attrs)
205 def not_implemented(self, method_name):
206 print_call_chain(method_name, "not implemented") ###
208 "%s.%s not implemented" %
209 (self.__class__.__name__, method_name))
214 def is_ephemeral(self):
215 # An ephemeral node is one whose result is in
216 # a Python temporary and we suspect there are no
217 # other references to it. Certain operations are
218 # disallowed on such values, since they are
219 # likely to result in a dangling pointer.
220 return self.type.is_pyobject and self.is_temp
222 def subexpr_nodes(self):
223 # Extract a list of subexpression nodes based
224 # on the contents of the subexprs class attribute.
226 for name in self.subexprs:
227 item = getattr(self, name)
229 if type(item) is list:
237 return self.temp_code
239 return self.calculate_result_code()
241 def result_as(self, type = None):
242 # Return the result code cast to the specified C type.
243 return typecast(type, self.ctype(), self.result())
246 # Return the result code cast to PyObject *.
247 return self.result_as(py_object_type)
250 # Return the native C type of the result (i.e. the
251 # C type of the result_code expression).
252 return self.result_ctype or self.type
254 def get_constant_c_result_code(self):
255 # Return the constant value of this node as a result code
256 # string, or None if the node is not constant. This method
257 # can be called when the constant result code is required
258 # before the code generation phase.
260 # The return value is a string that can represent a simple C
261 # value, a constant C name or a constant C expression. If the
262 # node type depends on Python code, this must return None.
265 def calculate_constant_result(self):
266 # Calculate the constant compile time result value of this
267 # expression and store it in ``self.constant_result``. Does
268 # nothing by default, thus leaving ``self.constant_result``
269 # unknown. If valid, the result can be an arbitrary Python
272 # This must only be called when it is assured that all
273 # sub-expressions have a valid constant_result value. The
274 # ConstantFolding transform will do this.
277 def has_constant_result(self):
278 return self.constant_result is not constant_value_not_set and \
279 self.constant_result is not not_a_constant
281 def compile_time_value(self, denv):
282 # Return value of compile-time expression, or report error.
283 error(self.pos, "Invalid compile-time expression")
285 def compile_time_value_error(self, e):
286 error(self.pos, "Error in compile-time expression: %s: %s" % (
287 e.__class__.__name__, e))
289 # ------------- Declaration Analysis ----------------
291 def analyse_target_declaration(self, env):
292 error(self.pos, "Cannot assign to or delete this")
294 # ------------- Expression Analysis ----------------
296 def analyse_const_expression(self, env):
297 # Called during the analyse_declarations phase of a
298 # constant expression. Analyses the expression's type,
299 # checks whether it is a legal const expression,
300 # and determines its value.
301 self.analyse_types(env)
302 return self.check_const()
304 def analyse_expressions(self, env):
305 # Convenience routine performing both the Type
306 # Analysis and Temp Allocation phases for a whole
308 self.analyse_types(env)
310 def analyse_target_expression(self, env, rhs):
311 # Convenience routine performing both the Type
312 # Analysis and Temp Allocation phases for the LHS of
314 self.analyse_target_types(env)
316 def analyse_boolean_expression(self, env):
317 # Analyse expression and coerce to a boolean.
318 self.analyse_types(env)
319 bool = self.coerce_to_boolean(env)
322 def analyse_temp_boolean_expression(self, env):
323 # Analyse boolean expression and coerce result into
324 # a temporary. This is used when a branch is to be
325 # performed on the result and we won't have an
326 # opportunity to ensure disposal code is executed
327 # afterwards. By forcing the result into a temporary,
328 # we ensure that all disposal has been done by the
329 # time we get the result.
330 self.analyse_types(env)
331 return self.coerce_to_boolean(env).coerce_to_simple(env)
333 # --------------- Type Inference -----------------
335 def type_dependencies(self, env):
336 # Returns the list of entries whose types must be determined
337 # before the type of self can be infered.
338 if hasattr(self, 'type') and self.type is not None:
340 return sum([node.type_dependencies(env) for node in self.subexpr_nodes()], ())
342 def infer_type(self, env):
343 # Attempt to deduce the type of self.
344 # Differs from analyse_types as it avoids unnecessary
345 # analysis of subexpressions, but can assume everything
346 # in self.type_dependencies() has been resolved.
347 if hasattr(self, 'type') and self.type is not None:
349 elif hasattr(self, 'entry') and self.entry is not None:
350 return self.entry.type
352 self.not_implemented("infer_type")
354 # --------------- Type Analysis ------------------
356 def analyse_as_module(self, env):
357 # If this node can be interpreted as a reference to a
358 # cimported module, return its scope, else None.
361 def analyse_as_type(self, env):
362 # If this node can be interpreted as a reference to a
363 # type, return that type, else None.
366 def analyse_as_extension_type(self, env):
367 # If this node can be interpreted as a reference to an
368 # extension type, return its type, else None.
371 def analyse_types(self, env):
372 self.not_implemented("analyse_types")
374 def analyse_target_types(self, env):
375 self.analyse_types(env)
377 def nogil_check(self, env):
378 # By default, any expression based on Python objects is
379 # prevented in nogil environments. Subtypes must override
380 # this if they can work without the GIL.
381 if self.type.is_pyobject:
384 def gil_assignment_check(self, env):
385 if env.nogil and self.type.is_pyobject:
386 error(self.pos, "Assignment of Python object not allowed without gil")
388 def check_const(self):
393 error(self.pos, "Not allowed in a constant expression")
395 def check_const_addr(self):
396 self.addr_not_const()
399 def addr_not_const(self):
400 error(self.pos, "Address is not constant")
402 # ----------------- Result Allocation -----------------
404 def result_in_temp(self):
405 # Return true if result is in a temporary owned by
406 # this node or one of its subexpressions. Overridden
407 # by certain nodes which can share the result of
411 def target_code(self):
412 # Return code fragment for use as LHS of a C assignment.
413 return self.calculate_result_code()
415 def calculate_result_code(self):
416 self.not_implemented("calculate_result_code")
418 # def release_target_temp(self, env):
419 # # Release temporaries used by LHS of an assignment.
420 # self.release_subexpr_temps(env)
422 def allocate_temp_result(self, code):
424 raise RuntimeError("Temp allocated multiple times in %r: %r" % (self.__class__.__name__, self.pos))
428 type = PyrexTypes.py_object_type
429 self.temp_code = code.funcstate.allocate_temp(
430 type, manage_ref=self.use_managed_ref)
432 self.temp_code = None
434 def release_temp_result(self, code):
435 if not self.temp_code:
437 raise RuntimeError("temp %s released multiple times in %s" % (
438 self.old_temp, self.__class__.__name__))
440 raise RuntimeError("no temp, but release requested in %s" % (
441 self.__class__.__name__))
442 code.funcstate.release_temp(self.temp_code)
443 self.old_temp = self.temp_code
444 self.temp_code = None
446 # ---------------- Code Generation -----------------
448 def make_owned_reference(self, code):
449 # If result is a pyobject, make sure we own
451 if self.type.is_pyobject and not self.result_in_temp():
452 code.put_incref(self.result(), self.ctype())
454 def generate_evaluation_code(self, code):
455 code.mark_pos(self.pos)
457 # Generate code to evaluate this node and
458 # its sub-expressions, and dispose of any
459 # temporary results of its sub-expressions.
460 self.generate_subexpr_evaluation_code(code)
463 self.allocate_temp_result(code)
465 self.generate_result_code(code)
467 # If we are temp we do not need to wait until this node is disposed
468 # before disposing children.
469 self.generate_subexpr_disposal_code(code)
470 self.free_subexpr_temps(code)
472 def generate_subexpr_evaluation_code(self, code):
473 for node in self.subexpr_nodes():
474 node.generate_evaluation_code(code)
476 def generate_result_code(self, code):
477 self.not_implemented("generate_result_code")
479 def generate_disposal_code(self, code):
481 if self.type.is_pyobject:
482 code.put_decref_clear(self.result(), self.ctype())
484 # Already done if self.is_temp
485 self.generate_subexpr_disposal_code(code)
487 def generate_subexpr_disposal_code(self, code):
488 # Generate code to dispose of temporary results
489 # of all sub-expressions.
490 for node in self.subexpr_nodes():
491 node.generate_disposal_code(code)
493 def generate_post_assignment_code(self, code):
495 if self.type.is_pyobject:
496 code.putln("%s = 0;" % self.result())
498 self.generate_subexpr_disposal_code(code)
500 def generate_assignment_code(self, rhs, code):
501 # Stub method for nodes which are not legal as
502 # the LHS of an assignment. An error will have
503 # been reported earlier.
506 def generate_deletion_code(self, code):
507 # Stub method for nodes that are not legal as
508 # the argument of a del statement. An error
509 # will have been reported earlier.
512 def free_temps(self, code):
514 if not self.type.is_void:
515 self.release_temp_result(code)
517 self.free_subexpr_temps(code)
519 def free_subexpr_temps(self, code):
520 for sub in self.subexpr_nodes():
523 def generate_function_definitions(self, env, code):
526 # ---------------- Annotation ---------------------
528 def annotate(self, code):
529 for node in self.subexpr_nodes():
532 # ----------------- Coercion ----------------------
534 def coerce_to(self, dst_type, env):
535 # Coerce the result so that it can be assigned to
536 # something of type dst_type. If processing is necessary,
537 # wraps this node in a coercion node and returns that.
538 # Otherwise, returns this node unchanged.
540 # This method is called during the analyse_expressions
541 # phase of the src_node's processing.
543 # Note that subclasses that override this (especially
544 # ConstNodes) must not (re-)set their own .type attribute
545 # here. Since expression nodes may turn up in different
546 # places in the tree (e.g. inside of CloneNodes in cascaded
547 # assignments), this method must return a new node instance
548 # if it changes the type.
552 src_is_py_type = src_type.is_pyobject
553 dst_is_py_type = dst_type.is_pyobject
555 if self.check_for_coercion_error(dst_type):
558 if dst_type.is_pyobject:
559 if not src.type.is_pyobject:
560 if dst_type is bytes_type and src.type.is_int:
561 src = CoerceIntToBytesNode(src, env)
563 src = CoerceToPyTypeNode(src, env)
564 if not src.type.subtype_of(dst_type):
565 if not isinstance(src, NoneNode):
566 src = PyTypeTestNode(src, dst_type, env)
567 elif src.type.is_pyobject:
568 src = CoerceFromPyTypeNode(dst_type, src, env)
569 elif (dst_type.is_complex
570 and src_type != dst_type
571 and dst_type.assignable_from(src_type)):
572 src = CoerceToComplexNode(src, dst_type, env)
573 else: # neither src nor dst are py types
574 # Added the string comparison, since for c types that
575 # is enough, but Cython gets confused when the types are
576 # in different pxi files.
577 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
578 self.fail_assignment(dst_type)
581 def fail_assignment(self, dst_type):
582 error(self.pos, "Cannot assign type '%s' to '%s'" % (self.type, dst_type))
584 def check_for_coercion_error(self, dst_type, fail=False, default=None):
585 if fail and not default:
586 default = "Cannot assign type '%(FROM)s' to '%(TO)s'"
587 message = find_coercion_error((self.type, dst_type), default)
588 if message is not None:
589 error(self.pos, message % {'FROM': self.type, 'TO': dst_type})
592 self.fail_assignment(dst_type)
596 def coerce_to_pyobject(self, env):
597 return self.coerce_to(PyrexTypes.py_object_type, env)
599 def coerce_to_boolean(self, env):
600 # Coerce result to something acceptable as
603 # if it's constant, calculate the result now
604 if self.has_constant_result():
605 bool_value = bool(self.constant_result)
606 return BoolNode(self.pos, value=bool_value,
607 constant_result=bool_value)
610 if type.is_pyobject or type.is_ptr or type.is_float:
611 return CoerceToBooleanNode(self, env)
613 if not (type.is_int or type.is_enum or type.is_error):
615 "Type '%s' not acceptable as a boolean" % type)
618 def coerce_to_integer(self, env):
619 # If not already some C integer type, coerce to longint.
623 return self.coerce_to(PyrexTypes.c_long_type, env)
625 def coerce_to_temp(self, env):
626 # Ensure that the result is in a temporary.
627 if self.result_in_temp():
630 return CoerceToTempNode(self, env)
632 def coerce_to_simple(self, env):
633 # Ensure that the result is simple (see is_simple).
637 return self.coerce_to_temp(env)
640 # A node is simple if its result is something that can
641 # be referred to without performing any operations, e.g.
642 # a constant, local var, C global var, struct member
643 # reference, or temporary.
644 return self.result_in_temp()
646 def may_be_none(self):
647 return self.type.is_pyobject
649 def as_cython_attribute(self):
652 def as_none_safe_node(self, message, error="PyExc_TypeError"):
653 # Wraps the node in a NoneCheckNode if it is not known to be
654 # not-None (e.g. because it is a Python literal).
655 if self.may_be_none():
656 return NoneCheckNode(self, error, message)
661 class AtomicExprNode(ExprNode):
662 # Abstract base class for expression nodes which have
663 # no sub-expressions.
667 # Override to optimize -- we know we have no children
668 def generate_subexpr_evaluation_code(self, code):
670 def generate_subexpr_disposal_code(self, code):
673 class PyConstNode(AtomicExprNode):
674 # Abstract base class for constant Python values.
677 type = py_object_type
682 def may_be_none(self):
685 def analyse_types(self, env):
688 def calculate_result_code(self):
691 def generate_result_code(self, code):
695 class NoneNode(PyConstNode):
696 # The constant value None
700 constant_result = None
704 def compile_time_value(self, denv):
707 def may_be_none(self):
711 class EllipsisNode(PyConstNode):
712 # '...' in a subscript list.
714 value = "Py_Ellipsis"
716 constant_result = Ellipsis
718 def compile_time_value(self, denv):
722 class ConstNode(AtomicExprNode):
723 # Abstract base type for literal constant nodes.
725 # value string C code fragment
733 def may_be_none(self):
736 def analyse_types(self, env):
737 pass # Types are held in class variables
739 def check_const(self):
742 def get_constant_c_result_code(self):
743 return self.calculate_result_code()
745 def calculate_result_code(self):
746 return str(self.value)
748 def generate_result_code(self, code):
752 class BoolNode(ConstNode):
753 type = PyrexTypes.c_bint_type
754 # The constant value True or False
756 def calculate_constant_result(self):
757 self.constant_result = self.value
759 def compile_time_value(self, denv):
762 def calculate_result_code(self):
763 return str(int(self.value))
766 class NullNode(ConstNode):
767 type = PyrexTypes.c_null_ptr_type
771 def get_constant_c_result_code(self):
775 class CharNode(ConstNode):
776 type = PyrexTypes.c_char_type
778 def calculate_constant_result(self):
779 self.constant_result = ord(self.value)
781 def compile_time_value(self, denv):
782 return ord(self.value)
784 def calculate_result_code(self):
785 return "'%s'" % StringEncoding.escape_char(self.value)
788 class IntNode(ConstNode):
791 # longness "" or "L" or "LL"
795 type = PyrexTypes.c_long_type
797 def coerce_to(self, dst_type, env):
798 if self.type is dst_type:
800 node = IntNode(self.pos, value=self.value,
801 unsigned=self.unsigned, longness=self.longness)
802 if dst_type.is_numeric and not dst_type.is_complex:
804 if dst_type.is_pyobject:
805 node.type = PyrexTypes.py_object_type
806 # We still need to perform normal coerce_to processing on the
807 # result, because we might be coercing to an extension type,
808 # in which case a type test node will be needed.
809 return ConstNode.coerce_to(node, dst_type, env)
811 def coerce_to_boolean(self, env):
813 self.pos, value=self.value,
814 type = PyrexTypes.c_bint_type,
815 unsigned=self.unsigned, longness=self.longness)
817 def generate_evaluation_code(self, code):
818 if self.type.is_pyobject:
819 # pre-allocate a Python version of the number
820 self.result_code = code.get_py_num(self.value, self.longness)
822 self.result_code = self.get_constant_c_result_code()
824 def get_constant_c_result_code(self):
826 if isinstance(value, basestring) and len(value) > 2:
827 # must convert C-incompatible Py3 oct/bin notations
829 value = value[0] + value[2:] # '0o123' => '0123'
830 elif value[1] in 'bB':
831 value = int(value[2:], 2)
832 return str(value) + self.unsigned + self.longness
834 def calculate_result_code(self):
835 return self.result_code
837 def calculate_constant_result(self):
838 self.constant_result = Utils.str_to_number(self.value)
840 def compile_time_value(self, denv):
841 return Utils.str_to_number(self.value)
844 class FloatNode(ConstNode):
845 type = PyrexTypes.c_double_type
847 def calculate_constant_result(self):
848 self.constant_result = float(self.value)
850 def compile_time_value(self, denv):
851 return float(self.value)
853 def calculate_result_code(self):
855 assert isinstance(strval, (str, unicode))
856 cmpval = repr(float(strval))
858 return "(Py_HUGE_VAL * 0)"
859 elif cmpval == 'inf':
861 elif cmpval == '-inf':
862 return "(-Py_HUGE_VAL)"
867 class BytesNode(ConstNode):
868 # A char* or bytes literal
872 type = PyrexTypes.c_char_ptr_type
874 def compile_time_value(self, denv):
877 def analyse_as_type(self, env):
878 type = PyrexTypes.parse_basic_type(self.value)
881 from TreeFragment import TreeFragment
882 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
883 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
884 sizeof_node = declaration.root.stats[0].expr
885 sizeof_node.analyse_types(env)
886 if isinstance(sizeof_node, SizeofTypeNode):
887 return sizeof_node.arg_type
889 def can_coerce_to_char_literal(self):
890 return len(self.value) == 1
892 def coerce_to_boolean(self, env):
893 # This is special because we start off as a C char*. Testing
894 # that for truth directly would yield the wrong result.
895 return BoolNode(self.pos, value=bool(self.value))
897 def coerce_to(self, dst_type, env):
899 if not self.can_coerce_to_char_literal():
900 error(self.pos, "Only single-character string literals can be coerced into ints.")
902 if dst_type is PyrexTypes.c_py_unicode_type:
903 error(self.pos, "Bytes literals cannot coerce to Py_UNICODE, use a unicode literal instead.")
905 return CharNode(self.pos, value=self.value)
907 node = BytesNode(self.pos, value=self.value)
908 if dst_type == PyrexTypes.c_char_ptr_type:
909 node.type = PyrexTypes.c_char_ptr_type
911 elif dst_type == PyrexTypes.c_uchar_ptr_type:
912 node.type = PyrexTypes.c_char_ptr_type
913 return CastNode(node, PyrexTypes.c_uchar_ptr_type)
915 if not self.type.is_pyobject:
916 if dst_type in (py_object_type, Builtin.bytes_type):
917 node.type = Builtin.bytes_type
918 elif dst_type.is_pyobject:
919 self.fail_assignment(dst_type)
921 elif dst_type.is_pyobject and dst_type is not py_object_type:
922 self.check_for_coercion_error(dst_type, fail=True)
925 # We still need to perform normal coerce_to processing on the
926 # result, because we might be coercing to an extension type,
927 # in which case a type test node will be needed.
928 return ConstNode.coerce_to(node, dst_type, env)
930 def as_py_string_node(self, env):
931 # Return a new BytesNode with the same value as this node
932 # but whose type is a Python type instead of a C type.
933 return BytesNode(self.pos, value = self.value, type = Builtin.bytes_type)
935 def generate_evaluation_code(self, code):
936 if self.type.is_pyobject:
937 self.result_code = code.get_py_string_const(self.value)
939 self.result_code = code.get_string_const(self.value)
941 def get_constant_c_result_code(self):
944 def calculate_result_code(self):
945 return self.result_code
948 class UnicodeNode(PyConstNode):
949 # A Python unicode object
951 # value EncodedString
955 def coerce_to(self, dst_type, env):
956 if dst_type is self.type:
958 elif dst_type is PyrexTypes.c_py_unicode_type:
959 if not self.can_coerce_to_char_literal():
960 error(self.pos, "Only single-character Unicode string literals can be coerced into Py_UNICODE.")
962 int_value = ord(self.value)
963 return IntNode(self.pos, value=int_value, constant_result=int_value)
964 elif not dst_type.is_pyobject:
965 error(self.pos, "Unicode literals do not support coercion to C types other than Py_UNICODE.")
966 elif dst_type is not py_object_type:
967 if not self.check_for_coercion_error(dst_type):
968 self.fail_assignment(dst_type)
971 def can_coerce_to_char_literal(self):
972 return len(self.value) == 1
974 def generate_evaluation_code(self, code):
975 self.result_code = code.get_py_string_const(self.value)
977 def calculate_result_code(self):
978 return self.result_code
980 def compile_time_value(self, env):
984 class StringNode(PyConstNode):
985 # A Python str object, i.e. a byte string in Python 2.x and a
986 # unicode string in Python 3.x
988 # value BytesLiteral or EncodedString
989 # is_identifier boolean
994 def coerce_to(self, dst_type, env):
995 if dst_type is not py_object_type and not str_type.subtype_of(dst_type):
996 # if dst_type is Builtin.bytes_type:
997 # # special case: bytes = 'str literal'
998 # return BytesNode(self.pos, value=self.value)
999 if not dst_type.is_pyobject:
1000 return BytesNode(self.pos, value=self.value).coerce_to(dst_type, env)
1001 self.check_for_coercion_error(dst_type, fail=True)
1003 # this will be a unicode string in Py3, so make sure we can decode it
1004 if self.value.encoding:
1005 encoding = self.value.encoding
1007 self.value.decode(encoding)
1008 except UnicodeDecodeError:
1009 error(self.pos, "String decoding as '%s' failed. Consider using a byte string or unicode string explicitly, or adjust the source code encoding." % encoding)
1013 def can_coerce_to_char_literal(self):
1014 return not self.is_identifier and len(self.value) == 1
1016 def generate_evaluation_code(self, code):
1017 self.result_code = code.get_py_string_const(
1018 self.value, identifier=self.is_identifier, is_str=True)
1020 def get_constant_c_result_code(self):
1023 def calculate_result_code(self):
1024 return self.result_code
1026 def compile_time_value(self, env):
1030 class IdentifierStringNode(StringNode):
1031 # A special str value that represents an identifier (bytes in Py2,
1033 is_identifier = True
1036 class LongNode(AtomicExprNode):
1037 # Python long integer literal
1041 type = py_object_type
1043 def calculate_constant_result(self):
1044 self.constant_result = Utils.str_to_number(self.value)
1046 def compile_time_value(self, denv):
1047 return Utils.str_to_number(self.value)
1049 def analyse_types(self, env):
1052 def may_be_none(self):
1055 gil_message = "Constructing Python long int"
1057 def generate_result_code(self, code):
1059 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
1062 code.error_goto_if_null(self.result(), self.pos)))
1063 code.put_gotref(self.py_result())
1066 class ImagNode(AtomicExprNode):
1067 # Imaginary number literal
1069 # value float imaginary part
1071 type = PyrexTypes.c_double_complex_type
1073 def calculate_constant_result(self):
1074 self.constant_result = complex(0.0, self.value)
1076 def compile_time_value(self, denv):
1077 return complex(0.0, self.value)
1079 def analyse_types(self, env):
1080 self.type.create_declaration_utility_code(env)
1082 def may_be_none(self):
1085 def coerce_to(self, dst_type, env):
1086 if self.type is dst_type:
1088 node = ImagNode(self.pos, value=self.value)
1089 if dst_type.is_pyobject:
1091 node.type = PyrexTypes.py_object_type
1092 # We still need to perform normal coerce_to processing on the
1093 # result, because we might be coercing to an extension type,
1094 # in which case a type test node will be needed.
1095 return AtomicExprNode.coerce_to(node, dst_type, env)
1097 gil_message = "Constructing complex number"
1099 def calculate_result_code(self):
1100 if self.type.is_pyobject:
1101 return self.result()
1103 return "%s(0, %r)" % (self.type.from_parts, float(self.value))
1105 def generate_result_code(self, code):
1106 if self.type.is_pyobject:
1108 "%s = PyComplex_FromDoubles(0.0, %r); %s" % (
1111 code.error_goto_if_null(self.result(), self.pos)))
1112 code.put_gotref(self.py_result())
1115 class NewExprNode(AtomicExprNode):
1119 # cppclass node c++ class to create
1123 def infer_type(self, env):
1124 type = self.cppclass.analyse_as_type(env)
1125 if type is None or not type.is_cpp_class:
1126 error(self.pos, "new operator can only be applied to a C++ class")
1127 self.type = error_type
1130 constructor = type.scope.lookup(u'<init>')
1131 if constructor is None:
1132 return_type = PyrexTypes.CFuncType(type, [])
1133 return_type = PyrexTypes.CPtrType(return_type)
1134 type.scope.declare_cfunction(u'<init>', return_type, self.pos)
1135 constructor = type.scope.lookup(u'<init>')
1136 self.class_type = type
1137 self.entry = constructor
1138 self.type = constructor.type
1141 def analyse_types(self, env):
1142 if self.type is None:
1143 self.infer_type(env)
1145 def may_be_none(self):
1148 def generate_result_code(self, code):
1151 def calculate_result_code(self):
1152 return "new " + self.class_type.declaration_code("")
1155 class NameNode(AtomicExprNode):
1156 # Reference to a local or global variable name.
1158 # name string Python name of the variable
1159 # entry Entry Symbol table entry
1160 # type_entry Entry For extension type names, the original type entry
1163 is_cython_module = False
1164 cython_attribute = None
1165 lhs_of_first_assignment = False
1166 is_used_as_rvalue = 0
1170 def create_analysed_rvalue(pos, env, entry):
1171 node = NameNode(pos)
1172 node.analyse_types(env, entry=entry)
1175 def as_cython_attribute(self):
1176 return self.cython_attribute
1178 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
1180 def type_dependencies(self, env):
1181 if self.entry is None:
1182 self.entry = env.lookup(self.name)
1183 if self.entry is not None and self.entry.type.is_unspecified:
1184 return (self.entry,)
1188 def infer_type(self, env):
1189 if self.entry is None:
1190 self.entry = env.lookup(self.name)
1191 if self.entry is None:
1192 return py_object_type
1193 elif (self.entry.type.is_extension_type or self.entry.type.is_builtin_type) and \
1194 self.name == self.entry.type.name:
1195 # Unfortunately the type attribute of type objects
1196 # is used for the pointer to the type they represent.
1199 return self.entry.type
1201 def compile_time_value(self, denv):
1203 return denv.lookup(self.name)
1205 error(self.pos, "Compile-time name '%s' not defined" % self.name)
1207 def get_constant_c_result_code(self):
1208 if not self.entry or self.entry.type.is_pyobject:
1210 return self.entry.cname
1212 def coerce_to(self, dst_type, env):
1213 # If coercing to a generic pyobject and this is a builtin
1214 # C function with a Python equivalent, manufacture a NameNode
1215 # referring to the Python builtin.
1216 #print "NameNode.coerce_to:", self.name, dst_type ###
1217 if dst_type is py_object_type:
1219 if entry and entry.is_cfunction:
1220 var_entry = entry.as_variable
1222 if var_entry.is_builtin and Options.cache_builtins:
1223 var_entry = env.declare_builtin(var_entry.name, self.pos)
1224 node = NameNode(self.pos, name = self.name)
1225 node.entry = var_entry
1226 node.analyse_rvalue_entry(env)
1228 return super(NameNode, self).coerce_to(dst_type, env)
1230 def analyse_as_module(self, env):
1231 # Try to interpret this as a reference to a cimported module.
1232 # Returns the module scope, or None.
1235 entry = env.lookup(self.name)
1236 if entry and entry.as_module:
1237 return entry.as_module
1240 def analyse_as_type(self, env):
1241 if self.cython_attribute:
1242 type = PyrexTypes.parse_basic_type(self.cython_attribute)
1244 type = PyrexTypes.parse_basic_type(self.name)
1249 entry = env.lookup(self.name)
1250 if entry and entry.is_type:
1255 def analyse_as_extension_type(self, env):
1256 # Try to interpret this as a reference to an extension type.
1257 # Returns the extension type, or None.
1260 entry = env.lookup(self.name)
1261 if entry and entry.is_type and entry.type.is_extension_type:
1266 def analyse_target_declaration(self, env):
1268 self.entry = env.lookup_here(self.name)
1270 if env.directives['warn.undeclared']:
1271 warning(self.pos, "implicit declaration of '%s'" % self.name, 1)
1272 if env.directives['infer_types'] != False:
1273 type = unspecified_type
1275 type = py_object_type
1276 self.entry = env.declare_var(self.name, type, self.pos)
1277 env.control_flow.set_state(self.pos, (self.name, 'initialized'), True)
1278 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1279 if self.entry.is_declared_generic:
1280 self.result_ctype = py_object_type
1282 def analyse_types(self, env):
1283 if self.entry is None:
1284 self.entry = env.lookup(self.name)
1286 self.entry = env.declare_builtin(self.name, self.pos)
1288 self.type = PyrexTypes.error_type
1293 if entry.type.is_buffer:
1295 Buffer.used_buffer_aux_vars(entry)
1296 if entry.utility_code:
1297 env.use_utility_code(entry.utility_code)
1298 self.analyse_rvalue_entry(env)
1300 def analyse_target_types(self, env):
1301 self.analyse_entry(env)
1302 if not self.is_lvalue():
1303 error(self.pos, "Assignment to non-lvalue '%s'"
1305 self.type = PyrexTypes.error_type
1307 if self.entry.type.is_buffer:
1309 Buffer.used_buffer_aux_vars(self.entry)
1311 def analyse_rvalue_entry(self, env):
1312 #print "NameNode.analyse_rvalue_entry:", self.name ###
1313 #print "Entry:", self.entry.__dict__ ###
1314 self.analyse_entry(env)
1316 if entry.is_declared_generic:
1317 self.result_ctype = py_object_type
1318 if entry.is_pyglobal or entry.is_builtin:
1319 if Options.cache_builtins and entry.is_builtin:
1323 env.use_utility_code(get_name_interned_utility_code)
1324 self.is_used_as_rvalue = 1
1326 def nogil_check(self, env):
1327 if self.is_used_as_rvalue:
1329 if entry.is_builtin:
1330 # if not Options.cache_builtins: # cached builtins are ok
1332 elif entry.is_pyglobal:
1335 gil_message = "Accessing Python global or builtin"
1337 def analyse_entry(self, env):
1338 #print "NameNode.analyse_entry:", self.name ###
1339 self.check_identifier_kind()
1344 def check_identifier_kind(self):
1345 # Check that this is an appropriate kind of name for use in an
1346 # expression. Also finds the variable entry associated with
1347 # an extension type.
1349 if entry.is_type and entry.type.is_extension_type:
1350 self.type_entry = entry
1351 if not (entry.is_const or entry.is_variable
1352 or entry.is_builtin or entry.is_cfunction
1353 or entry.is_cpp_class):
1354 if self.entry.as_variable:
1355 self.entry = self.entry.as_variable
1358 "'%s' is not a constant, variable or function identifier" % self.name)
1360 def is_simple(self):
1361 # If it's not a C variable, it'll be in a temp.
1364 def calculate_target_results(self, env):
1367 def check_const(self):
1369 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1374 def check_const_addr(self):
1376 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1377 self.addr_not_const()
1381 def is_lvalue(self):
1382 return self.entry.is_variable and \
1383 not self.entry.type.is_array and \
1384 not self.entry.is_readonly
1386 def is_ephemeral(self):
1387 # Name nodes are never ephemeral, even if the
1388 # result is in a temporary.
1391 def calculate_result_code(self):
1394 return "<error>" # There was an error earlier
1397 def generate_result_code(self, code):
1398 assert hasattr(self, 'entry')
1401 return # There was an error earlier
1402 if entry.is_builtin and Options.cache_builtins:
1403 return # Lookup already cached
1404 elif entry.is_pyglobal or entry.is_builtin:
1405 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1406 interned_cname = code.intern_identifier(self.entry.name)
1407 if entry.is_builtin:
1408 namespace = Naming.builtins_cname
1409 else: # entry.is_pyglobal
1410 namespace = entry.scope.namespace_cname
1411 code.globalstate.use_utility_code(get_name_interned_utility_code)
1413 '%s = __Pyx_GetName(%s, %s); %s' % (
1417 code.error_goto_if_null(self.result(), self.pos)))
1418 code.put_gotref(self.py_result())
1420 elif entry.is_local and False:
1421 # control flow not good enough yet
1422 assigned = entry.scope.control_flow.get_state((entry.name, 'initialized'), self.pos)
1423 if assigned is False:
1424 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1425 elif not Options.init_local_none and assigned is None:
1426 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
1427 (entry.cname, entry.name, code.error_goto(self.pos)))
1428 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initialized'), True)
1430 def generate_assignment_code(self, rhs, code):
1431 #print "NameNode.generate_assignment_code:", self.name ###
1434 return # There was an error earlier
1436 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1437 and not self.lhs_of_first_assignment):
1438 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1440 # is_pyglobal seems to be True for module level-globals only.
1441 # We use this to access class->tp_dict if necessary.
1442 if entry.is_pyglobal:
1443 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1444 interned_cname = code.intern_identifier(self.entry.name)
1445 namespace = self.entry.scope.namespace_cname
1447 # if the entry is a member we have to cheat: SetAttr does not work
1448 # on types, so we create a descriptor which is then added to tp_dict
1449 code.put_error_if_neg(self.pos,
1450 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1454 rhs.generate_disposal_code(code)
1455 rhs.free_temps(code)
1456 # in Py2.6+, we need to invalidate the method cache
1457 code.putln("PyType_Modified(%s);" %
1458 entry.scope.parent_type.typeptr_cname)
1460 code.put_error_if_neg(self.pos,
1461 'PyObject_SetAttr(%s, %s, %s)' % (
1465 if debug_disposal_code:
1466 print("NameNode.generate_assignment_code:")
1467 print("...generating disposal code for %s" % rhs)
1468 rhs.generate_disposal_code(code)
1469 rhs.free_temps(code)
1471 if self.type.is_buffer:
1472 # Generate code for doing the buffer release/acquisition.
1473 # This might raise an exception in which case the assignment (done
1474 # below) will not happen.
1476 # The reason this is not in a typetest-like node is because the
1477 # variables that the acquired buffer info is stored to is allocated
1478 # per entry and coupled with it.
1479 self.generate_acquire_buffer(rhs, code)
1481 if self.type.is_pyobject:
1482 #print "NameNode.generate_assignment_code: to", self.name ###
1483 #print "...from", rhs ###
1484 #print "...LHS type", self.type, "ctype", self.ctype() ###
1485 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1486 if self.use_managed_ref:
1487 rhs.make_owned_reference(code)
1488 if entry.is_cglobal:
1489 code.put_gotref(self.py_result())
1490 if not self.lhs_of_first_assignment:
1491 if entry.is_local and not Options.init_local_none:
1492 initialized = entry.scope.control_flow.get_state((entry.name, 'initialized'), self.pos)
1493 if initialized is True:
1494 code.put_decref(self.result(), self.ctype())
1495 elif initialized is None:
1496 code.put_xdecref(self.result(), self.ctype())
1498 code.put_decref(self.result(), self.ctype())
1499 if entry.is_cglobal:
1500 code.put_giveref(rhs.py_result())
1502 code.putln('%s = %s;' % (self.result(),
1503 rhs.result_as(self.ctype())))
1504 if debug_disposal_code:
1505 print("NameNode.generate_assignment_code:")
1506 print("...generating post-assignment code for %s" % rhs)
1507 rhs.generate_post_assignment_code(code)
1508 rhs.free_temps(code)
1510 def generate_acquire_buffer(self, rhs, code):
1511 # rhstmp is only used in case the rhs is a complicated expression leading to
1512 # the object, to avoid repeating the same C expression for every reference
1513 # to the rhs. It does NOT hold a reference.
1514 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1516 rhstmp = rhs.result_as(self.ctype())
1518 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1519 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1521 buffer_aux = self.entry.buffer_aux
1522 bufstruct = buffer_aux.buffer_info_var.cname
1524 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1525 is_initialized=not self.lhs_of_first_assignment,
1526 pos=self.pos, code=code)
1529 code.putln("%s = 0;" % rhstmp)
1530 code.funcstate.release_temp(rhstmp)
1532 def generate_deletion_code(self, code):
1533 if self.entry is None:
1534 return # There was an error earlier
1535 if not self.entry.is_pyglobal:
1536 error(self.pos, "Deletion of local or C global name not supported")
1538 code.put_error_if_neg(self.pos,
1539 '__Pyx_DelAttrString(%s, "%s")' % (
1540 Naming.module_cname,
1543 def annotate(self, code):
1544 if hasattr(self, 'is_called') and self.is_called:
1545 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1546 if self.type.is_pyobject:
1547 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1549 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1551 class BackquoteNode(ExprNode):
1556 type = py_object_type
1560 def analyse_types(self, env):
1561 self.arg.analyse_types(env)
1562 self.arg = self.arg.coerce_to_pyobject(env)
1565 gil_message = "Backquote expression"
1567 def calculate_constant_result(self):
1568 self.constant_result = repr(self.arg.constant_result)
1570 def generate_result_code(self, code):
1572 "%s = PyObject_Repr(%s); %s" % (
1574 self.arg.py_result(),
1575 code.error_goto_if_null(self.result(), self.pos)))
1576 code.put_gotref(self.py_result())
1580 class ImportNode(ExprNode):
1581 # Used as part of import statement implementation.
1582 # Implements result =
1583 # __import__(module_name, globals(), None, name_list)
1585 # module_name StringNode dotted name of module
1586 # name_list ListNode or None list of names to be imported
1588 type = py_object_type
1590 subexprs = ['module_name', 'name_list']
1592 def analyse_types(self, env):
1593 self.module_name.analyse_types(env)
1594 self.module_name = self.module_name.coerce_to_pyobject(env)
1596 self.name_list.analyse_types(env)
1597 self.name_list.coerce_to_pyobject(env)
1599 env.use_utility_code(import_utility_code)
1601 gil_message = "Python import"
1603 def generate_result_code(self, code):
1605 name_list_code = self.name_list.py_result()
1607 name_list_code = "0"
1609 "%s = __Pyx_Import(%s, %s); %s" % (
1611 self.module_name.py_result(),
1613 code.error_goto_if_null(self.result(), self.pos)))
1614 code.put_gotref(self.py_result())
1617 class IteratorNode(ExprNode):
1618 # Used as part of for statement implementation.
1620 # allocate_counter_temp/release_counter_temp needs to be called
1621 # by parent (ForInStatNode)
1623 # Implements result = iter(sequence)
1627 type = py_object_type
1629 subexprs = ['sequence']
1631 def analyse_types(self, env):
1632 self.sequence.analyse_types(env)
1633 if isinstance(self.sequence, SliceIndexNode) and \
1634 (self.sequence.base.type.is_array or self.sequence.base.type.is_ptr) \
1635 or self.sequence.type.is_array and self.sequence.type.size is not None:
1636 # C array iteration will be transformed later on
1639 self.sequence = self.sequence.coerce_to_pyobject(env)
1642 gil_message = "Iterating over Python object"
1644 def allocate_counter_temp(self, code):
1645 self.counter_cname = code.funcstate.allocate_temp(
1646 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1648 def release_counter_temp(self, code):
1649 code.funcstate.release_temp(self.counter_cname)
1651 def generate_result_code(self, code):
1652 is_builtin_sequence = self.sequence.type is list_type or \
1653 self.sequence.type is tuple_type
1654 may_be_a_sequence = is_builtin_sequence or not self.sequence.type.is_builtin_type
1655 if is_builtin_sequence:
1657 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1658 elif may_be_a_sequence:
1660 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1661 self.sequence.py_result(),
1662 self.sequence.py_result()))
1663 if may_be_a_sequence:
1665 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
1668 self.sequence.py_result(),
1670 code.putln("} else {")
1671 if is_builtin_sequence:
1673 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1674 code.error_goto(self.pos))
1676 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1679 self.sequence.py_result(),
1680 code.error_goto_if_null(self.result(), self.pos)))
1681 code.put_gotref(self.py_result())
1682 if may_be_a_sequence:
1686 class NextNode(AtomicExprNode):
1687 # Used as part of for statement implementation.
1688 # Implements result = iterator.next()
1689 # Created during analyse_types phase.
1690 # The iterator is not owned by this node.
1694 type = py_object_type
1696 def __init__(self, iterator, env):
1697 self.pos = iterator.pos
1698 self.iterator = iterator
1701 def generate_result_code(self, code):
1702 sequence_type = self.iterator.sequence.type
1703 if sequence_type is list_type:
1704 type_checks = [(list_type, "List")]
1705 elif sequence_type is tuple_type:
1706 type_checks = [(tuple_type, "Tuple")]
1707 elif not sequence_type.is_builtin_type:
1708 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1712 for py_type, prefix in type_checks:
1713 if len(type_checks) > 1:
1715 "if (likely(Py%s_CheckExact(%s))) {" % (
1716 prefix, self.iterator.py_result()))
1718 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1719 self.iterator.counter_cname,
1721 self.iterator.py_result()))
1723 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1726 self.iterator.py_result(),
1727 self.iterator.counter_cname,
1729 self.iterator.counter_cname))
1730 if len(type_checks) > 1:
1732 if len(type_checks) == 1:
1736 "%s = PyIter_Next(%s);" % (
1738 self.iterator.py_result()))
1742 code.putln(code.error_goto_if_PyErr(self.pos))
1743 code.putln("break;")
1745 code.put_gotref(self.py_result())
1749 class ExcValueNode(AtomicExprNode):
1750 # Node created during analyse_types phase
1751 # of an ExceptClauseNode to fetch the current
1754 type = py_object_type
1756 def __init__(self, pos, env):
1757 ExprNode.__init__(self, pos)
1759 def set_var(self, var):
1762 def calculate_result_code(self):
1765 def generate_result_code(self, code):
1768 def analyse_types(self, env):
1772 class TempNode(ExprNode):
1773 # Node created during analyse_types phase
1774 # of some nodes to hold a temporary value.
1776 # Note: One must call "allocate" and "release" on
1777 # the node during code generation to get/release the temp.
1778 # This is because the temp result is often used outside of
1779 # the regular cycle.
1783 def __init__(self, pos, type, env):
1784 ExprNode.__init__(self, pos)
1786 if type.is_pyobject:
1787 self.result_ctype = py_object_type
1790 def analyse_types(self, env):
1793 def generate_result_code(self, code):
1796 def allocate(self, code):
1797 self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=True)
1799 def release(self, code):
1800 code.funcstate.release_temp(self.temp_cname)
1801 self.temp_cname = None
1805 return self.temp_cname
1807 assert False, "Remember to call allocate/release on TempNode"
1810 # Do not participate in normal temp alloc/dealloc:
1811 def allocate_temp_result(self, code):
1814 def release_temp_result(self, code):
1817 class PyTempNode(TempNode):
1818 # TempNode holding a Python value.
1820 def __init__(self, pos, env):
1821 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1823 class RawCNameExprNode(ExprNode):
1826 def __init__(self, pos, type=None):
1830 def analyse_types(self, env):
1833 def set_cname(self, cname):
1839 def generate_result_code(self, code):
1843 #-------------------------------------------------------------------
1847 #-------------------------------------------------------------------
1849 class IndexNode(ExprNode):
1850 # Sequence indexing.
1854 # indices [ExprNode]
1855 # is_buffer_access boolean Whether this is a buffer access.
1857 # indices is used on buffer access, index on non-buffer access.
1858 # The former contains a clean list of index parameters, the
1859 # latter whatever Python object is needed for index access.
1861 subexprs = ['base', 'index', 'indices']
1864 def __init__(self, pos, index, *args, **kw):
1865 ExprNode.__init__(self, pos, index=index, *args, **kw)
1868 def calculate_constant_result(self):
1869 self.constant_result = \
1870 self.base.constant_result[self.index.constant_result]
1872 def compile_time_value(self, denv):
1873 base = self.base.compile_time_value(denv)
1874 index = self.index.compile_time_value(denv)
1877 except Exception, e:
1878 self.compile_time_value_error(e)
1880 def is_ephemeral(self):
1881 return self.base.is_ephemeral()
1883 def analyse_target_declaration(self, env):
1886 def analyse_as_type(self, env):
1887 base_type = self.base.analyse_as_type(env)
1888 if base_type and not base_type.is_pyobject:
1889 if base_type.is_cpp_class:
1890 if isinstance(self.index, TupleNode):
1891 template_values = self.index.args
1893 template_values = [self.index]
1895 type_node = Nodes.TemplatedTypeNode(
1897 positional_args = template_values,
1898 keyword_args = None)
1899 return type_node.analyse(env, base_type = base_type)
1901 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1904 def type_dependencies(self, env):
1905 return self.base.type_dependencies(env)
1907 def infer_type(self, env):
1908 if isinstance(self.base, BytesNode):
1909 return py_object_type
1910 base_type = self.base.infer_type(env)
1911 if base_type.is_ptr or base_type.is_array:
1912 return base_type.base_type
1913 elif base_type is unicode_type and self.index.infer_type(env).is_int:
1914 # Py_UNICODE will automatically coerce to a unicode string
1915 # if required, so this is safe. We only infer Py_UNICODE
1916 # when the index is a C integer type. Otherwise, we may
1917 # need to use normal Python item access, in which case
1918 # it's faster to return the one-char unicode string than
1919 # to receive it, throw it away, and potentially rebuild it
1920 # on a subsequent PyObject coercion.
1921 return PyrexTypes.c_py_unicode_type
1922 elif base_type in (str_type, unicode_type):
1923 # these types will always return themselves on Python indexing
1926 # TODO: Handle buffers (hopefully without too much redundancy).
1927 return py_object_type
1929 def analyse_types(self, env):
1930 self.analyse_base_and_index_types(env, getting = 1)
1932 def analyse_target_types(self, env):
1933 self.analyse_base_and_index_types(env, setting = 1)
1935 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1936 # Note: This might be cleaned up by having IndexNode
1937 # parsed in a saner way and only construct the tuple if
1940 # Note that this function must leave IndexNode in a cloneable state.
1941 # For buffers, self.index is packed out on the initial analysis, and
1942 # when cloning self.indices is copied.
1943 self.is_buffer_access = False
1945 self.base.analyse_types(env)
1946 if self.base.type.is_error:
1947 # Do not visit child tree if base is undeclared to avoid confusing
1949 self.type = PyrexTypes.error_type
1952 # Handle the case where base is a literal char* (and we expect a string, not an int)
1953 if isinstance(self.base, BytesNode):
1954 self.base = self.base.coerce_to_pyobject(env)
1956 skip_child_analysis = False
1957 buffer_access = False
1958 if self.base.type.is_buffer:
1959 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1961 indices = self.indices
1963 if isinstance(self.index, TupleNode):
1964 indices = self.index.args
1966 indices = [self.index]
1967 if len(indices) == self.base.type.ndim:
1968 buffer_access = True
1969 skip_child_analysis = True
1971 x.analyse_types(env)
1972 if not x.type.is_int:
1973 buffer_access = False
1975 # On cloning, indices is cloned. Otherwise, unpack index into indices
1976 assert not (buffer_access and isinstance(self.index, CloneNode))
1979 self.indices = indices
1981 self.type = self.base.type.dtype
1982 self.is_buffer_access = True
1983 self.buffer_type = self.base.entry.type
1985 if getting and self.type.is_pyobject:
1988 if not self.base.entry.type.writable:
1989 error(self.pos, "Writing to readonly buffer")
1991 self.base.entry.buffer_aux.writable_needed = True
1993 base_type = self.base.type
1994 if isinstance(self.index, TupleNode):
1995 self.index.analyse_types(env, skip_children=skip_child_analysis)
1996 elif not skip_child_analysis:
1997 self.index.analyse_types(env)
1998 self.original_index_type = self.index.type
1999 if base_type is PyrexTypes.c_py_unicode_type:
2000 # we infer Py_UNICODE for unicode strings in some
2001 # cases, but indexing must still work for them
2002 if self.index.constant_result in (0, -1):
2003 # FIXME: we know that this node is redundant -
2004 # currently, this needs to get handled in Optimize.py
2006 self.base = self.base.coerce_to_pyobject(env)
2007 base_type = self.base.type
2008 if base_type.is_pyobject:
2009 if self.index.type.is_int:
2011 and (base_type in (list_type, tuple_type, unicode_type))
2012 and (not self.index.type.signed or isinstance(self.index, IntNode) and int(self.index.value) >= 0)
2013 and not env.directives['boundscheck']):
2017 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
2019 self.index = self.index.coerce_to_pyobject(env)
2021 if self.index.type.is_int and base_type is unicode_type:
2022 # Py_UNICODE will automatically coerce to a unicode string
2023 # if required, so this is fast and safe
2024 self.type = PyrexTypes.c_py_unicode_type
2026 self.type = py_object_type
2028 if base_type.is_ptr or base_type.is_array:
2029 self.type = base_type.base_type
2030 if self.index.type.is_pyobject:
2031 self.index = self.index.coerce_to(
2032 PyrexTypes.c_py_ssize_t_type, env)
2033 if not self.index.type.is_int:
2035 "Invalid index type '%s'" %
2037 elif base_type.is_cpp_class:
2038 function = env.lookup_operator("[]", [self.base, self.index])
2039 if function is None:
2040 error(self.pos, "Indexing '%s' not supported for index type '%s'" % (base_type, self.index.type))
2041 self.type = PyrexTypes.error_type
2042 self.result_code = "<error>"
2044 func_type = function.type
2045 if func_type.is_ptr:
2046 func_type = func_type.base_type
2047 self.index = self.index.coerce_to(func_type.args[0].type, env)
2048 self.type = func_type.return_type
2049 if setting and not func_type.return_type.is_reference:
2050 error(self.pos, "Can't set non-reference result '%s'" % self.type)
2053 "Attempting to index non-array type '%s'" %
2055 self.type = PyrexTypes.error_type
2057 gil_message = "Indexing Python object"
2059 def nogil_check(self, env):
2060 if self.is_buffer_access:
2061 if env.directives['boundscheck']:
2062 error(self.pos, "Cannot check buffer index bounds without gil; use boundscheck(False) directive")
2064 elif self.type.is_pyobject:
2065 error(self.pos, "Cannot access buffer with object dtype without gil")
2067 super(IndexNode, self).nogil_check(env)
2070 def check_const_addr(self):
2071 return self.base.check_const_addr() and self.index.check_const()
2073 def is_lvalue(self):
2076 def calculate_result_code(self):
2077 if self.is_buffer_access:
2078 return "(*%s)" % self.buffer_ptr_code
2079 elif self.base.type is list_type:
2080 return "PyList_GET_ITEM(%s, %s)" % (self.base.result(), self.index.result())
2081 elif self.base.type is tuple_type:
2082 return "PyTuple_GET_ITEM(%s, %s)" % (self.base.result(), self.index.result())
2083 elif self.base.type is unicode_type and self.type is PyrexTypes.c_py_unicode_type:
2084 return "PyUnicode_AS_UNICODE(%s)[%s]" % (self.base.result(), self.index.result())
2086 return "(%s[%s])" % (
2087 self.base.result(), self.index.result())
2089 def extra_index_params(self):
2090 if self.index.type.is_int:
2091 if self.original_index_type.signed:
2092 size_adjustment = ""
2094 size_adjustment = "+1"
2095 return ", sizeof(%s)%s, %s" % (self.original_index_type.declaration_code(""), size_adjustment, self.original_index_type.to_py_function)
2099 def generate_subexpr_evaluation_code(self, code):
2100 self.base.generate_evaluation_code(code)
2101 if not self.indices:
2102 self.index.generate_evaluation_code(code)
2104 for i in self.indices:
2105 i.generate_evaluation_code(code)
2107 def generate_subexpr_disposal_code(self, code):
2108 self.base.generate_disposal_code(code)
2109 if not self.indices:
2110 self.index.generate_disposal_code(code)
2112 for i in self.indices:
2113 i.generate_disposal_code(code)
2115 def free_subexpr_temps(self, code):
2116 self.base.free_temps(code)
2117 if not self.indices:
2118 self.index.free_temps(code)
2120 for i in self.indices:
2123 def generate_result_code(self, code):
2124 if self.is_buffer_access:
2125 if code.globalstate.directives['nonecheck']:
2126 self.put_nonecheck(code)
2127 self.buffer_ptr_code = self.buffer_lookup_code(code)
2128 if self.type.is_pyobject:
2129 # is_temp is True, so must pull out value and incref it.
2130 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
2131 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
2133 if self.type.is_pyobject:
2134 if self.index.type.is_int:
2135 index_code = self.index.result()
2136 if self.base.type is list_type:
2137 function = "__Pyx_GetItemInt_List"
2138 elif self.base.type is tuple_type:
2139 function = "__Pyx_GetItemInt_Tuple"
2141 function = "__Pyx_GetItemInt"
2142 code.globalstate.use_utility_code(getitem_int_utility_code)
2144 index_code = self.index.py_result()
2145 if self.base.type is dict_type:
2146 function = "__Pyx_PyDict_GetItem"
2147 code.globalstate.use_utility_code(getitem_dict_utility_code)
2149 function = "PyObject_GetItem"
2151 "%s = %s(%s, %s%s); if (!%s) %s" % (
2154 self.base.py_result(),
2156 self.extra_index_params(),
2158 code.error_goto(self.pos)))
2159 code.put_gotref(self.py_result())
2160 elif self.type is PyrexTypes.c_py_unicode_type and self.base.type is unicode_type:
2161 assert self.index.type.is_int
2162 index_code = self.index.result()
2163 function = "__Pyx_GetItemInt_Unicode"
2164 code.globalstate.use_utility_code(getitem_int_pyunicode_utility_code)
2166 "%s = %s(%s, %s%s); if (unlikely(%s == (Py_UNICODE)-1)) %s;" % (
2169 self.base.py_result(),
2171 self.extra_index_params(),
2173 code.error_goto(self.pos)))
2175 def generate_setitem_code(self, value_code, code):
2176 if self.index.type.is_int:
2177 function = "__Pyx_SetItemInt"
2178 index_code = self.index.result()
2179 code.globalstate.use_utility_code(setitem_int_utility_code)
2181 index_code = self.index.py_result()
2182 if self.base.type is dict_type:
2183 function = "PyDict_SetItem"
2184 # It would seem that we could specialized lists/tuples, but that
2185 # shouldn't happen here.
2186 # Both PyList_SetItem PyTuple_SetItem and a Py_ssize_t as input,
2187 # not a PyObject*, and bad conversion here would give the wrong
2188 # exception. Also, tuples are supposed to be immutable, and raise
2189 # TypeErrors when trying to set their entries (PyTuple_SetItem
2190 # is for creating new tuples from).
2192 function = "PyObject_SetItem"
2194 "if (%s(%s, %s, %s%s) < 0) %s" % (
2196 self.base.py_result(),
2199 self.extra_index_params(),
2200 code.error_goto(self.pos)))
2202 def generate_buffer_setitem_code(self, rhs, code, op=""):
2203 # Used from generate_assignment_code and InPlaceAssignmentNode
2204 if code.globalstate.directives['nonecheck']:
2205 self.put_nonecheck(code)
2206 ptrexpr = self.buffer_lookup_code(code)
2207 if self.buffer_type.dtype.is_pyobject:
2208 # Must manage refcounts. Decref what is already there
2209 # and incref what we put in.
2210 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
2211 rhs_code = rhs.result()
2212 code.putln("%s = %s;" % (ptr, ptrexpr))
2213 code.put_gotref("*%s" % ptr)
2214 code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
2217 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
2218 code.put_giveref("*%s" % ptr)
2219 code.funcstate.release_temp(ptr)
2222 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
2224 def generate_assignment_code(self, rhs, code):
2225 self.generate_subexpr_evaluation_code(code)
2226 if self.is_buffer_access:
2227 self.generate_buffer_setitem_code(rhs, code)
2228 elif self.type.is_pyobject:
2229 self.generate_setitem_code(rhs.py_result(), code)
2233 self.result(), rhs.result()))
2234 self.generate_subexpr_disposal_code(code)
2235 self.free_subexpr_temps(code)
2236 rhs.generate_disposal_code(code)
2237 rhs.free_temps(code)
2239 def generate_deletion_code(self, code):
2240 self.generate_subexpr_evaluation_code(code)
2241 #if self.type.is_pyobject:
2242 if self.index.type.is_int:
2243 function = "__Pyx_DelItemInt"
2244 index_code = self.index.result()
2245 code.globalstate.use_utility_code(delitem_int_utility_code)
2247 index_code = self.index.py_result()
2248 if self.base.type is dict_type:
2249 function = "PyDict_DelItem"
2251 function = "PyObject_DelItem"
2253 "if (%s(%s, %s%s) < 0) %s" % (
2255 self.base.py_result(),
2257 self.extra_index_params(),
2258 code.error_goto(self.pos)))
2259 self.generate_subexpr_disposal_code(code)
2260 self.free_subexpr_temps(code)
2262 def buffer_lookup_code(self, code):
2263 # Assign indices to temps
2264 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
2265 for temp, index in zip(index_temps, self.indices):
2266 code.putln("%s = %s;" % (temp, index.result()))
2267 # Generate buffer access code using these temps
2269 # The above could happen because child_attrs is wrong somewhere so that
2270 # options are not propagated.
2271 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
2272 index_signeds=[i.type.signed for i in self.indices],
2273 index_cnames=index_temps,
2274 directives=code.globalstate.directives,
2275 pos=self.pos, code=code)
2277 def put_nonecheck(self, code):
2278 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
2279 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
2280 code.putln("__Pyx_RaiseNoneIndexingError();")
2281 code.putln(code.error_goto(self.pos))
2284 class SliceIndexNode(ExprNode):
2285 # 2-element slice indexing
2288 # start ExprNode or None
2289 # stop ExprNode or None
2291 subexprs = ['base', 'start', 'stop']
2293 def infer_type(self, env):
2294 base_type = self.base.infer_type(env)
2295 if base_type.is_string:
2297 elif base_type in (bytes_type, str_type, unicode_type,
2298 list_type, tuple_type):
2300 return py_object_type
2302 def calculate_constant_result(self):
2303 self.constant_result = self.base.constant_result[
2304 self.start.constant_result : self.stop.constant_result]
2306 def compile_time_value(self, denv):
2307 base = self.base.compile_time_value(denv)
2308 if self.start is None:
2311 start = self.start.compile_time_value(denv)
2312 if self.stop is None:
2315 stop = self.stop.compile_time_value(denv)
2317 return base[start:stop]
2318 except Exception, e:
2319 self.compile_time_value_error(e)
2321 def analyse_target_declaration(self, env):
2324 def analyse_target_types(self, env):
2325 self.analyse_types(env)
2326 # when assigning, we must accept any Python type
2327 if self.type.is_pyobject:
2328 self.type = py_object_type
2330 def analyse_types(self, env):
2331 self.base.analyse_types(env)
2333 self.start.analyse_types(env)
2335 self.stop.analyse_types(env)
2336 base_type = self.base.type
2337 if base_type.is_string:
2338 self.type = bytes_type
2339 elif base_type.is_array or base_type.is_ptr:
2340 # we need a ptr type here instead of an array type, as
2341 # array types can result in invalid type casts in the C
2343 self.type = PyrexTypes.CPtrType(base_type.base_type)
2345 self.base = self.base.coerce_to_pyobject(env)
2346 self.type = py_object_type
2347 if base_type.is_builtin_type:
2348 # slicing builtin types returns something of the same type
2349 self.type = base_type
2350 c_int = PyrexTypes.c_py_ssize_t_type
2352 self.start = self.start.coerce_to(c_int, env)
2354 self.stop = self.stop.coerce_to(c_int, env)
2357 nogil_check = Node.gil_error
2358 gil_message = "Slicing Python object"
2360 def generate_result_code(self, code):
2361 if not self.type.is_pyobject:
2363 "Slicing is not currently supported for '%s'." % self.type)
2365 if self.base.type.is_string:
2366 if self.stop is None:
2368 "%s = PyBytes_FromString(%s + %s); %s" % (
2372 code.error_goto_if_null(self.result(), self.pos)))
2375 "%s = PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
2381 code.error_goto_if_null(self.result(), self.pos)))
2384 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
2386 self.base.py_result(),
2389 code.error_goto_if_null(self.result(), self.pos)))
2390 code.put_gotref(self.py_result())
2392 def generate_assignment_code(self, rhs, code):
2393 self.generate_subexpr_evaluation_code(code)
2394 if self.type.is_pyobject:
2395 code.put_error_if_neg(self.pos,
2396 "PySequence_SetSlice(%s, %s, %s, %s)" % (
2397 self.base.py_result(),
2404 start_offset = self.start_code()
2405 if start_offset == '0':
2409 if rhs.type.is_array:
2410 array_length = rhs.type.size
2411 self.generate_slice_guard_code(code, array_length)
2414 "Slice assignments from pointers are not yet supported.")
2415 # FIXME: fix the array size according to start/stop
2416 array_length = self.base.type.size
2417 for i in range(array_length):
2418 code.putln("%s[%s%s] = %s[%d];" % (
2419 self.base.result(), start_offset, i,
2421 self.generate_subexpr_disposal_code(code)
2422 self.free_subexpr_temps(code)
2423 rhs.generate_disposal_code(code)
2424 rhs.free_temps(code)
2426 def generate_deletion_code(self, code):
2427 if not self.base.type.is_pyobject:
2429 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2431 self.generate_subexpr_evaluation_code(code)
2432 code.put_error_if_neg(self.pos,
2433 "PySequence_DelSlice(%s, %s, %s)" % (
2434 self.base.py_result(),
2437 self.generate_subexpr_disposal_code(code)
2439 def generate_slice_guard_code(self, code, target_size):
2440 if not self.base.type.is_array:
2442 slice_size = self.base.type.size
2445 stop = self.stop.result()
2449 slice_size = self.base.type.size + stop
2456 start = self.start.result()
2460 start = self.base.type.size + start
2468 error(self.pos, "Assignment to empty slice.")
2469 elif start is None and stop is None:
2470 # we know the exact slice length
2471 if target_size != slice_size:
2472 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2473 slice_size, target_size))
2474 elif start is not None:
2477 check = "(%s)-(%s)" % (stop, start)
2478 else: # stop is not None:
2481 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2482 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));' % (
2483 target_size, check))
2484 code.putln(code.error_goto(self.pos))
2487 def start_code(self):
2489 return self.start.result()
2493 def stop_code(self):
2495 return self.stop.result()
2496 elif self.base.type.is_array:
2497 return self.base.type.size
2499 return "PY_SSIZE_T_MAX"
2501 def calculate_result_code(self):
2502 # self.result() is not used, but this method must exist
2506 class SliceNode(ExprNode):
2507 # start:stop:step in subscript list
2513 type = py_object_type
2516 def calculate_constant_result(self):
2517 self.constant_result = self.base.constant_result[
2518 self.start.constant_result : \
2519 self.stop.constant_result : \
2520 self.step.constant_result]
2522 def compile_time_value(self, denv):
2523 start = self.start.compile_time_value(denv)
2524 if self.stop is None:
2527 stop = self.stop.compile_time_value(denv)
2528 if self.step is None:
2531 step = self.step.compile_time_value(denv)
2533 return slice(start, stop, step)
2534 except Exception, e:
2535 self.compile_time_value_error(e)
2537 subexprs = ['start', 'stop', 'step']
2539 def analyse_types(self, env):
2540 self.start.analyse_types(env)
2541 self.stop.analyse_types(env)
2542 self.step.analyse_types(env)
2543 self.start = self.start.coerce_to_pyobject(env)
2544 self.stop = self.stop.coerce_to_pyobject(env)
2545 self.step = self.step.coerce_to_pyobject(env)
2547 gil_message = "Constructing Python slice object"
2549 def generate_result_code(self, code):
2551 "%s = PySlice_New(%s, %s, %s); %s" % (
2553 self.start.py_result(),
2554 self.stop.py_result(),
2555 self.step.py_result(),
2556 code.error_goto_if_null(self.result(), self.pos)))
2557 code.put_gotref(self.py_result())
2560 class CallNode(ExprNode):
2562 def analyse_as_type_constructor(self, env):
2563 type = self.function.analyse_as_type(env)
2564 if type and type.is_struct_or_union:
2565 args, kwds = self.explicit_args_kwds()
2567 for arg, member in zip(args, type.scope.var_entries):
2568 items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg))
2570 items += kwds.key_value_pairs
2571 self.key_value_pairs = items
2572 self.__class__ = DictNode
2573 self.analyse_types(env)
2574 self.coerce_to(type, env)
2576 elif type and type.is_cpp_class:
2577 for arg in self.args:
2578 arg.analyse_types(env)
2579 constructor = type.scope.lookup("<init>")
2580 self.function = RawCNameExprNode(self.function.pos, constructor.type)
2581 self.function.entry = constructor
2582 self.function.set_cname(type.declaration_code(""))
2583 self.analyse_c_function_call(env)
2586 def is_lvalue(self):
2587 return self.type.is_reference
2589 def nogil_check(self, env):
2590 func_type = self.function_type()
2591 if func_type.is_pyobject:
2593 elif not getattr(func_type, 'nogil', False):
2596 gil_message = "Calling gil-requiring function"
2599 class SimpleCallNode(CallNode):
2600 # Function call without keyword, * or ** args.
2604 # arg_tuple ExprNode or None used internally
2605 # self ExprNode or None used internally
2606 # coerced_self ExprNode or None used internally
2607 # wrapper_call bool used internally
2608 # has_optional_args bool used internally
2610 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2615 wrapper_call = False
2616 has_optional_args = False
2618 def compile_time_value(self, denv):
2619 function = self.function.compile_time_value(denv)
2620 args = [arg.compile_time_value(denv) for arg in self.args]
2622 return function(*args)
2623 except Exception, e:
2624 self.compile_time_value_error(e)
2626 def type_dependencies(self, env):
2627 # TODO: Update when Danilo's C++ code merged in to handle the
2628 # the case of function overloading.
2629 return self.function.type_dependencies(env)
2631 def infer_type(self, env):
2632 function = self.function
2633 func_type = function.infer_type(env)
2634 if isinstance(self.function, NewExprNode):
2635 return PyrexTypes.CPtrType(self.function.class_type)
2636 if func_type.is_ptr:
2637 func_type = func_type.base_type
2638 if func_type.is_cfunction:
2639 return func_type.return_type
2640 elif func_type is type_type:
2641 if function.is_name and function.entry and function.entry.type:
2642 result_type = function.entry.type
2643 if result_type.is_extension_type:
2645 elif result_type.is_builtin_type:
2646 if function.entry.name == 'float':
2647 return PyrexTypes.c_double_type
2648 elif function.entry.name in Builtin.types_that_construct_their_instance:
2650 return py_object_type
2652 def analyse_as_type(self, env):
2653 attr = self.function.as_cython_attribute()
2654 if attr == 'pointer':
2655 if len(self.args) != 1:
2656 error(self.args.pos, "only one type allowed.")
2658 type = self.args[0].analyse_as_type(env)
2660 error(self.args[0].pos, "Unknown type")
2662 return PyrexTypes.CPtrType(type)
2664 def explicit_args_kwds(self):
2665 return self.args, None
2667 def analyse_types(self, env):
2668 if self.analyse_as_type_constructor(env):
2670 function = self.function
2671 function.is_called = 1
2672 self.function.analyse_types(env)
2673 if function.is_attribute and function.entry and function.entry.is_cmethod:
2674 # Take ownership of the object from which the attribute
2675 # was obtained, because we need to pass it as 'self'.
2676 self.self = function.obj
2677 function.obj = CloneNode(self.self)
2678 func_type = self.function_type()
2679 if func_type.is_pyobject:
2680 self.arg_tuple = TupleNode(self.pos, args = self.args)
2681 self.arg_tuple.analyse_types(env)
2683 if func_type is Builtin.type_type and function.is_name and \
2684 function.entry and \
2685 function.entry.is_builtin and \
2686 function.entry.name in Builtin.types_that_construct_their_instance:
2687 # calling a builtin type that returns a specific object type
2688 if function.entry.name == 'float':
2689 # the following will come true later on in a transform
2690 self.type = PyrexTypes.c_double_type
2691 self.result_ctype = PyrexTypes.c_double_type
2693 self.type = Builtin.builtin_types[function.entry.name]
2694 self.result_ctype = py_object_type
2695 elif function.is_name and function.type_entry:
2696 # We are calling an extension type constructor. As
2697 # long as we do not support __new__(), the result type
2699 self.type = function.type_entry.type
2700 self.result_ctype = py_object_type
2702 self.type = py_object_type
2705 for arg in self.args:
2706 arg.analyse_types(env)
2707 if self.self and func_type.args:
2708 # Coerce 'self' to the type expected by the method.
2709 expected_type = func_type.args[0].type
2710 self.coerced_self = CloneNode(self.self).coerce_to(
2712 # Insert coerced 'self' argument into argument list.
2713 self.args.insert(0, self.coerced_self)
2714 self.analyse_c_function_call(env)
2716 def function_type(self):
2717 # Return the type of the function being called, coercing a function
2718 # pointer to a function if necessary.
2719 func_type = self.function.type
2720 if func_type.is_ptr:
2721 func_type = func_type.base_type
2724 def analyse_c_function_call(self, env):
2725 if self.function.type is error_type:
2726 self.type = error_type
2728 if self.function.type.is_cpp_class:
2729 overloaded_entry = self.function.type.scope.lookup("operator()")
2730 if overloaded_entry is None:
2731 self.type = PyrexTypes.error_type
2732 self.result_code = "<error>"
2734 elif hasattr(self.function, 'entry'):
2735 overloaded_entry = self.function.entry
2737 overloaded_entry = None
2738 if overloaded_entry:
2739 entry = PyrexTypes.best_match(self.args, overloaded_entry.all_alternatives(), self.pos)
2741 self.type = PyrexTypes.error_type
2742 self.result_code = "<error>"
2744 self.function.entry = entry
2745 self.function.type = entry.type
2746 func_type = self.function_type()
2748 func_type = self.function_type()
2749 if not func_type.is_cfunction:
2750 error(self.pos, "Calling non-function type '%s'" % func_type)
2751 self.type = PyrexTypes.error_type
2752 self.result_code = "<error>"
2755 max_nargs = len(func_type.args)
2756 expected_nargs = max_nargs - func_type.optional_arg_count
2757 actual_nargs = len(self.args)
2758 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2759 self.has_optional_args = 1
2762 for i in range(min(max_nargs, actual_nargs)):
2763 formal_type = func_type.args[i].type
2764 self.args[i] = self.args[i].coerce_to(formal_type, env)
2765 for i in range(max_nargs, actual_nargs):
2766 if self.args[i].type.is_pyobject:
2767 error(self.args[i].pos,
2768 "Python object cannot be passed as a varargs parameter")
2769 # Calc result type and code fragment
2770 if isinstance(self.function, NewExprNode):
2771 self.type = PyrexTypes.CPtrType(self.function.class_type)
2773 self.type = func_type.return_type
2774 if self.type.is_pyobject:
2775 self.result_ctype = py_object_type
2777 elif func_type.exception_value is not None \
2778 or func_type.exception_check:
2780 # C++ exception handler
2781 if func_type.exception_check == '+':
2782 if func_type.exception_value is None:
2783 env.use_utility_code(cpp_exception_utility_code)
2785 def calculate_result_code(self):
2786 return self.c_call_code()
2788 def c_call_code(self):
2789 func_type = self.function_type()
2790 if self.type is PyrexTypes.error_type or not func_type.is_cfunction:
2792 formal_args = func_type.args
2794 args = zip(formal_args, self.args)
2795 max_nargs = len(func_type.args)
2796 expected_nargs = max_nargs - func_type.optional_arg_count
2797 actual_nargs = len(self.args)
2798 for formal_arg, actual_arg in args[:expected_nargs]:
2799 arg_code = actual_arg.result_as(formal_arg.type)
2800 arg_list_code.append(arg_code)
2802 if func_type.is_overridable:
2803 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2805 if func_type.optional_arg_count:
2806 if expected_nargs == actual_nargs:
2807 optional_args = 'NULL'
2809 optional_args = "&%s" % self.opt_arg_struct
2810 arg_list_code.append(optional_args)
2812 for actual_arg in self.args[len(formal_args):]:
2813 arg_list_code.append(actual_arg.result())
2814 result = "%s(%s)" % (self.function.result(),
2815 ', '.join(arg_list_code))
2818 def generate_result_code(self, code):
2819 func_type = self.function_type()
2820 if func_type.is_pyobject:
2821 arg_code = self.arg_tuple.py_result()
2823 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2825 self.function.py_result(),
2827 code.error_goto_if_null(self.result(), self.pos)))
2828 code.put_gotref(self.py_result())
2829 elif func_type.is_cfunction:
2830 if self.has_optional_args:
2831 actual_nargs = len(self.args)
2832 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2833 self.opt_arg_struct = code.funcstate.allocate_temp(
2834 func_type.op_arg_struct.base_type, manage_ref=True)
2835 code.putln("%s.%s = %s;" % (
2836 self.opt_arg_struct,
2837 Naming.pyrex_prefix + "n",
2838 len(self.args) - expected_nargs))
2839 args = zip(func_type.args, self.args)
2840 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2841 code.putln("%s.%s = %s;" % (
2842 self.opt_arg_struct,
2843 func_type.opt_arg_cname(formal_arg.name),
2844 actual_arg.result_as(formal_arg.type)))
2846 if self.type.is_pyobject and self.is_temp:
2847 exc_checks.append("!%s" % self.result())
2849 exc_val = func_type.exception_value
2850 exc_check = func_type.exception_check
2851 if exc_val is not None:
2852 exc_checks.append("%s == %s" % (self.result(), exc_val))
2854 exc_checks.append("PyErr_Occurred()")
2855 if self.is_temp or exc_checks:
2856 rhs = self.c_call_code()
2858 lhs = "%s = " % self.result()
2859 if self.is_temp and self.type.is_pyobject:
2860 #return_type = self.type # func_type.return_type
2861 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2862 # "from", return_type, "to pyobject" ###
2863 rhs = typecast(py_object_type, self.type, rhs)
2866 if func_type.exception_check == '+':
2867 if func_type.exception_value is None:
2868 raise_py_exception = "__Pyx_CppExn2PyErr()"
2869 elif func_type.exception_value.type.is_pyobject:
2870 raise_py_exception = ' try { throw; } catch(const std::exception& exn) { PyErr_SetString(%s, exn.what()); } catch(...) { PyErr_SetNone(%s); }' % (
2871 func_type.exception_value.entry.cname,
2872 func_type.exception_value.entry.cname)
2874 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2876 "try {%s%s;} catch(...) {%s; %s}" % (
2880 code.error_goto(self.pos)))
2883 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2886 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2887 if self.type.is_pyobject and self.result():
2888 code.put_gotref(self.py_result())
2889 if self.has_optional_args:
2890 code.funcstate.release_temp(self.opt_arg_struct)
2893 class PythonCapiFunctionNode(ExprNode):
2895 def __init__(self, pos, py_name, cname, func_type, utility_code = None):
2899 self.type = func_type
2900 self.utility_code = utility_code
2902 def analyse_types(self, env):
2905 def generate_result_code(self, code):
2906 if self.utility_code:
2907 code.globalstate.use_utility_code(self.utility_code)
2909 def calculate_result_code(self):
2912 class PythonCapiCallNode(SimpleCallNode):
2913 # Python C-API Function call (only created in transforms)
2915 def __init__(self, pos, function_name, func_type,
2916 utility_code = None, py_name=None, **kwargs):
2917 self.type = func_type.return_type
2918 self.result_ctype = self.type
2919 self.function = PythonCapiFunctionNode(
2920 pos, py_name, function_name, func_type,
2921 utility_code = utility_code)
2922 # call this last so that we can override the constructed
2923 # attributes above with explicit keyword arguments if required
2924 SimpleCallNode.__init__(self, pos, **kwargs)
2927 class GeneralCallNode(CallNode):
2928 # General Python function call, including keyword,
2929 # * and ** arguments.
2932 # positional_args ExprNode Tuple of positional arguments
2933 # keyword_args ExprNode or None Dict of keyword arguments
2934 # starstar_arg ExprNode or None Dict of extra keyword args
2936 type = py_object_type
2938 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2940 nogil_check = Node.gil_error
2942 def compile_time_value(self, denv):
2943 function = self.function.compile_time_value(denv)
2944 positional_args = self.positional_args.compile_time_value(denv)
2945 keyword_args = self.keyword_args.compile_time_value(denv)
2946 starstar_arg = self.starstar_arg.compile_time_value(denv)
2948 keyword_args.update(starstar_arg)
2949 return function(*positional_args, **keyword_args)
2950 except Exception, e:
2951 self.compile_time_value_error(e)
2953 def explicit_args_kwds(self):
2954 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2955 raise PostParseError(self.pos,
2956 'Compile-time keyword arguments must be explicit.')
2957 return self.positional_args.args, self.keyword_args
2959 def analyse_types(self, env):
2960 if self.analyse_as_type_constructor(env):
2962 self.function.analyse_types(env)
2963 self.positional_args.analyse_types(env)
2964 if self.keyword_args:
2965 self.keyword_args.analyse_types(env)
2966 if self.starstar_arg:
2967 self.starstar_arg.analyse_types(env)
2968 if not self.function.type.is_pyobject:
2969 if self.function.type.is_error:
2970 self.type = error_type
2972 if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
2973 error(self.pos, "Keyword and starred arguments not allowed in cdef functions.")
2975 self.function = self.function.coerce_to_pyobject(env)
2976 self.positional_args = \
2977 self.positional_args.coerce_to_pyobject(env)
2978 if self.starstar_arg:
2979 self.starstar_arg = \
2980 self.starstar_arg.coerce_to_pyobject(env)
2981 function = self.function
2982 if function.is_name and function.type_entry:
2983 # We are calling an extension type constructor. As long
2984 # as we do not support __new__(), the result type is clear
2985 self.type = function.type_entry.type
2986 self.result_ctype = py_object_type
2988 self.type = py_object_type
2991 def generate_result_code(self, code):
2992 if self.type.is_error: return
2993 kwargs_call_function = "PyEval_CallObjectWithKeywords"
2994 if self.keyword_args and self.starstar_arg:
2995 code.put_error_if_neg(self.pos,
2996 "PyDict_Update(%s, %s)" % (
2997 self.keyword_args.py_result(),
2998 self.starstar_arg.py_result()))
2999 keyword_code = self.keyword_args.py_result()
3000 elif self.keyword_args:
3001 keyword_code = self.keyword_args.py_result()
3002 elif self.starstar_arg:
3003 keyword_code = self.starstar_arg.py_result()
3004 if self.starstar_arg.type is not Builtin.dict_type:
3005 # CPython supports calling functions with non-dicts, so do we
3006 code.globalstate.use_utility_code(kwargs_call_utility_code)
3007 kwargs_call_function = "__Pyx_PyEval_CallObjectWithKeywords"
3010 if not keyword_code:
3011 call_code = "PyObject_Call(%s, %s, NULL)" % (
3012 self.function.py_result(),
3013 self.positional_args.py_result())
3015 call_code = "%s(%s, %s, %s)" % (
3016 kwargs_call_function,
3017 self.function.py_result(),
3018 self.positional_args.py_result(),
3024 code.error_goto_if_null(self.result(), self.pos)))
3025 code.put_gotref(self.py_result())
3028 class AsTupleNode(ExprNode):
3029 # Convert argument to tuple. Used for normalising
3030 # the * argument of a function call.
3036 def calculate_constant_result(self):
3037 self.constant_result = tuple(self.base.constant_result)
3039 def compile_time_value(self, denv):
3040 arg = self.arg.compile_time_value(denv)
3043 except Exception, e:
3044 self.compile_time_value_error(e)
3046 def analyse_types(self, env):
3047 self.arg.analyse_types(env)
3048 self.arg = self.arg.coerce_to_pyobject(env)
3049 self.type = tuple_type
3052 def may_be_none(self):
3055 nogil_check = Node.gil_error
3056 gil_message = "Constructing Python tuple"
3058 def generate_result_code(self, code):
3060 "%s = PySequence_Tuple(%s); %s" % (
3062 self.arg.py_result(),
3063 code.error_goto_if_null(self.result(), self.pos)))
3064 code.put_gotref(self.py_result())
3067 class AttributeNode(ExprNode):
3072 # needs_none_check boolean Used if obj is an extension type.
3073 # If set to True, it is known that the type is not None.
3077 # is_py_attr boolean Is a Python getattr operation
3078 # member string C name of struct member
3079 # is_called boolean Function call is being done on result
3080 # entry Entry Symbol table entry of attribute
3085 type = PyrexTypes.error_type
3088 needs_none_check = True
3090 def as_cython_attribute(self):
3091 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
3092 return self.attribute
3093 cy = self.obj.as_cython_attribute()
3095 return "%s.%s" % (cy, self.attribute)
3097 def coerce_to(self, dst_type, env):
3098 # If coercing to a generic pyobject and this is a cpdef function
3099 # we can create the corresponding attribute
3100 if dst_type is py_object_type:
3102 if entry and entry.is_cfunction and entry.as_variable:
3103 # must be a cpdef function
3105 self.entry = entry.as_variable
3106 self.analyse_as_python_attribute(env)
3108 return ExprNode.coerce_to(self, dst_type, env)
3110 def calculate_constant_result(self):
3111 attr = self.attribute
3112 if attr.startswith("__") and attr.endswith("__"):
3114 self.constant_result = getattr(self.obj.constant_result, attr)
3116 def compile_time_value(self, denv):
3117 attr = self.attribute
3118 if attr.startswith("__") and attr.endswith("__"):
3120 "Invalid attribute name '%s' in compile-time expression" % attr)
3122 obj = self.obj.compile_time_value(denv)
3124 return getattr(obj, attr)
3125 except Exception, e:
3126 self.compile_time_value_error(e)
3128 def type_dependencies(self, env):
3129 return self.obj.type_dependencies(env)
3131 def infer_type(self, env):
3132 if self.analyse_as_cimported_attribute(env, 0):
3133 return self.entry.type
3134 elif self.analyse_as_unbound_cmethod(env):
3135 return self.entry.type
3137 self.analyse_attribute(env, obj_type = self.obj.infer_type(env))
3140 def analyse_target_declaration(self, env):
3143 def analyse_target_types(self, env):
3144 self.analyse_types(env, target = 1)
3146 def analyse_types(self, env, target = 0):
3147 if self.analyse_as_cimported_attribute(env, target):
3149 if not target and self.analyse_as_unbound_cmethod(env):
3151 self.analyse_as_ordinary_attribute(env, target)
3153 def analyse_as_cimported_attribute(self, env, target):
3154 # Try to interpret this as a reference to an imported
3155 # C const, type, var or function. If successful, mutates
3156 # this node into a NameNode and returns 1, otherwise
3158 module_scope = self.obj.analyse_as_module(env)
3160 entry = module_scope.lookup_here(self.attribute)
3162 entry.is_cglobal or entry.is_cfunction
3163 or entry.is_type or entry.is_const):
3164 self.mutate_into_name_node(env, entry, target)
3168 def analyse_as_unbound_cmethod(self, env):
3169 # Try to interpret this as a reference to an unbound
3170 # C method of an extension type. If successful, mutates
3171 # this node into a NameNode and returns 1, otherwise
3173 type = self.obj.analyse_as_extension_type(env)
3175 entry = type.scope.lookup_here(self.attribute)
3176 if entry and entry.is_cmethod:
3177 # Create a temporary entry describing the C method
3178 # as an ordinary function.
3179 ubcm_entry = Symtab.Entry(entry.name,
3180 "%s->%s" % (type.vtabptr_cname, entry.cname),
3182 ubcm_entry.is_cfunction = 1
3183 ubcm_entry.func_cname = entry.func_cname
3184 ubcm_entry.is_unbound_cmethod = 1
3185 self.mutate_into_name_node(env, ubcm_entry, None)
3189 def analyse_as_type(self, env):
3190 module_scope = self.obj.analyse_as_module(env)
3192 return module_scope.lookup_type(self.attribute)
3193 if not isinstance(self.obj, (UnicodeNode, StringNode, BytesNode)):
3194 base_type = self.obj.analyse_as_type(env)
3195 if base_type and hasattr(base_type, 'scope'):
3196 return base_type.scope.lookup_type(self.attribute)
3199 def analyse_as_extension_type(self, env):
3200 # Try to interpret this as a reference to an extension type
3201 # in a cimported module. Returns the extension type, or None.
3202 module_scope = self.obj.analyse_as_module(env)
3204 entry = module_scope.lookup_here(self.attribute)
3205 if entry and entry.is_type and entry.type.is_extension_type:
3209 def analyse_as_module(self, env):
3210 # Try to interpret this as a reference to a cimported module
3211 # in another cimported module. Returns the module scope, or None.
3212 module_scope = self.obj.analyse_as_module(env)
3214 entry = module_scope.lookup_here(self.attribute)
3215 if entry and entry.as_module:
3216 return entry.as_module
3219 def mutate_into_name_node(self, env, entry, target):
3220 # Mutate this node into a NameNode and complete the
3221 # analyse_types phase.
3222 self.__class__ = NameNode
3223 self.name = self.attribute
3228 NameNode.analyse_target_types(self, env)
3230 NameNode.analyse_rvalue_entry(self, env)
3232 def analyse_as_ordinary_attribute(self, env, target):
3233 self.obj.analyse_types(env)
3234 self.analyse_attribute(env)
3235 if self.entry and self.entry.is_cmethod and not self.is_called:
3236 # error(self.pos, "C method can only be called")
3238 ## Reference to C array turns into pointer to first element.
3239 #while self.type.is_array:
3240 # self.type = self.type.element_ptr_type()
3244 self.result_ctype = py_object_type
3246 def analyse_attribute(self, env, obj_type = None):
3247 # Look up attribute and set self.type and self.member.
3249 self.member = self.attribute
3250 if obj_type is None:
3251 if self.obj.type.is_string:
3252 self.obj = self.obj.coerce_to_pyobject(env)
3253 obj_type = self.obj.type
3255 if obj_type.is_string:
3256 obj_type = py_object_type
3257 if obj_type.is_ptr or obj_type.is_array:
3258 obj_type = obj_type.base_type
3260 elif obj_type.is_extension_type:
3264 if obj_type.has_attributes:
3266 if obj_type.attributes_known():
3267 entry = obj_type.scope.lookup_here(self.attribute)
3268 if entry and entry.is_member:
3272 "Cannot select attribute of incomplete type '%s'"
3274 self.type = PyrexTypes.error_type
3278 if obj_type.is_extension_type and entry.name == "__weakref__":
3279 error(self.pos, "Illegal use of special attribute __weakref__")
3280 # methods need the normal attribute lookup
3281 # because they do not have struct entries
3282 if entry.is_variable or entry.is_cmethod:
3283 self.type = entry.type
3284 self.member = entry.cname
3287 # If it's not a variable or C method, it must be a Python
3288 # method of an extension type, so we treat it like a Python
3291 # If we get here, the base object is not a struct/union/extension
3292 # type, or it is an extension type and the attribute is either not
3293 # declared or is declared as a Python method. Treat it as a Python
3294 # attribute reference.
3295 self.analyse_as_python_attribute(env, obj_type)
3297 def analyse_as_python_attribute(self, env, obj_type = None):
3298 if obj_type is None:
3299 obj_type = self.obj.type
3300 self.member = self.attribute
3301 self.type = py_object_type
3303 if not obj_type.is_pyobject and not obj_type.is_error:
3304 if obj_type.can_coerce_to_pyobject(env):
3305 self.obj = self.obj.coerce_to_pyobject(env)
3308 "Object of type '%s' has no attribute '%s'" %
3309 (obj_type, self.attribute))
3311 def nogil_check(self, env):
3315 gil_message = "Accessing Python attribute"
3317 def is_simple(self):
3319 return self.result_in_temp() or self.obj.is_simple()
3321 return NameNode.is_simple(self)
3323 def is_lvalue(self):
3327 return NameNode.is_lvalue(self)
3329 def is_ephemeral(self):
3331 return self.obj.is_ephemeral()
3333 return NameNode.is_ephemeral(self)
3335 def calculate_result_code(self):
3336 #print "AttributeNode.calculate_result_code:", self.member ###
3337 #print "...obj node =", self.obj, "code", self.obj.result() ###
3338 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
3340 obj_code = obj.result_as(obj.type)
3341 #print "...obj_code =", obj_code ###
3342 if self.entry and self.entry.is_cmethod:
3343 if obj.type.is_extension_type:
3344 return "((struct %s *)%s%s%s)->%s" % (
3345 obj.type.vtabstruct_cname, obj_code, self.op,
3346 obj.type.vtabslot_cname, self.member)
3349 elif obj.type.is_complex:
3350 return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code)
3352 return "%s%s%s" % (obj_code, self.op, self.member)
3354 def generate_result_code(self, code):
3355 interned_attr_cname = code.intern_identifier(self.attribute)
3358 '%s = PyObject_GetAttr(%s, %s); %s' % (
3360 self.obj.py_result(),
3361 interned_attr_cname,
3362 code.error_goto_if_null(self.result(), self.pos)))
3363 code.put_gotref(self.py_result())
3365 # result_code contains what is needed, but we may need to insert
3366 # a check and raise an exception
3367 if (self.obj.type.is_extension_type
3368 and self.needs_none_check
3369 and code.globalstate.directives['nonecheck']):
3370 self.put_nonecheck(code)
3372 def generate_assignment_code(self, rhs, code):
3373 interned_attr_cname = code.intern_identifier(self.attribute)
3374 self.obj.generate_evaluation_code(code)
3376 code.put_error_if_neg(self.pos,
3377 'PyObject_SetAttr(%s, %s, %s)' % (
3378 self.obj.py_result(),
3379 interned_attr_cname,
3381 rhs.generate_disposal_code(code)
3382 rhs.free_temps(code)
3383 elif self.obj.type.is_complex:
3384 code.putln("__Pyx_SET_C%s(%s, %s);" % (
3385 self.member.upper(),
3386 self.obj.result_as(self.obj.type),
3387 rhs.result_as(self.ctype())))
3389 if (self.obj.type.is_extension_type
3390 and self.needs_none_check
3391 and code.globalstate.directives['nonecheck']):
3392 self.put_nonecheck(code)
3394 select_code = self.result()
3395 if self.type.is_pyobject and self.use_managed_ref:
3396 rhs.make_owned_reference(code)
3397 code.put_giveref(rhs.py_result())
3398 code.put_gotref(select_code)
3399 code.put_decref(select_code, self.ctype())
3403 rhs.result_as(self.ctype())))
3405 rhs.generate_post_assignment_code(code)
3406 rhs.free_temps(code)
3407 self.obj.generate_disposal_code(code)
3408 self.obj.free_temps(code)
3410 def generate_deletion_code(self, code):
3411 interned_attr_cname = code.intern_identifier(self.attribute)
3412 self.obj.generate_evaluation_code(code)
3414 code.put_error_if_neg(self.pos,
3415 'PyObject_DelAttr(%s, %s)' % (
3416 self.obj.py_result(),
3417 interned_attr_cname))
3419 error(self.pos, "Cannot delete C attribute of extension type")
3420 self.obj.generate_disposal_code(code)
3421 self.obj.free_temps(code)
3423 def annotate(self, code):
3425 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
3427 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
3429 def put_nonecheck(self, code):
3430 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
3431 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
3432 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute)
3433 code.putln(code.error_goto(self.pos))
3437 #-------------------------------------------------------------------
3441 #-------------------------------------------------------------------
3443 class StarredTargetNode(ExprNode):
3444 # A starred expression like "*a"
3446 # This is only allowed in sequence assignment targets such as
3448 # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4]
3450 # and will be removed during type analysis (or generate an error
3451 # if it's found at unexpected places).
3455 subexprs = ['target']
3457 type = py_object_type
3460 def __init__(self, pos, target):
3462 self.target = target
3464 def analyse_declarations(self, env):
3465 error(self.pos, "can use starred expression only as assignment target")
3466 self.target.analyse_declarations(env)
3468 def analyse_types(self, env):
3469 error(self.pos, "can use starred expression only as assignment target")
3470 self.target.analyse_types(env)
3471 self.type = self.target.type
3473 def analyse_target_declaration(self, env):
3474 self.target.analyse_target_declaration(env)
3476 def analyse_target_types(self, env):
3477 self.target.analyse_target_types(env)
3478 self.type = self.target.type
3480 def calculate_result_code(self):
3483 def generate_result_code(self, code):
3487 class SequenceNode(ExprNode):
3488 # Base class for list and tuple constructor nodes.
3489 # Contains common code for performing sequence unpacking.
3493 # unpacked_items [ExprNode] or None
3494 # coerced_unpacked_items [ExprNode] or None
3498 is_sequence_constructor = 1
3499 unpacked_items = None
3501 def compile_time_value_list(self, denv):
3502 return [arg.compile_time_value(denv) for arg in self.args]
3504 def replace_starred_target_node(self):
3505 # replace a starred node in the targets by the contained expression
3506 self.starred_assignment = False
3508 for arg in self.args:
3510 if self.starred_assignment:
3511 error(arg.pos, "more than 1 starred expression in assignment")
3512 self.starred_assignment = True
3514 arg.is_starred = True
3518 def analyse_target_declaration(self, env):
3519 self.replace_starred_target_node()
3520 for arg in self.args:
3521 arg.analyse_target_declaration(env)
3523 def analyse_types(self, env, skip_children=False):
3524 for i in range(len(self.args)):
3526 if not skip_children: arg.analyse_types(env)
3527 self.args[i] = arg.coerce_to_pyobject(env)
3528 self.type = py_object_type
3531 def may_be_none(self):
3534 def analyse_target_types(self, env):
3535 self.iterator = PyTempNode(self.pos, env)
3536 self.unpacked_items = []
3537 self.coerced_unpacked_items = []
3538 for arg in self.args:
3539 arg.analyse_target_types(env)
3541 if not arg.type.assignable_from(Builtin.list_type):
3543 "starred target must have Python object (list) type")
3544 if arg.type is py_object_type:
3545 arg.type = Builtin.list_type
3546 unpacked_item = PyTempNode(self.pos, env)
3547 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
3548 self.unpacked_items.append(unpacked_item)
3549 self.coerced_unpacked_items.append(coerced_unpacked_item)
3550 self.type = py_object_type
3552 def generate_result_code(self, code):
3553 self.generate_operation_code(code)
3555 def generate_assignment_code(self, rhs, code):
3556 if self.starred_assignment:
3557 self.generate_starred_assignment_code(rhs, code)
3559 self.generate_parallel_assignment_code(rhs, code)
3561 for item in self.unpacked_items:
3563 rhs.free_temps(code)
3565 def generate_parallel_assignment_code(self, rhs, code):
3566 # Need to work around the fact that generate_evaluation_code
3567 # allocates the temps in a rather hacky way -- the assignment
3568 # is evaluated twice, within each if-block.
3570 if rhs.type is tuple_type:
3571 tuple_check = "likely(%s != Py_None)"
3573 tuple_check = "PyTuple_CheckExact(%s)"
3575 "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
3576 tuple_check % rhs.py_result(),
3579 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3580 for item in self.unpacked_items:
3582 for i in range(len(self.args)):
3583 item = self.unpacked_items[i]
3585 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3588 code.put_incref(item.result(), item.ctype())
3589 value_node = self.coerced_unpacked_items[i]
3590 value_node.generate_evaluation_code(code)
3591 rhs.generate_disposal_code(code)
3593 for i in range(len(self.args)):
3594 self.args[i].generate_assignment_code(
3595 self.coerced_unpacked_items[i], code)
3597 code.putln("} else {")
3599 if rhs.type is tuple_type:
3600 code.globalstate.use_utility_code(tuple_unpacking_error_code)
3601 code.putln("__Pyx_UnpackTupleError(%s, %s);" % (
3602 rhs.py_result(), len(self.args)))
3603 code.putln(code.error_goto(self.pos))
3605 code.globalstate.use_utility_code(unpacking_utility_code)
3607 self.iterator.allocate(code)
3609 "%s = PyObject_GetIter(%s); %s" % (
3610 self.iterator.result(),
3612 code.error_goto_if_null(self.iterator.result(), self.pos)))
3613 code.put_gotref(self.iterator.py_result())
3614 rhs.generate_disposal_code(code)
3615 for i in range(len(self.args)):
3616 item = self.unpacked_items[i]
3617 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3618 self.iterator.py_result(), i)
3622 typecast(item.ctype(), py_object_type, unpack_code),
3623 code.error_goto_if_null(item.result(), self.pos)))
3624 code.put_gotref(item.py_result())
3625 value_node = self.coerced_unpacked_items[i]
3626 value_node.generate_evaluation_code(code)
3627 code.put_error_if_neg(self.pos,
3628 "__Pyx_EndUnpack(%s)" % (
3629 self.iterator.py_result()))
3630 if debug_disposal_code:
3631 print("UnpackNode.generate_assignment_code:")
3632 print("...generating disposal code for %s" % self.iterator)
3633 self.iterator.generate_disposal_code(code)
3634 self.iterator.free_temps(code)
3635 self.iterator.release(code)
3637 for i in range(len(self.args)):
3638 self.args[i].generate_assignment_code(
3639 self.coerced_unpacked_items[i], code)
3643 def generate_starred_assignment_code(self, rhs, code):
3644 code.globalstate.use_utility_code(unpacking_utility_code)
3646 for i, arg in enumerate(self.args):
3648 starred_target = self.unpacked_items[i]
3649 fixed_args_left = self.args[:i]
3650 fixed_args_right = self.args[i+1:]
3653 self.iterator.allocate(code)
3655 "%s = PyObject_GetIter(%s); %s" % (
3656 self.iterator.result(),
3658 code.error_goto_if_null(self.iterator.result(), self.pos)))
3659 code.put_gotref(self.iterator.py_result())
3660 rhs.generate_disposal_code(code)
3662 for item in self.unpacked_items:
3664 for i in range(len(fixed_args_left)):
3665 item = self.unpacked_items[i]
3666 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3667 self.iterator.py_result(), i)
3671 typecast(item.ctype(), py_object_type, unpack_code),
3672 code.error_goto_if_null(item.result(), self.pos)))
3673 code.put_gotref(item.py_result())
3674 value_node = self.coerced_unpacked_items[i]
3675 value_node.generate_evaluation_code(code)
3677 target_list = starred_target.result()
3678 code.putln("%s = PySequence_List(%s); %s" % (
3679 target_list, self.iterator.py_result(),
3680 code.error_goto_if_null(target_list, self.pos)))
3681 code.put_gotref(target_list)
3682 if fixed_args_right:
3683 code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
3684 unpacked_right_args = self.unpacked_items[-len(fixed_args_right):]
3685 code.putln("if (unlikely(PyList_GET_SIZE(%s) < %d)) {" % (
3686 (target_list, len(unpacked_right_args))))
3687 code.put("__Pyx_RaiseNeedMoreValuesError(%d+PyList_GET_SIZE(%s)); %s" % (
3688 len(fixed_args_left), target_list,
3689 code.error_goto(self.pos)))
3691 for i, (arg, coerced_arg) in enumerate(zip(unpacked_right_args[::-1],
3692 self.coerced_unpacked_items[::-1])):
3694 "%s = PyList_GET_ITEM(%s, PyList_GET_SIZE(%s)-1); " % (
3696 target_list, target_list))
3697 # resize the list the hard way
3698 code.putln("((PyVarObject*)%s)->ob_size--;" % target_list)
3699 code.put_gotref(arg.py_result())
3700 coerced_arg.generate_evaluation_code(code)
3702 self.iterator.generate_disposal_code(code)
3703 self.iterator.free_temps(code)
3704 self.iterator.release(code)
3706 for i in range(len(self.args)):
3707 self.args[i].generate_assignment_code(
3708 self.coerced_unpacked_items[i], code)
3710 def annotate(self, code):
3711 for arg in self.args:
3713 if self.unpacked_items:
3714 for arg in self.unpacked_items:
3716 for arg in self.coerced_unpacked_items:
3720 class TupleNode(SequenceNode):
3721 # Tuple constructor.
3725 gil_message = "Constructing Python tuple"
3727 def analyse_types(self, env, skip_children=False):
3728 if len(self.args) == 0:
3732 SequenceNode.analyse_types(self, env, skip_children)
3734 def calculate_result_code(self):
3735 if len(self.args) > 0:
3736 error(self.pos, "Positive length tuples must be constructed.")
3738 return Naming.empty_tuple
3740 def calculate_constant_result(self):
3741 self.constant_result = tuple([
3742 arg.constant_result for arg in self.args])
3744 def compile_time_value(self, denv):
3745 values = self.compile_time_value_list(denv)
3747 return tuple(values)
3748 except Exception, e:
3749 self.compile_time_value_error(e)
3751 def generate_operation_code(self, code):
3752 if len(self.args) == 0:
3753 # result_code is Naming.empty_tuple
3756 "%s = PyTuple_New(%s); %s" % (
3759 code.error_goto_if_null(self.result(), self.pos)))
3760 code.put_gotref(self.py_result())
3761 for i in range(len(self.args)):
3763 if not arg.result_in_temp():
3764 code.put_incref(arg.result(), arg.ctype())
3766 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3770 code.put_giveref(arg.py_result())
3772 def generate_subexpr_disposal_code(self, code):
3773 # We call generate_post_assignment_code here instead
3774 # of generate_disposal_code, because values were stored
3775 # in the tuple using a reference-stealing operation.
3776 for arg in self.args:
3777 arg.generate_post_assignment_code(code)
3778 # Should NOT call free_temps -- this is invoked by the default
3779 # generate_evaluation_code which will do that.
3782 class ListNode(SequenceNode):
3785 # obj_conversion_errors [PyrexError] used internally
3786 # orignial_args [ExprNode] used internally
3788 obj_conversion_errors = []
3790 gil_message = "Constructing Python list"
3792 def type_dependencies(self, env):
3795 def infer_type(self, env):
3796 # TOOD: Infer non-object list arrays.
3799 def analyse_expressions(self, env):
3800 SequenceNode.analyse_expressions(self, env)
3801 self.coerce_to_pyobject(env)
3803 def analyse_types(self, env):
3805 self.original_args = list(self.args)
3806 SequenceNode.analyse_types(self, env)
3807 self.type = list_type
3808 self.obj_conversion_errors = held_errors()
3809 release_errors(ignore=True)
3811 def coerce_to(self, dst_type, env):
3812 if dst_type.is_pyobject:
3813 for err in self.obj_conversion_errors:
3815 self.obj_conversion_errors = []
3816 if not self.type.subtype_of(dst_type):
3817 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3818 elif dst_type.is_ptr:
3819 base_type = dst_type.base_type
3820 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3821 for i in range(len(self.original_args)):
3823 if isinstance(arg, CoerceToPyTypeNode):
3825 self.args[i] = arg.coerce_to(base_type, env)
3826 elif dst_type.is_struct:
3827 if len(self.args) > len(dst_type.scope.var_entries):
3828 error(self.pos, "Too may members for '%s'" % dst_type)
3830 if len(self.args) < len(dst_type.scope.var_entries):
3831 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3832 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3833 if isinstance(arg, CoerceToPyTypeNode):
3835 self.args[i] = arg.coerce_to(member.type, env)
3836 self.type = dst_type
3838 self.type = error_type
3839 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3842 def release_temp(self, env):
3843 if self.type.is_array:
3844 # To be valid C++, we must allocate the memory on the stack
3845 # manually and be sure not to reuse it for something else.
3848 SequenceNode.release_temp(self, env)
3850 def calculate_constant_result(self):
3851 self.constant_result = [
3852 arg.constant_result for arg in self.args]
3854 def compile_time_value(self, denv):
3855 return self.compile_time_value_list(denv)
3857 def generate_operation_code(self, code):
3858 if self.type.is_pyobject:
3859 for err in self.obj_conversion_errors:
3861 code.putln("%s = PyList_New(%s); %s" %
3864 code.error_goto_if_null(self.result(), self.pos)))
3865 code.put_gotref(self.py_result())
3866 for i in range(len(self.args)):
3868 #if not arg.is_temp:
3869 if not arg.result_in_temp():
3870 code.put_incref(arg.result(), arg.ctype())
3871 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3875 code.put_giveref(arg.py_result())
3876 elif self.type.is_array:
3877 for i, arg in enumerate(self.args):
3878 code.putln("%s[%s] = %s;" % (
3882 elif self.type.is_struct:
3883 for arg, member in zip(self.args, self.type.scope.var_entries):
3884 code.putln("%s.%s = %s;" % (
3889 raise InternalError("List type never specified")
3891 def generate_subexpr_disposal_code(self, code):
3892 # We call generate_post_assignment_code here instead
3893 # of generate_disposal_code, because values were stored
3894 # in the list using a reference-stealing operation.
3895 for arg in self.args:
3896 arg.generate_post_assignment_code(code)
3897 # Should NOT call free_temps -- this is invoked by the default
3898 # generate_evaluation_code which will do that.
3901 class ScopedExprNode(ExprNode):
3902 # Abstract base class for ExprNodes that have their own local
3903 # scope, such as generator expressions.
3905 # expr_scope Scope the inner scope of the expression
3910 def analyse_types(self, env):
3911 # nothing to do here, the children will be analysed separately
3914 def analyse_expressions(self, env):
3915 # nothing to do here, the children will be analysed separately
3918 def analyse_scoped_expressions(self, env):
3919 # this is called with the expr_scope as env
3923 class ComprehensionNode(ExprNode): # (ScopedExprNode)
3924 subexprs = ["target"]
3925 child_attrs = ["loop", "append"]
3927 def infer_type(self, env):
3928 return self.target.infer_type(env)
3930 def analyse_declarations(self, env):
3931 self.append.target = self # this is used in the PyList_Append of the inner loop
3932 self.loop.analyse_declarations(env)
3933 # self.expr_scope = Symtab.GeneratorExpressionScope(env)
3934 # self.loop.analyse_declarations(self.expr_scope)
3936 def analyse_types(self, env):
3937 self.target.analyse_expressions(env)
3938 self.type = self.target.type
3939 self.loop.analyse_expressions(env)
3941 # def analyse_scoped_expressions(self, env):
3942 # self.loop.analyse_expressions(env)
3944 def may_be_none(self):
3947 def calculate_result_code(self):
3948 return self.target.result()
3950 def generate_result_code(self, code):
3951 self.generate_operation_code(code)
3953 def generate_operation_code(self, code):
3954 self.loop.generate_execution_code(code)
3956 def annotate(self, code):
3957 self.loop.annotate(code)
3960 class ComprehensionAppendNode(ExprNode):
3961 # Need to be careful to avoid infinite recursion:
3962 # target must not be in child_attrs/subexprs
3965 type = PyrexTypes.c_int_type
3967 def analyse_types(self, env):
3968 self.expr.analyse_types(env)
3969 if not self.expr.type.is_pyobject:
3970 self.expr = self.expr.coerce_to_pyobject(env)
3973 def generate_result_code(self, code):
3974 if self.target.type is list_type:
3975 function = "PyList_Append"
3976 elif self.target.type is set_type:
3977 function = "PySet_Add"
3979 raise InternalError(
3980 "Invalid type for comprehension node: %s" % self.target.type)
3982 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3985 self.target.result(),
3987 code.error_goto_if(self.result(), self.pos)))
3989 class DictComprehensionAppendNode(ComprehensionAppendNode):
3990 subexprs = ['key_expr', 'value_expr']
3992 def analyse_types(self, env):
3993 self.key_expr.analyse_types(env)
3994 if not self.key_expr.type.is_pyobject:
3995 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3996 self.value_expr.analyse_types(env)
3997 if not self.value_expr.type.is_pyobject:
3998 self.value_expr = self.value_expr.coerce_to_pyobject(env)
4001 def generate_result_code(self, code):
4002 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
4004 self.target.result(),
4005 self.key_expr.result(),
4006 self.value_expr.result(),
4007 code.error_goto_if(self.result(), self.pos)))
4010 class GeneratorExpressionNode(ScopedExprNode):
4011 # A generator expression, e.g. (i for i in range(10))
4013 # Result is a generator.
4015 # loop ForStatNode the for-loop, containing a YieldExprNode
4017 child_attrs = ["loop"]
4019 type = py_object_type
4021 def analyse_declarations(self, env):
4022 self.expr_scope = Symtab.GeneratorExpressionScope(env)
4023 self.loop.analyse_declarations(self.expr_scope)
4025 def analyse_types(self, env):
4028 def analyse_scoped_expressions(self, env):
4029 self.loop.analyse_expressions(env)
4031 def may_be_none(self):
4034 def annotate(self, code):
4035 self.loop.annotate(code)
4038 class InlinedGeneratorExpressionNode(GeneratorExpressionNode):
4039 # An inlined generator expression for which the result is
4040 # calculated inside of the loop. This will only be created by
4041 # transforms when replacing builtin calls on generator
4044 # loop ForStatNode the for-loop, not containing any YieldExprNodes
4045 # result_node ResultRefNode the reference to the result value temp
4046 # orig_func String the name of the builtin function this node replaces
4048 child_attrs = ["loop"]
4050 def analyse_types(self, env):
4051 self.type = self.result_node.type
4054 def coerce_to(self, dst_type, env):
4055 if self.orig_func == 'sum' and dst_type.is_numeric:
4056 # we can optimise by dropping the aggregation variable into C
4057 self.result_node.type = self.type = dst_type
4059 return GeneratorExpressionNode.coerce_to(self, dst_type, env)
4061 def generate_result_code(self, code):
4062 self.result_node.result_code = self.result()
4063 self.loop.generate_execution_code(code)
4066 class SetNode(ExprNode):
4073 gil_message = "Constructing Python set"
4075 def analyse_types(self, env):
4076 for i in range(len(self.args)):
4078 arg.analyse_types(env)
4079 self.args[i] = arg.coerce_to_pyobject(env)
4080 self.type = set_type
4083 def may_be_none(self):
4086 def calculate_constant_result(self):
4087 self.constant_result = set([
4088 arg.constant_result for arg in self.args])
4090 def compile_time_value(self, denv):
4091 values = [arg.compile_time_value(denv) for arg in self.args]
4094 except Exception, e:
4095 self.compile_time_value_error(e)
4097 def generate_evaluation_code(self, code):
4098 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
4099 self.allocate_temp_result(code)
4101 "%s = PySet_New(0); %s" % (
4103 code.error_goto_if_null(self.result(), self.pos)))
4104 code.put_gotref(self.py_result())
4105 for arg in self.args:
4106 arg.generate_evaluation_code(code)
4108 code.error_goto_if_neg(
4109 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
4111 arg.generate_disposal_code(code)
4112 arg.free_temps(code)
4115 class DictNode(ExprNode):
4116 # Dictionary constructor.
4118 # key_value_pairs [DictItemNode]
4120 # obj_conversion_errors [PyrexError] used internally
4122 subexprs = ['key_value_pairs']
4126 obj_conversion_errors = []
4128 def calculate_constant_result(self):
4129 self.constant_result = dict([
4130 item.constant_result for item in self.key_value_pairs])
4132 def compile_time_value(self, denv):
4133 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
4134 for item in self.key_value_pairs]
4137 except Exception, e:
4138 self.compile_time_value_error(e)
4140 def type_dependencies(self, env):
4143 def infer_type(self, env):
4144 # TOOD: Infer struct constructors.
4147 def analyse_types(self, env):
4149 for item in self.key_value_pairs:
4150 item.analyse_types(env)
4151 self.obj_conversion_errors = held_errors()
4152 release_errors(ignore=True)
4154 def may_be_none(self):
4157 def coerce_to(self, dst_type, env):
4158 if dst_type.is_pyobject:
4159 self.release_errors()
4160 if not self.type.subtype_of(dst_type):
4161 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
4162 elif dst_type.is_struct_or_union:
4163 self.type = dst_type
4164 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
4165 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
4166 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
4167 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
4168 for item in self.key_value_pairs:
4169 if isinstance(item.key, CoerceToPyTypeNode):
4170 item.key = item.key.arg
4171 if not isinstance(item.key, (UnicodeNode, StringNode, BytesNode)):
4172 error(item.key.pos, "Invalid struct field identifier")
4173 item.key = StringNode(item.key.pos, value="<error>")
4175 key = str(item.key.value) # converts string literals to unicode in Py3
4176 member = dst_type.scope.lookup_here(key)
4178 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key))
4181 if isinstance(value, CoerceToPyTypeNode):
4183 item.value = value.coerce_to(member.type, env)
4185 self.type = error_type
4186 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
4189 def release_errors(self):
4190 for err in self.obj_conversion_errors:
4192 self.obj_conversion_errors = []
4194 gil_message = "Constructing Python dict"
4196 def generate_evaluation_code(self, code):
4197 # Custom method used here because key-value
4198 # pairs are evaluated and used one at a time.
4199 code.mark_pos(self.pos)
4200 self.allocate_temp_result(code)
4201 if self.type.is_pyobject:
4202 self.release_errors()
4204 "%s = PyDict_New(); %s" % (
4206 code.error_goto_if_null(self.result(), self.pos)))
4207 code.put_gotref(self.py_result())
4208 for item in self.key_value_pairs:
4209 item.generate_evaluation_code(code)
4210 if self.type.is_pyobject:
4211 code.put_error_if_neg(self.pos,
4212 "PyDict_SetItem(%s, %s, %s)" % (
4214 item.key.py_result(),
4215 item.value.py_result()))
4217 code.putln("%s.%s = %s;" % (
4220 item.value.result()))
4221 item.generate_disposal_code(code)
4222 item.free_temps(code)
4224 def annotate(self, code):
4225 for item in self.key_value_pairs:
4228 class DictItemNode(ExprNode):
4229 # Represents a single item in a DictNode
4233 subexprs = ['key', 'value']
4235 nogil_check = None # Parent DictNode takes care of it
4237 def calculate_constant_result(self):
4238 self.constant_result = (
4239 self.key.constant_result, self.value.constant_result)
4241 def analyse_types(self, env):
4242 self.key.analyse_types(env)
4243 self.value.analyse_types(env)
4244 self.key = self.key.coerce_to_pyobject(env)
4245 self.value = self.value.coerce_to_pyobject(env)
4247 def generate_evaluation_code(self, code):
4248 self.key.generate_evaluation_code(code)
4249 self.value.generate_evaluation_code(code)
4251 def generate_disposal_code(self, code):
4252 self.key.generate_disposal_code(code)
4253 self.value.generate_disposal_code(code)
4255 def free_temps(self, code):
4256 self.key.free_temps(code)
4257 self.value.free_temps(code)
4260 return iter([self.key, self.value])
4263 class ClassNode(ExprNode):
4264 # Helper class used in the implementation of Python
4265 # class definitions. Constructs a class object given
4266 # a name, tuple of bases and class dictionary.
4268 # name EncodedString Name of the class
4269 # bases ExprNode Base class tuple
4270 # dict ExprNode Class dict (not owned by this node)
4271 # doc ExprNode or None Doc string
4272 # module_name string Name of defining module
4274 subexprs = ['bases', 'doc']
4276 def analyse_types(self, env):
4277 self.bases.analyse_types(env)
4279 self.doc.analyse_types(env)
4280 self.doc = self.doc.coerce_to_pyobject(env)
4281 self.module_name = env.global_scope().qualified_name
4282 self.type = py_object_type
4284 env.use_utility_code(create_class_utility_code);
4286 def may_be_none(self):
4289 gil_message = "Constructing Python class"
4291 def generate_result_code(self, code):
4292 cname = code.intern_identifier(self.name)
4294 code.put_error_if_neg(self.pos,
4295 'PyDict_SetItemString(%s, "__doc__", %s)' % (
4296 self.dict.py_result(),
4297 self.doc.py_result()))
4299 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
4301 self.bases.py_result(),
4302 self.dict.py_result(),
4305 code.error_goto_if_null(self.result(), self.pos)))
4306 code.put_gotref(self.py_result())
4308 class BoundMethodNode(ExprNode):
4309 # Helper class used in the implementation of Python
4310 # class definitions. Constructs an bound method
4311 # object from a class and a function.
4313 # function ExprNode Function object
4314 # self_object ExprNode self object
4316 subexprs = ['function']
4318 def analyse_types(self, env):
4319 self.function.analyse_types(env)
4320 self.type = py_object_type
4323 gil_message = "Constructing an bound method"
4325 def generate_result_code(self, code):
4327 "%s = PyMethod_New(%s, %s, (PyObject*)%s->ob_type); %s" % (
4329 self.function.py_result(),
4330 self.self_object.py_result(),
4331 self.self_object.py_result(),
4332 code.error_goto_if_null(self.result(), self.pos)))
4333 code.put_gotref(self.py_result())
4335 class UnboundMethodNode(ExprNode):
4336 # Helper class used in the implementation of Python
4337 # class definitions. Constructs an unbound method
4338 # object from a class and a function.
4340 # function ExprNode Function object
4342 type = py_object_type
4345 subexprs = ['function']
4347 def analyse_types(self, env):
4348 self.function.analyse_types(env)
4350 def may_be_none(self):
4353 gil_message = "Constructing an unbound method"
4355 def generate_result_code(self, code):
4356 class_cname = code.pyclass_stack[-1].classobj.result()
4358 "%s = PyMethod_New(%s, 0, %s); %s" % (
4360 self.function.py_result(),
4362 code.error_goto_if_null(self.result(), self.pos)))
4363 code.put_gotref(self.py_result())
4366 class PyCFunctionNode(ExprNode):
4367 # Helper class used in the implementation of Python
4368 # class definitions. Constructs a PyCFunction object
4369 # from a PyMethodDef struct.
4371 # pymethdef_cname string PyMethodDef structure
4372 # self_object ExprNode or None
4379 type = py_object_type
4382 def analyse_types(self, env):
4384 env.use_utility_code(binding_cfunc_utility_code)
4386 def may_be_none(self):
4389 gil_message = "Constructing Python function"
4391 def self_result_code(self):
4392 if self.self_object is None:
4393 self_result = "NULL"
4395 self_result = self.self_object.py_result()
4398 def generate_result_code(self, code):
4400 constructor = "%s_New" % Naming.binding_cfunc
4402 constructor = "PyCFunction_New"
4404 "%s = %s(&%s, %s); %s" % (
4407 self.pymethdef_cname,
4408 self.self_result_code(),
4409 code.error_goto_if_null(self.result(), self.pos)))
4410 code.put_gotref(self.py_result())
4412 class InnerFunctionNode(PyCFunctionNode):
4413 # Special PyCFunctionNode that depends on a closure class
4417 def self_result_code(self):
4418 return "((PyObject*)%s)" % Naming.cur_scope_cname
4420 class LambdaNode(InnerFunctionNode):
4421 # Lambda expression node (only used as a function reference)
4423 # args [CArgDeclNode] formal arguments
4424 # star_arg PyArgDeclNode or None * argument
4425 # starstar_arg PyArgDeclNode or None ** argument
4426 # lambda_name string a module-globally unique lambda name
4427 # result_expr ExprNode
4428 # def_node DefNode the underlying function 'def' node
4430 child_attrs = ['def_node']
4433 name = StringEncoding.EncodedString('<lambda>')
4435 def analyse_declarations(self, env):
4436 #self.def_node.needs_closure = self.needs_closure
4437 self.def_node.analyse_declarations(env)
4438 self.pymethdef_cname = self.def_node.entry.pymethdef_cname
4439 env.add_lambda_def(self.def_node)
4441 class YieldExprNode(ExprNode):
4442 # Yield expression node
4444 # arg ExprNode the value to return from the generator
4445 # label_name string name of the C label used for this yield
4448 type = py_object_type
4450 def analyse_types(self, env):
4452 if self.arg is not None:
4453 self.arg.analyse_types(env)
4454 if not self.arg.type.is_pyobject:
4455 self.arg = self.arg.coerce_to_pyobject(env)
4456 error(self.pos, "Generators are not supported")
4458 def generate_result_code(self, code):
4459 self.label_name = code.new_label('resume_from_yield')
4460 code.use_label(self.label_name)
4461 code.putln("/* FIXME: save temporary variables */")
4462 code.putln("/* FIXME: return from function, yielding value */")
4463 code.put_label(self.label_name)
4464 code.putln("/* FIXME: restore temporary variables and */")
4465 code.putln("/* FIXME: extract sent value from closure */")
4468 #-------------------------------------------------------------------
4470 # Unary operator nodes
4472 #-------------------------------------------------------------------
4474 compile_time_unary_operators = {
4475 'not': operator.not_,
4481 class UnopNode(ExprNode):
4485 # Processing during analyse_expressions phase:
4487 # analyse_c_operation
4488 # Called when the operand is not a pyobject.
4489 # - Check operand type and coerce if needed.
4490 # - Determine result type and result code fragment.
4491 # - Allocate temporary for result if needed.
4493 subexprs = ['operand']
4496 def calculate_constant_result(self):
4497 func = compile_time_unary_operators[self.operator]
4498 self.constant_result = func(self.operand.constant_result)
4500 def compile_time_value(self, denv):
4501 func = compile_time_unary_operators.get(self.operator)
4504 "Unary '%s' not supported in compile-time expression"
4506 operand = self.operand.compile_time_value(denv)
4508 return func(operand)
4509 except Exception, e:
4510 self.compile_time_value_error(e)
4512 def infer_type(self, env):
4513 return self.operand.infer_type(env)
4515 def analyse_types(self, env):
4516 self.operand.analyse_types(env)
4517 if self.is_py_operation():
4518 self.coerce_operand_to_pyobject(env)
4519 self.type = py_object_type
4521 elif self.is_cpp_operation():
4522 self.analyse_cpp_operation(env)
4524 self.analyse_c_operation(env)
4526 def check_const(self):
4527 return self.operand.check_const()
4529 def is_py_operation(self):
4530 return self.operand.type.is_pyobject
4532 def nogil_check(self, env):
4533 if self.is_py_operation():
4536 def is_cpp_operation(self):
4537 type = self.operand.type
4538 return type.is_cpp_class
4540 def coerce_operand_to_pyobject(self, env):
4541 self.operand = self.operand.coerce_to_pyobject(env)
4543 def generate_result_code(self, code):
4544 if self.operand.type.is_pyobject:
4545 self.generate_py_operation_code(code)
4547 def generate_py_operation_code(self, code):
4548 function = self.py_operation_function()
4550 "%s = %s(%s); %s" % (
4553 self.operand.py_result(),
4554 code.error_goto_if_null(self.result(), self.pos)))
4555 code.put_gotref(self.py_result())
4557 def type_error(self):
4558 if not self.operand.type.is_error:
4559 error(self.pos, "Invalid operand type for '%s' (%s)" %
4560 (self.operator, self.operand.type))
4561 self.type = PyrexTypes.error_type
4563 def analyse_cpp_operation(self, env):
4564 type = self.operand.type
4566 type = type.base_type
4567 function = type.scope.lookup("operator%s" % self.operator)
4569 error(self.pos, "'%s' operator not defined for %s"
4570 % (self.operator, type))
4573 func_type = function.type
4574 if func_type.is_ptr:
4575 func_type = func_type.base_type
4576 self.type = func_type.return_type
4579 class NotNode(ExprNode):
4584 type = PyrexTypes.c_bint_type
4586 subexprs = ['operand']
4588 def calculate_constant_result(self):
4589 self.constant_result = not self.operand.constant_result
4591 def compile_time_value(self, denv):
4592 operand = self.operand.compile_time_value(denv)
4595 except Exception, e:
4596 self.compile_time_value_error(e)
4598 def infer_type(self, env):
4599 return PyrexTypes.c_bint_type
4601 def analyse_types(self, env):
4602 self.operand.analyse_types(env)
4603 self.operand = self.operand.coerce_to_boolean(env)
4605 def calculate_result_code(self):
4606 return "(!%s)" % self.operand.result()
4608 def generate_result_code(self, code):
4612 class UnaryPlusNode(UnopNode):
4613 # unary '+' operator
4617 def analyse_c_operation(self, env):
4618 self.type = self.operand.type
4620 def py_operation_function(self):
4621 return "PyNumber_Positive"
4623 def calculate_result_code(self):
4624 if self.is_cpp_operation():
4625 return "(+%s)" % self.operand.result()
4627 return self.operand.result()
4630 class UnaryMinusNode(UnopNode):
4631 # unary '-' operator
4635 def analyse_c_operation(self, env):
4636 if self.operand.type.is_numeric:
4637 self.type = self.operand.type
4640 if self.type.is_complex:
4643 def py_operation_function(self):
4644 return "PyNumber_Negative"
4646 def calculate_result_code(self):
4648 return "(-%s)" % self.operand.result()
4650 return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result())
4652 def get_constant_c_result_code(self):
4653 value = self.operand.get_constant_c_result_code()
4655 return "(-%s)" % (value)
4657 class TildeNode(UnopNode):
4658 # unary '~' operator
4660 def analyse_c_operation(self, env):
4661 if self.operand.type.is_int:
4662 self.type = self.operand.type
4666 def py_operation_function(self):
4667 return "PyNumber_Invert"
4669 def calculate_result_code(self):
4670 return "(~%s)" % self.operand.result()
4673 class CUnopNode(UnopNode):
4675 def is_py_operation(self):
4678 class DereferenceNode(CUnopNode):
4683 def analyse_c_operation(self, env):
4684 if self.operand.type.is_ptr:
4685 self.type = self.operand.type.base_type
4689 def calculate_result_code(self):
4690 return "(*%s)" % self.operand.result()
4693 class DecrementIncrementNode(CUnopNode):
4694 # unary ++/-- operator
4696 def analyse_c_operation(self, env):
4697 if self.operand.type.is_ptr or self.operand.type.is_numeric:
4698 self.type = self.operand.type
4702 def calculate_result_code(self):
4704 return "(%s%s)" % (self.operator, self.operand.result())
4706 return "(%s%s)" % (self.operand.result(), self.operator)
4708 def inc_dec_constructor(is_prefix, operator):
4709 return lambda pos, **kwds: DecrementIncrementNode(pos, is_prefix=is_prefix, operator=operator, **kwds)
4712 class AmpersandNode(ExprNode):
4713 # The C address-of operator.
4717 subexprs = ['operand']
4719 def infer_type(self, env):
4720 return PyrexTypes.c_ptr_type(self.operand.infer_type(env))
4722 def analyse_types(self, env):
4723 self.operand.analyse_types(env)
4724 argtype = self.operand.type
4725 if not (argtype.is_cfunction or self.operand.is_lvalue()):
4726 self.error("Taking address of non-lvalue")
4728 if argtype.is_pyobject:
4729 self.error("Cannot take address of Python variable")
4731 self.type = PyrexTypes.c_ptr_type(argtype)
4733 def check_const(self):
4734 return self.operand.check_const_addr()
4736 def error(self, mess):
4737 error(self.pos, mess)
4738 self.type = PyrexTypes.error_type
4739 self.result_code = "<error>"
4741 def calculate_result_code(self):
4742 return "(&%s)" % self.operand.result()
4744 def generate_result_code(self, code):
4748 unop_node_classes = {
4750 "-": UnaryMinusNode,
4754 def unop_node(pos, operator, operand):
4755 # Construct unnop node of appropriate class for
4757 if isinstance(operand, IntNode) and operator == '-':
4758 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
4759 elif isinstance(operand, UnopNode) and operand.operator == operator:
4760 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
4761 return unop_node_classes[operator](pos,
4762 operator = operator,
4766 class TypecastNode(ExprNode):
4770 # base_type CBaseTypeNode
4771 # declarator CDeclaratorNode
4773 # If used from a transform, one can if wanted specify the attribute
4774 # "type" directly and leave base_type and declarator to None
4776 subexprs = ['operand']
4777 base_type = declarator = type = None
4779 def type_dependencies(self, env):
4782 def infer_type(self, env):
4783 if self.type is None:
4784 base_type = self.base_type.analyse(env)
4785 _, self.type = self.declarator.analyse(base_type, env)
4788 def analyse_types(self, env):
4789 if self.type is None:
4790 base_type = self.base_type.analyse(env)
4791 _, self.type = self.declarator.analyse(base_type, env)
4792 if self.type.is_cfunction:
4794 "Cannot cast to a function type")
4795 self.type = PyrexTypes.error_type
4796 self.operand.analyse_types(env)
4797 to_py = self.type.is_pyobject
4798 from_py = self.operand.type.is_pyobject
4799 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
4800 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
4801 if to_py and not from_py:
4802 if self.type is bytes_type and self.operand.type.is_int:
4803 # FIXME: the type cast node isn't needed in this case
4804 # and can be dropped once analyse_types() can return a
4806 self.operand = CoerceIntToBytesNode(self.operand, env)
4807 elif self.operand.type.can_coerce_to_pyobject(env):
4808 self.result_ctype = py_object_type
4809 self.operand = self.operand.coerce_to_pyobject(env)
4811 if self.operand.type.is_ptr:
4812 if not (self.operand.type.base_type.is_void or self.operand.type.base_type.is_struct):
4813 error(self.pos, "Python objects cannot be cast from pointers of primitive types")
4815 # Should this be an error?
4816 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
4817 self.operand = self.operand.coerce_to_simple(env)
4818 elif from_py and not to_py:
4819 if self.type.create_from_py_utility_code(env):
4820 self.operand = self.operand.coerce_to(self.type, env)
4821 elif self.type.is_ptr:
4822 if not (self.type.base_type.is_void or self.type.base_type.is_struct):
4823 error(self.pos, "Python objects cannot be cast to pointers of primitive types")
4825 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
4826 elif from_py and to_py:
4827 if self.typecheck and self.type.is_extension_type:
4828 self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True)
4829 elif self.type.is_complex and self.operand.type.is_complex:
4830 self.operand = self.operand.coerce_to_simple(env)
4832 def nogil_check(self, env):
4833 if self.type and self.type.is_pyobject and self.is_temp:
4836 def check_const(self):
4837 return self.operand.check_const()
4839 def calculate_constant_result(self):
4840 # we usually do not know the result of a type cast at code
4844 def calculate_result_code(self):
4845 if self.type.is_complex:
4846 operand_result = self.operand.result()
4847 if self.operand.type.is_complex:
4848 real_part = self.type.real_type.cast_code("__Pyx_CREAL(%s)" % operand_result)
4849 imag_part = self.type.real_type.cast_code("__Pyx_CIMAG(%s)" % operand_result)
4851 real_part = self.type.real_type.cast_code(operand_result)
4853 return "%s(%s, %s)" % (
4854 self.type.from_parts,
4858 return self.type.cast_code(self.operand.result())
4860 def get_constant_c_result_code(self):
4861 operand_result = self.operand.get_constant_c_result_code()
4863 return self.type.cast_code(operand_result)
4865 def result_as(self, type):
4866 if self.type.is_pyobject and not self.is_temp:
4867 # Optimise away some unnecessary casting
4868 return self.operand.result_as(type)
4870 return ExprNode.result_as(self, type)
4872 def generate_result_code(self, code):
4875 "%s = (PyObject *)%s;" % (
4877 self.operand.result()))
4878 code.put_incref(self.result(), self.ctype())
4881 class SizeofNode(ExprNode):
4882 # Abstract base class for sizeof(x) expression nodes.
4884 type = PyrexTypes.c_size_t_type
4886 def check_const(self):
4889 def generate_result_code(self, code):
4893 class SizeofTypeNode(SizeofNode):
4894 # C sizeof function applied to a type
4896 # base_type CBaseTypeNode
4897 # declarator CDeclaratorNode
4902 def analyse_types(self, env):
4903 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
4904 # this could be better handled by more uniformly treating types as runtime-available objects
4905 if 0 and self.base_type.module_path:
4906 path = self.base_type.module_path
4907 obj = env.lookup(path[0])
4908 if obj.as_module is None:
4909 operand = NameNode(pos=self.pos, name=path[0])
4910 for attr in path[1:]:
4911 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
4912 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
4913 self.operand = operand
4914 self.__class__ = SizeofVarNode
4915 self.analyse_types(env)
4917 if self.arg_type is None:
4918 base_type = self.base_type.analyse(env)
4919 _, arg_type = self.declarator.analyse(base_type, env)
4920 self.arg_type = arg_type
4923 def check_type(self):
4924 arg_type = self.arg_type
4925 if arg_type.is_pyobject and not arg_type.is_extension_type:
4926 error(self.pos, "Cannot take sizeof Python object")
4927 elif arg_type.is_void:
4928 error(self.pos, "Cannot take sizeof void")
4929 elif not arg_type.is_complete():
4930 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
4932 def calculate_result_code(self):
4933 if self.arg_type.is_extension_type:
4934 # the size of the pointer is boring
4935 # we want the size of the actual struct
4936 arg_code = self.arg_type.declaration_code("", deref=1)
4938 arg_code = self.arg_type.declaration_code("")
4939 return "(sizeof(%s))" % arg_code
4942 class SizeofVarNode(SizeofNode):
4943 # C sizeof function applied to a variable
4947 subexprs = ['operand']
4949 def analyse_types(self, env):
4950 # We may actually be looking at a type rather than a variable...
4951 # If we are, traditional analysis would fail...
4952 operand_as_type = self.operand.analyse_as_type(env)
4954 self.arg_type = operand_as_type
4955 self.__class__ = SizeofTypeNode
4958 self.operand.analyse_types(env)
4960 def calculate_result_code(self):
4961 return "(sizeof(%s))" % self.operand.result()
4963 def generate_result_code(self, code):
4966 class TypeofNode(ExprNode):
4967 # Compile-time type of an expression, as a string.
4970 # literal StringNode # internal
4973 type = py_object_type
4975 subexprs = ['literal'] # 'operand' will be ignored after type analysis!
4977 def analyse_types(self, env):
4978 self.operand.analyse_types(env)
4979 self.literal = StringNode(
4980 self.pos, value=StringEncoding.EncodedString(str(self.operand.type)))
4981 self.literal.analyse_types(env)
4982 self.literal = self.literal.coerce_to_pyobject(env)
4984 def may_be_none(self):
4987 def generate_evaluation_code(self, code):
4988 self.literal.generate_evaluation_code(code)
4990 def calculate_result_code(self):
4991 return self.literal.calculate_result_code()
4993 #-------------------------------------------------------------------
4995 # Binary operator nodes
4997 #-------------------------------------------------------------------
4999 def _not_in(x, seq):
5002 compile_time_binary_operators = {
5010 'is_not': operator.is_not,
5013 '/': operator.truediv,
5014 '//': operator.floordiv,
5015 '<<': operator.lshift,
5020 '>>': operator.rshift,
5023 'in': operator.contains,
5027 def get_compile_time_binop(node):
5028 func = compile_time_binary_operators.get(node.operator)
5031 "Binary '%s' not supported in compile-time expression"
5035 class BinopNode(ExprNode):
5040 # Processing during analyse_expressions phase:
5042 # analyse_c_operation
5043 # Called when neither operand is a pyobject.
5044 # - Check operand types and coerce if needed.
5045 # - Determine result type and result code fragment.
5046 # - Allocate temporary for result if needed.
5048 subexprs = ['operand1', 'operand2']
5050 def calculate_constant_result(self):
5051 func = compile_time_binary_operators[self.operator]
5052 self.constant_result = func(
5053 self.operand1.constant_result,
5054 self.operand2.constant_result)
5056 def compile_time_value(self, denv):
5057 func = get_compile_time_binop(self)
5058 operand1 = self.operand1.compile_time_value(denv)
5059 operand2 = self.operand2.compile_time_value(denv)
5061 return func(operand1, operand2)
5062 except Exception, e:
5063 self.compile_time_value_error(e)
5065 def infer_type(self, env):
5066 return self.result_type(self.operand1.infer_type(env),
5067 self.operand2.infer_type(env))
5069 def analyse_types(self, env):
5070 self.operand1.analyse_types(env)
5071 self.operand2.analyse_types(env)
5072 if self.is_py_operation():
5073 self.coerce_operands_to_pyobjects(env)
5074 self.type = self.result_type(self.operand1.type,
5076 assert self.type.is_pyobject
5078 elif self.is_cpp_operation():
5079 self.analyse_cpp_operation(env)
5081 self.analyse_c_operation(env)
5083 def is_py_operation(self):
5084 return self.is_py_operation_types(self.operand1.type, self.operand2.type)
5086 def is_py_operation_types(self, type1, type2):
5087 return type1.is_pyobject or type2.is_pyobject
5089 def is_cpp_operation(self):
5090 return (self.operand1.type.is_cpp_class
5091 or self.operand2.type.is_cpp_class)
5093 def analyse_cpp_operation(self, env):
5094 type1 = self.operand1.type
5095 type2 = self.operand2.type
5096 entry = env.lookup_operator(self.operator, [self.operand1, self.operand2])
5100 func_type = entry.type
5101 if func_type.is_ptr:
5102 func_type = func_type.base_type
5103 if len(func_type.args) == 1:
5104 self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env)
5106 self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env)
5107 self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env)
5108 self.type = func_type.return_type
5110 def result_type(self, type1, type2):
5111 if self.is_py_operation_types(type1, type2):
5113 type2 = Builtin.bytes_type
5115 type1 = Builtin.bytes_type
5116 elif self.operator == '%' \
5117 and type1 in (Builtin.str_type, Builtin.unicode_type):
5118 # note that b'%s' % b'abc' doesn't work in Py3
5120 if type1.is_builtin_type:
5122 if self.operator in '**%+|&^':
5123 # FIXME: at least these operators should be safe - others?
5125 elif self.operator == '*':
5126 if type1 in (Builtin.bytes_type, Builtin.str_type, Builtin.unicode_type):
5128 # multiplication of containers/numbers with an
5129 # integer value always (?) returns the same type
5132 elif type2.is_builtin_type and type1.is_int and self.operator == '*':
5133 # multiplication of containers/numbers with an
5134 # integer value always (?) returns the same type
5136 return py_object_type
5138 return self.compute_c_result_type(type1, type2)
5140 def nogil_check(self, env):
5141 if self.is_py_operation():
5144 def coerce_operands_to_pyobjects(self, env):
5145 self.operand1 = self.operand1.coerce_to_pyobject(env)
5146 self.operand2 = self.operand2.coerce_to_pyobject(env)
5148 def check_const(self):
5149 return self.operand1.check_const() and self.operand2.check_const()
5151 def generate_result_code(self, code):
5152 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
5153 if self.operand1.type.is_pyobject:
5154 function = self.py_operation_function()
5155 if function == "PyNumber_Power":
5156 extra_args = ", Py_None"
5160 "%s = %s(%s, %s%s); %s" % (
5163 self.operand1.py_result(),
5164 self.operand2.py_result(),
5166 code.error_goto_if_null(self.result(), self.pos)))
5167 code.put_gotref(self.py_result())
5169 def type_error(self):
5170 if not (self.operand1.type.is_error
5171 or self.operand2.type.is_error):
5172 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
5173 (self.operator, self.operand1.type,
5174 self.operand2.type))
5175 self.type = PyrexTypes.error_type
5178 class NumBinopNode(BinopNode):
5179 # Binary operation taking numeric arguments.
5183 def analyse_c_operation(self, env):
5184 type1 = self.operand1.type
5185 type2 = self.operand2.type
5186 self.type = self.compute_c_result_type(type1, type2)
5190 if self.type.is_complex:
5193 self.operand1 = self.operand1.coerce_to(self.type, env)
5194 self.operand2 = self.operand2.coerce_to(self.type, env)
5196 def compute_c_result_type(self, type1, type2):
5197 if self.c_types_okay(type1, type2):
5198 return PyrexTypes.widest_numeric_type(type1, type2)
5202 def get_constant_c_result_code(self):
5203 value1 = self.operand1.get_constant_c_result_code()
5204 value2 = self.operand2.get_constant_c_result_code()
5205 if value1 and value2:
5206 return "(%s %s %s)" % (value1, self.operator, value2)
5210 def c_types_okay(self, type1, type2):
5211 #print "NumBinopNode.c_types_okay:", type1, type2 ###
5212 return (type1.is_numeric or type1.is_enum) \
5213 and (type2.is_numeric or type2.is_enum)
5215 def calculate_result_code(self):
5217 return "(%s %s %s)" % (
5218 self.operand1.result(),
5220 self.operand2.result())
5222 func = self.type.binary_op(self.operator)
5224 error(self.pos, "binary operator %s not supported for %s" % (self.operator, self.type))
5225 return "%s(%s, %s)" % (
5227 self.operand1.result(),
5228 self.operand2.result())
5230 def is_py_operation_types(self, type1, type2):
5231 return (type1 is PyrexTypes.c_py_unicode_type or
5232 type2 is PyrexTypes.c_py_unicode_type or
5233 BinopNode.is_py_operation_types(self, type1, type2))
5235 def py_operation_function(self):
5236 return self.py_functions[self.operator]
5240 "^": "PyNumber_Xor",
5241 "&": "PyNumber_And",
5242 "<<": "PyNumber_Lshift",
5243 ">>": "PyNumber_Rshift",
5244 "+": "PyNumber_Add",
5245 "-": "PyNumber_Subtract",
5246 "*": "PyNumber_Multiply",
5247 "/": "__Pyx_PyNumber_Divide",
5248 "//": "PyNumber_FloorDivide",
5249 "%": "PyNumber_Remainder",
5250 "**": "PyNumber_Power"
5254 class IntBinopNode(NumBinopNode):
5255 # Binary operation taking integer arguments.
5257 def c_types_okay(self, type1, type2):
5258 #print "IntBinopNode.c_types_okay:", type1, type2 ###
5259 return (type1.is_int or type1.is_enum) \
5260 and (type2.is_int or type2.is_enum)
5263 class AddNode(NumBinopNode):
5266 def is_py_operation_types(self, type1, type2):
5267 if type1.is_string and type2.is_string:
5270 return NumBinopNode.is_py_operation_types(self, type1, type2)
5272 def compute_c_result_type(self, type1, type2):
5273 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
5274 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
5276 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
5279 return NumBinopNode.compute_c_result_type(
5283 class SubNode(NumBinopNode):
5286 def compute_c_result_type(self, type1, type2):
5287 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
5289 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
5290 return PyrexTypes.c_int_type
5292 return NumBinopNode.compute_c_result_type(
5296 class MulNode(NumBinopNode):
5299 def is_py_operation_types(self, type1, type2):
5300 if (type1.is_string and type2.is_int) \
5301 or (type2.is_string and type1.is_int):
5304 return NumBinopNode.is_py_operation_types(self, type1, type2)
5307 class DivNode(NumBinopNode):
5308 # '/' or '//' operator.
5311 truedivision = None # == "unknown" if operator == '/'
5312 ctruedivision = False
5313 cdivision_warnings = False
5314 zerodivision_check = None
5316 def find_compile_time_binary_operator(self, op1, op2):
5317 func = compile_time_binary_operators[self.operator]
5318 if self.operator == '/' and self.truedivision is None:
5319 # => true div for floats, floor div for integers
5320 if isinstance(op1, (int,long)) and isinstance(op2, (int,long)):
5321 func = compile_time_binary_operators['//']
5324 def calculate_constant_result(self):
5325 op1 = self.operand1.constant_result
5326 op2 = self.operand2.constant_result
5327 func = self.find_compile_time_binary_operator(op1, op2)
5328 self.constant_result = func(
5329 self.operand1.constant_result,
5330 self.operand2.constant_result)
5332 def compile_time_value(self, denv):
5333 operand1 = self.operand1.compile_time_value(denv)
5334 operand2 = self.operand2.compile_time_value(denv)
5336 func = self.find_compile_time_binary_operator(
5337 self, operand1, operand2)
5338 return func(operand1, operand2)
5339 except Exception, e:
5340 self.compile_time_value_error(e)
5342 def analyse_types(self, env):
5343 if self.cdivision or env.directives['cdivision']:
5344 self.ctruedivision = False
5346 self.ctruedivision = self.truedivision
5347 NumBinopNode.analyse_types(self, env)
5348 if self.is_cpp_operation():
5349 self.cdivision = True
5350 if not self.type.is_pyobject:
5351 self.zerodivision_check = (
5352 self.cdivision is None and not env.directives['cdivision']
5353 and (not self.operand2.has_constant_result() or
5354 self.operand2.constant_result == 0))
5355 if self.zerodivision_check or env.directives['cdivision_warnings']:
5356 # Need to check ahead of time to warn or raise zero division error
5357 self.operand1 = self.operand1.coerce_to_simple(env)
5358 self.operand2 = self.operand2.coerce_to_simple(env)
5360 error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
5362 def compute_c_result_type(self, type1, type2):
5363 if self.operator == '/' and self.ctruedivision:
5364 if not type1.is_float and not type2.is_float:
5365 widest_type = PyrexTypes.widest_numeric_type(type1, PyrexTypes.c_double_type)
5366 widest_type = PyrexTypes.widest_numeric_type(type2, widest_type)
5368 return NumBinopNode.compute_c_result_type(self, type1, type2)
5370 def zero_division_message(self):
5371 if self.type.is_int:
5372 return "integer division or modulo by zero"
5374 return "float division"
5376 def generate_evaluation_code(self, code):
5377 if not self.type.is_pyobject and not self.type.is_complex:
5378 if self.cdivision is None:
5379 self.cdivision = (code.globalstate.directives['cdivision']
5380 or not self.type.signed
5381 or self.type.is_float)
5382 if not self.cdivision:
5383 code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
5384 NumBinopNode.generate_evaluation_code(self, code)
5385 self.generate_div_warning_code(code)
5387 def generate_div_warning_code(self, code):
5388 if not self.type.is_pyobject:
5389 if self.zerodivision_check:
5391 zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.operand2.result())
5393 zero_test = "%s == 0" % self.operand2.result()
5394 code.putln("if (unlikely(%s)) {" % zero_test)
5395 code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
5396 code.putln(code.error_goto(self.pos))
5398 if self.type.is_int and self.type.signed and self.operator != '%':
5399 code.globalstate.use_utility_code(division_overflow_test_code)
5400 code.putln("else if (sizeof(%s) == sizeof(long) && unlikely(%s == -1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % (
5401 self.type.declaration_code(''),
5402 self.operand2.result(),
5403 self.operand1.result()))
5404 code.putln('PyErr_Format(PyExc_OverflowError, "value too large to perform division");')
5405 code.putln(code.error_goto(self.pos))
5407 if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
5408 code.globalstate.use_utility_code(cdivision_warning_utility_code)
5409 code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
5410 self.operand1.result(),
5411 self.operand2.result()))
5412 code.putln(code.set_error_info(self.pos));
5413 code.put("if (__Pyx_cdivision_warning()) ")
5414 code.put_goto(code.error_label)
5417 def calculate_result_code(self):
5418 if self.type.is_complex:
5419 return NumBinopNode.calculate_result_code(self)
5420 elif self.type.is_float and self.operator == '//':
5421 return "floor(%s / %s)" % (
5422 self.operand1.result(),
5423 self.operand2.result())
5424 elif self.truedivision or self.cdivision:
5425 op1 = self.operand1.result()
5426 op2 = self.operand2.result()
5427 if self.truedivision:
5428 if self.type != self.operand1.type:
5429 op1 = self.type.cast_code(op1)
5430 if self.type != self.operand2.type:
5431 op2 = self.type.cast_code(op2)
5432 return "(%s / %s)" % (op1, op2)
5434 return "__Pyx_div_%s(%s, %s)" % (
5435 self.type.specialization_name(),
5436 self.operand1.result(),
5437 self.operand2.result())
5440 class ModNode(DivNode):
5443 def is_py_operation_types(self, type1, type2):
5444 return (type1.is_string
5446 or NumBinopNode.is_py_operation_types(self, type1, type2))
5448 def zero_division_message(self):
5449 if self.type.is_int:
5450 return "integer division or modulo by zero"
5452 return "float divmod()"
5454 def generate_evaluation_code(self, code):
5455 if not self.type.is_pyobject:
5456 if self.cdivision is None:
5457 self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
5458 if not self.cdivision:
5459 if self.type.is_int:
5460 code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
5462 code.globalstate.use_utility_code(
5463 mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
5464 NumBinopNode.generate_evaluation_code(self, code)
5465 self.generate_div_warning_code(code)
5467 def calculate_result_code(self):
5469 if self.type.is_float:
5470 return "fmod%s(%s, %s)" % (
5471 self.type.math_h_modifier,
5472 self.operand1.result(),
5473 self.operand2.result())
5475 return "(%s %% %s)" % (
5476 self.operand1.result(),
5477 self.operand2.result())
5479 return "__Pyx_mod_%s(%s, %s)" % (
5480 self.type.specialization_name(),
5481 self.operand1.result(),
5482 self.operand2.result())
5484 class PowNode(NumBinopNode):
5487 def analyse_c_operation(self, env):
5488 NumBinopNode.analyse_c_operation(self, env)
5489 if self.type.is_complex:
5490 error(self.pos, "complex powers not yet supported")
5491 self.pow_func = "<error>"
5492 elif self.type.is_float:
5493 self.pow_func = "pow"
5495 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
5496 env.use_utility_code(
5497 int_pow_utility_code.specialize(func_name=self.pow_func,
5498 type=self.type.declaration_code('')))
5500 def calculate_result_code(self):
5501 return "%s(%s, %s)" % (
5503 self.operand1.result(),
5504 self.operand2.result())
5507 # Note: This class is temporary "shut down" into an ineffective mode temp
5510 # More sophisticated temp reuse was going on before,
5511 # one could have a look at adding this again after /all/ classes
5512 # are converted to the new temp scheme. (The temp juggling cannot work
5514 class BoolBinopNode(ExprNode):
5515 # Short-circuiting boolean operation.
5521 subexprs = ['operand1', 'operand2']
5523 def infer_type(self, env):
5524 type1 = self.operand1.infer_type(env)
5525 type2 = self.operand2.infer_type(env)
5526 return PyrexTypes.independent_spanning_type(type1, type2)
5528 def calculate_constant_result(self):
5529 if self.operator == 'and':
5530 self.constant_result = \
5531 self.operand1.constant_result and \
5532 self.operand2.constant_result
5534 self.constant_result = \
5535 self.operand1.constant_result or \
5536 self.operand2.constant_result
5538 def compile_time_value(self, denv):
5539 if self.operator == 'and':
5540 return self.operand1.compile_time_value(denv) \
5541 and self.operand2.compile_time_value(denv)
5543 return self.operand1.compile_time_value(denv) \
5544 or self.operand2.compile_time_value(denv)
5546 def coerce_to_boolean(self, env):
5547 self.operand1 = self.operand1.coerce_to_boolean(env)
5548 self.operand2 = self.operand2.coerce_to_boolean(env)
5549 self.type = PyrexTypes.c_bint_type
5552 def analyse_types(self, env):
5553 self.operand1.analyse_types(env)
5554 self.operand2.analyse_types(env)
5555 self.type = PyrexTypes.independent_spanning_type(self.operand1.type, self.operand2.type)
5556 self.operand1 = self.operand1.coerce_to(self.type, env)
5557 self.operand2 = self.operand2.coerce_to(self.type, env)
5559 # For what we're about to do, it's vital that
5560 # both operands be temp nodes.
5561 self.operand1 = self.operand1.coerce_to_simple(env)
5562 self.operand2 = self.operand2.coerce_to_simple(env)
5565 gil_message = "Truth-testing Python object"
5567 def check_const(self):
5568 return self.operand1.check_const() and self.operand2.check_const()
5570 def generate_evaluation_code(self, code):
5571 code.mark_pos(self.pos)
5572 self.operand1.generate_evaluation_code(code)
5573 test_result, uses_temp = self.generate_operand1_test(code)
5574 if self.operator == 'and':
5583 code.funcstate.release_temp(test_result)
5584 self.operand1.generate_disposal_code(code)
5585 self.operand2.generate_evaluation_code(code)
5586 self.allocate_temp_result(code)
5587 self.operand2.make_owned_reference(code)
5588 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
5589 self.operand2.generate_post_assignment_code(code)
5590 self.operand2.free_temps(code)
5591 code.putln("} else {")
5592 self.operand1.make_owned_reference(code)
5593 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
5594 self.operand1.generate_post_assignment_code(code)
5595 self.operand1.free_temps(code)
5598 def generate_operand1_test(self, code):
5599 # Generate code to test the truth of the first operand.
5600 if self.type.is_pyobject:
5601 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
5604 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5606 self.operand1.py_result(),
5607 code.error_goto_if_neg(test_result, self.pos)))
5609 test_result = self.operand1.result()
5610 return (test_result, self.type.is_pyobject)
5613 class CondExprNode(ExprNode):
5614 # Short-circuiting conditional expression.
5618 # false_val ExprNode
5623 subexprs = ['test', 'true_val', 'false_val']
5625 def type_dependencies(self, env):
5626 return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
5628 def infer_type(self, env):
5629 return PyrexTypes.independent_spanning_type(self.true_val.infer_type(env),
5630 self.false_val.infer_type(env))
5632 def calculate_constant_result(self):
5633 if self.test.constant_result:
5634 self.constant_result = self.true_val.constant_result
5636 self.constant_result = self.false_val.constant_result
5638 def analyse_types(self, env):
5639 self.test.analyse_types(env)
5640 self.test = self.test.coerce_to_boolean(env)
5641 self.true_val.analyse_types(env)
5642 self.false_val.analyse_types(env)
5643 self.type = PyrexTypes.independent_spanning_type(self.true_val.type, self.false_val.type)
5644 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
5645 self.true_val = self.true_val.coerce_to(self.type, env)
5646 self.false_val = self.false_val.coerce_to(self.type, env)
5648 if self.type == PyrexTypes.error_type:
5651 def type_error(self):
5652 if not (self.true_val.type.is_error or self.false_val.type.is_error):
5653 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
5654 (self.true_val.type, self.false_val.type))
5655 self.type = PyrexTypes.error_type
5657 def check_const(self):
5658 return (self.test.check_const()
5659 and self.true_val.check_const()
5660 and self.false_val.check_const())
5662 def generate_evaluation_code(self, code):
5663 # Because subexprs may not be evaluated we can use a more optimal
5664 # subexpr allocation strategy than the default, so override evaluation_code.
5666 code.mark_pos(self.pos)
5667 self.allocate_temp_result(code)
5668 self.test.generate_evaluation_code(code)
5669 code.putln("if (%s) {" % self.test.result() )
5670 self.eval_and_get(code, self.true_val)
5671 code.putln("} else {")
5672 self.eval_and_get(code, self.false_val)
5674 self.test.generate_disposal_code(code)
5675 self.test.free_temps(code)
5677 def eval_and_get(self, code, expr):
5678 expr.generate_evaluation_code(code)
5679 expr.make_owned_reference(code)
5680 code.putln("%s = %s;" % (self.result(), expr.result()))
5681 expr.generate_post_assignment_code(code)
5682 expr.free_temps(code)
5684 richcmp_constants = {
5694 class CmpNode(object):
5695 # Mixin class containing code common to PrimaryCmpNodes
5696 # and CascadedCmpNodes.
5698 def infer_type(self, env):
5699 # TODO: Actually implement this (after merging with -unstable).
5700 return py_object_type
5702 def calculate_cascaded_constant_result(self, operand1_result):
5703 func = compile_time_binary_operators[self.operator]
5704 operand2_result = self.operand2.constant_result
5705 result = func(operand1_result, operand2_result)
5707 self.cascade.calculate_cascaded_constant_result(operand2_result)
5708 if self.cascade.constant_result:
5709 self.constant_result = result and self.cascade.constant_result
5711 self.constant_result = result
5713 def cascaded_compile_time_value(self, operand1, denv):
5714 func = get_compile_time_binop(self)
5715 operand2 = self.operand2.compile_time_value(denv)
5717 result = func(operand1, operand2)
5718 except Exception, e:
5719 self.compile_time_value_error(e)
5722 cascade = self.cascade
5724 # FIXME: I bet this must call cascaded_compile_time_value()
5725 result = result and cascade.cascaded_compile_time_value(operand2, denv)
5728 def is_cpp_comparison(self):
5729 return self.operand1.type.is_cpp_class or self.operand2.type.is_cpp_class
5731 def find_common_int_type(self, env, op, operand1, operand2):
5732 # type1 != type2 and at least one of the types is not a C int
5733 type1 = operand1.type
5734 type2 = operand2.type
5735 type1_can_be_int = False
5736 type2_can_be_int = False
5738 if isinstance(operand1, (StringNode, BytesNode, UnicodeNode)) \
5739 and operand1.can_coerce_to_char_literal():
5740 type1_can_be_int = True
5741 if isinstance(operand2, (StringNode, BytesNode, UnicodeNode)) \
5742 and operand2.can_coerce_to_char_literal():
5743 type2_can_be_int = True
5746 if type2_can_be_int:
5749 if type1_can_be_int:
5751 elif type1_can_be_int:
5752 if type2_can_be_int:
5753 return PyrexTypes.c_uchar_type
5757 def find_common_type(self, env, op, operand1, common_type=None):
5758 operand2 = self.operand2
5759 type1 = operand1.type
5760 type2 = operand2.type
5762 new_common_type = None
5764 # catch general errors
5765 if type1 == str_type and (type2.is_string or type2 in (bytes_type, unicode_type)) or \
5766 type2 == str_type and (type1.is_string or type1 in (bytes_type, unicode_type)):
5767 error(self.pos, "Comparisons between bytes/unicode and str are not portable to Python 3")
5768 new_common_type = error_type
5770 # try to use numeric comparisons where possible
5771 elif type1.is_complex or type2.is_complex:
5772 if op not in ('==', '!='):
5773 error(self.pos, "complex types are unordered")
5774 new_common_type = error_type
5775 if type1.is_pyobject:
5776 new_common_type = type1
5777 elif type2.is_pyobject:
5778 new_common_type = type2
5780 new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
5781 elif type1.is_numeric and type2.is_numeric:
5782 new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
5783 elif common_type is None or not common_type.is_pyobject:
5784 new_common_type = self.find_common_int_type(env, op, operand1, operand2)
5786 if new_common_type is None:
5787 # fall back to generic type compatibility tests
5789 new_common_type = type1
5790 elif type1.is_pyobject or type2.is_pyobject:
5791 if type2.is_numeric or type2.is_string:
5792 if operand2.check_for_coercion_error(type1):
5793 new_common_type = error_type
5795 new_common_type = py_object_type
5796 elif type1.is_numeric or type1.is_string:
5797 if operand1.check_for_coercion_error(type2):
5798 new_common_type = error_type
5800 new_common_type = py_object_type
5801 elif py_object_type.assignable_from(type1) and py_object_type.assignable_from(type2):
5802 new_common_type = py_object_type
5804 # one Python type and one non-Python type, not assignable
5805 self.invalid_types_error(operand1, op, operand2)
5806 new_common_type = error_type
5807 elif type1.assignable_from(type2):
5808 new_common_type = type1
5809 elif type2.assignable_from(type1):
5810 new_common_type = type2
5812 # C types that we couldn't handle up to here are an error
5813 self.invalid_types_error(operand1, op, operand2)
5814 new_common_type = error_type
5816 # recursively merge types
5817 if common_type is None or new_common_type.is_error:
5818 common_type = new_common_type
5820 # we could do a lot better by splitting the comparison
5821 # into a non-Python part and a Python part, but this is
5823 common_type = PyrexTypes.spanning_type(common_type, new_common_type)
5826 common_type = self.cascade.find_common_type(env, self.operator, operand2, common_type)
5830 def invalid_types_error(self, operand1, op, operand2):
5831 error(self.pos, "Invalid types for '%s' (%s, %s)" %
5832 (op, operand1.type, operand2.type))
5834 def is_python_comparison(self):
5835 return not self.is_c_string_contains() and (
5836 self.has_python_operands()
5837 or (self.cascade and self.cascade.is_python_comparison())
5838 or self.operator in ('in', 'not_in'))
5840 def coerce_operands_to(self, dst_type, env):
5841 operand2 = self.operand2
5842 if operand2.type != dst_type:
5843 self.operand2 = operand2.coerce_to(dst_type, env)
5845 self.cascade.coerce_operands_to(dst_type, env)
5847 def is_python_result(self):
5848 return ((self.has_python_operands() and
5849 self.operator not in ('is', 'is_not', 'in', 'not_in') and
5850 not self.is_c_string_contains())
5851 or (self.cascade and self.cascade.is_python_result()))
5853 def is_c_string_contains(self):
5854 return self.operator in ('in', 'not_in') and \
5855 ((self.operand1.type.is_int
5856 and (self.operand2.type.is_string or self.operand2.type is bytes_type)) or
5857 (self.operand1.type is PyrexTypes.c_py_unicode_type
5858 and self.operand2.type is unicode_type))
5860 def generate_operation_code(self, code, result_code,
5861 operand1, op , operand2):
5862 if self.type.is_pyobject:
5863 coerce_result = "__Pyx_PyBool_FromLong"
5870 if op == 'in' or op == 'not_in':
5871 code.globalstate.use_utility_code(contains_utility_code)
5872 if self.type.is_pyobject:
5873 coerce_result = "__Pyx_PyBoolOrNull_FromLong"
5875 negation = "__Pyx_NegateNonNeg"
5876 if operand2.type is dict_type:
5877 code.globalstate.use_utility_code(
5878 raise_none_iter_error_utility_code)
5879 code.putln("if (unlikely(%s == Py_None)) {" % operand2.py_result())
5880 code.putln("__Pyx_RaiseNoneNotIterableError(); %s" %
5881 code.error_goto(self.pos))
5882 code.putln("} else {")
5883 method = "PyDict_Contains"
5885 method = "PySequence_Contains"
5886 if self.type.is_pyobject:
5887 error_clause = code.error_goto_if_null
5888 got_ref = "__Pyx_XGOTREF(%s); " % result_code
5890 error_clause = code.error_goto_if_neg
5893 "%s = %s(%s(%s(%s, %s))); %s%s" % (
5898 operand2.py_result(),
5899 operand1.py_result(),
5901 error_clause(result_code, self.pos)))
5902 if operand2.type is dict_type:
5905 elif (operand1.type.is_pyobject
5906 and op not in ('is', 'is_not')):
5907 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
5909 operand1.py_result(),
5910 operand2.py_result(),
5911 richcmp_constants[op],
5912 code.error_goto_if_null(result_code, self.pos)))
5913 code.put_gotref(result_code)
5914 elif operand1.type.is_complex:
5919 code.putln("%s = %s(%s%s(%s, %s));" % (
5923 operand1.type.unary_op('eq'),
5927 type1 = operand1.type
5928 type2 = operand2.type
5929 if (type1.is_extension_type or type2.is_extension_type) \
5930 and not type1.same_as(type2):
5931 common_type = py_object_type
5932 elif type1.is_numeric:
5933 common_type = PyrexTypes.widest_numeric_type(type1, type2)
5936 code1 = operand1.result_as(common_type)
5937 code2 = operand2.result_as(common_type)
5938 code.putln("%s = %s(%s %s %s);" % (
5942 self.c_operator(op),
5945 def c_operator(self, op):
5948 elif op == 'is_not':
5953 contains_utility_code = UtilityCode(
5955 static CYTHON_INLINE long __Pyx_NegateNonNeg(long b) { return unlikely(b < 0) ? b : !b; }
5956 static CYTHON_INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
5957 return unlikely(b < 0) ? NULL : __Pyx_PyBool_FromLong(b);
5961 char_in_bytes_utility_code = UtilityCode(
5963 static CYTHON_INLINE int __Pyx_BytesContains(PyObject* bytes, char character); /*proto*/
5966 static CYTHON_INLINE int __Pyx_BytesContains(PyObject* bytes, char character) {
5967 const Py_ssize_t length = PyBytes_GET_SIZE(bytes);
5968 char* char_start = PyBytes_AS_STRING(bytes);
5970 for (pos=char_start; pos < char_start+length; pos++) {
5971 if (character == pos[0]) return 1;
5977 pyunicode_in_unicode_utility_code = UtilityCode(
5979 static CYTHON_INLINE int __Pyx_UnicodeContains(PyObject* unicode, Py_UNICODE character); /*proto*/
5982 static CYTHON_INLINE int __Pyx_UnicodeContains(PyObject* unicode, Py_UNICODE character) {
5983 const Py_ssize_t length = PyUnicode_GET_SIZE(unicode);
5984 Py_UNICODE* char_start = PyUnicode_AS_UNICODE(unicode);
5986 for (pos=char_start; pos < char_start+length; pos++) {
5987 if (character == pos[0]) return 1;
5994 class PrimaryCmpNode(ExprNode, CmpNode):
5995 # Non-cascaded comparison or first comparison of
5996 # a cascaded sequence.
6001 # cascade CascadedCmpNode
6003 # We don't use the subexprs mechanism, because
6004 # things here are too complicated for it to handle.
6005 # Instead, we override all the framework methods
6008 child_attrs = ['operand1', 'operand2', 'cascade']
6012 def infer_type(self, env):
6013 # TODO: Actually implement this (after merging with -unstable).
6014 return py_object_type
6016 def type_dependencies(self, env):
6019 def calculate_constant_result(self):
6020 self.calculate_cascaded_constant_result(self.operand1.constant_result)
6022 def compile_time_value(self, denv):
6023 operand1 = self.operand1.compile_time_value(denv)
6024 return self.cascaded_compile_time_value(operand1, denv)
6026 def analyse_types(self, env):
6027 self.operand1.analyse_types(env)
6028 self.operand2.analyse_types(env)
6029 if self.is_cpp_comparison():
6030 self.analyse_cpp_comparison(env)
6032 error(self.pos, "Cascading comparison not yet supported for cpp types.")
6035 self.cascade.analyse_types(env)
6037 if self.operator in ('in', 'not_in'):
6038 if self.is_c_string_contains():
6039 self.is_pycmp = False
6042 error(self.pos, "Cascading comparison not yet supported for 'int_val in string'.")
6044 if self.operand2.type is unicode_type:
6045 env.use_utility_code(pyunicode_in_unicode_utility_code)
6047 if self.operand1.type is PyrexTypes.c_uchar_type:
6048 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_char_type, env)
6049 if self.operand2.type is not bytes_type:
6050 self.operand2 = self.operand2.coerce_to(bytes_type, env)
6051 env.use_utility_code(char_in_bytes_utility_code)
6052 self.operand2 = self.operand2.as_none_safe_node(
6053 "argument of type 'NoneType' is not iterable")
6055 common_type = py_object_type
6056 self.is_pycmp = True
6058 common_type = self.find_common_type(env, self.operator, self.operand1)
6059 self.is_pycmp = common_type.is_pyobject
6061 if common_type is not None and not common_type.is_error:
6062 if self.operand1.type != common_type:
6063 self.operand1 = self.operand1.coerce_to(common_type, env)
6064 self.coerce_operands_to(common_type, env)
6067 self.operand2 = self.operand2.coerce_to_simple(env)
6068 self.cascade.coerce_cascaded_operands_to_temp(env)
6069 if self.is_python_result():
6070 self.type = PyrexTypes.py_object_type
6072 self.type = PyrexTypes.c_bint_type
6075 cdr.type = self.type
6077 if self.is_pycmp or self.cascade:
6080 def analyse_cpp_comparison(self, env):
6081 type1 = self.operand1.type
6082 type2 = self.operand2.type
6083 entry = env.lookup_operator(self.operator, [self.operand1, self.operand2])
6085 error(self.pos, "Invalid types for '%s' (%s, %s)" %
6086 (self.operator, type1, type2))
6087 self.type = PyrexTypes.error_type
6088 self.result_code = "<error>"
6090 func_type = entry.type
6091 if func_type.is_ptr:
6092 func_type = func_type.base_type
6093 if len(func_type.args) == 1:
6094 self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env)
6096 self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env)
6097 self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env)
6098 self.type = func_type.return_type
6100 def has_python_operands(self):
6101 return (self.operand1.type.is_pyobject
6102 or self.operand2.type.is_pyobject)
6104 def check_const(self):
6109 return self.operand1.check_const() and self.operand2.check_const()
6111 def calculate_result_code(self):
6112 if self.operand1.type.is_complex:
6113 if self.operator == "!=":
6117 return "(%s%s(%s, %s))" % (
6119 self.operand1.type.binary_op('=='),
6120 self.operand1.result(),
6121 self.operand2.result())
6122 elif self.is_c_string_contains():
6123 if self.operand2.type is bytes_type:
6124 method = "__Pyx_BytesContains"
6126 method = "__Pyx_UnicodeContains"
6127 if self.operator == "not_in":
6131 return "(%s%s(%s, %s))" % (
6134 self.operand2.result(),
6135 self.operand1.result())
6137 return "(%s %s %s)" % (
6138 self.operand1.result(),
6139 self.c_operator(self.operator),
6140 self.operand2.result())
6142 def generate_evaluation_code(self, code):
6143 self.operand1.generate_evaluation_code(code)
6144 self.operand2.generate_evaluation_code(code)
6146 self.allocate_temp_result(code)
6147 self.generate_operation_code(code, self.result(),
6148 self.operand1, self.operator, self.operand2)
6150 self.cascade.generate_evaluation_code(code,
6151 self.result(), self.operand2)
6152 self.operand1.generate_disposal_code(code)
6153 self.operand1.free_temps(code)
6154 self.operand2.generate_disposal_code(code)
6155 self.operand2.free_temps(code)
6157 def generate_subexpr_disposal_code(self, code):
6158 # If this is called, it is a non-cascaded cmp,
6159 # so only need to dispose of the two main operands.
6160 self.operand1.generate_disposal_code(code)
6161 self.operand2.generate_disposal_code(code)
6163 def free_subexpr_temps(self, code):
6164 # If this is called, it is a non-cascaded cmp,
6165 # so only need to dispose of the two main operands.
6166 self.operand1.free_temps(code)
6167 self.operand2.free_temps(code)
6169 def annotate(self, code):
6170 self.operand1.annotate(code)
6171 self.operand2.annotate(code)
6173 self.cascade.annotate(code)
6176 class CascadedCmpNode(Node, CmpNode):
6177 # A CascadedCmpNode is not a complete expression node. It
6178 # hangs off the side of another comparison node, shares
6179 # its left operand with that node, and shares its result
6180 # with the PrimaryCmpNode at the head of the chain.
6184 # cascade CascadedCmpNode
6186 child_attrs = ['operand2', 'cascade']
6189 constant_result = constant_value_not_set # FIXME: where to calculate this?
6191 def infer_type(self, env):
6192 # TODO: Actually implement this (after merging with -unstable).
6193 return py_object_type
6195 def type_dependencies(self, env):
6198 def has_constant_result(self):
6199 return self.constant_result is not constant_value_not_set and \
6200 self.constant_result is not not_a_constant
6202 def analyse_types(self, env):
6203 self.operand2.analyse_types(env)
6205 self.cascade.analyse_types(env)
6207 def has_python_operands(self):
6208 return self.operand2.type.is_pyobject
6210 def coerce_operands_to_pyobjects(self, env):
6211 self.operand2 = self.operand2.coerce_to_pyobject(env)
6213 self.cascade.coerce_operands_to_pyobjects(env)
6215 def coerce_cascaded_operands_to_temp(self, env):
6217 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
6218 self.operand2 = self.operand2.coerce_to_simple(env)
6219 self.cascade.coerce_cascaded_operands_to_temp(env)
6221 def generate_evaluation_code(self, code, result, operand1):
6222 if self.type.is_pyobject:
6223 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
6224 code.put_decref(result, self.type)
6226 code.putln("if (%s) {" % result)
6227 self.operand2.generate_evaluation_code(code)
6228 self.generate_operation_code(code, result,
6229 operand1, self.operator, self.operand2)
6231 self.cascade.generate_evaluation_code(
6232 code, result, self.operand2)
6233 # Cascaded cmp result is always temp
6234 self.operand2.generate_disposal_code(code)
6235 self.operand2.free_temps(code)
6238 def annotate(self, code):
6239 self.operand2.annotate(code)
6241 self.cascade.annotate(code)
6244 binop_node_classes = {
6245 "or": BoolBinopNode,
6246 "and": BoolBinopNode,
6261 def binop_node(pos, operator, operand1, operand2):
6262 # Construct binop node of appropriate class for
6264 return binop_node_classes[operator](pos,
6265 operator = operator,
6266 operand1 = operand1,
6267 operand2 = operand2)
6269 #-------------------------------------------------------------------
6273 # Coercion nodes are special in that they are created during
6274 # the analyse_types phase of parse tree processing.
6275 # Their __init__ methods consequently incorporate some aspects
6278 #-------------------------------------------------------------------
6280 class CoercionNode(ExprNode):
6281 # Abstract base class for coercion nodes.
6283 # arg ExprNode node being coerced
6286 constant_result = not_a_constant
6288 def __init__(self, arg):
6292 print("%s Coercing %s" % (self, self.arg))
6294 def calculate_constant_result(self):
6295 # constant folding can break type coercion, so this is disabled
6298 def annotate(self, code):
6299 self.arg.annotate(code)
6300 if self.arg.type != self.type:
6301 file, line, col = self.pos
6302 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
6305 class CastNode(CoercionNode):
6306 # Wrap a node in a C type cast.
6308 def __init__(self, arg, new_type):
6309 CoercionNode.__init__(self, arg)
6310 self.type = new_type
6312 def calculate_result_code(self):
6313 return self.arg.result_as(self.type)
6315 def generate_result_code(self, code):
6316 self.arg.generate_result_code(code)
6319 class PyTypeTestNode(CoercionNode):
6320 # This node is used to check that a generic Python
6321 # object is an instance of a particular extension type.
6322 # This node borrows the result of its argument node.
6324 def __init__(self, arg, dst_type, env, notnone=False):
6325 # The arg is know to be a Python object, and
6326 # the dst_type is known to be an extension type.
6327 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
6328 CoercionNode.__init__(self, arg)
6329 self.type = dst_type
6330 self.result_ctype = arg.ctype()
6331 self.notnone = notnone
6333 nogil_check = Node.gil_error
6334 gil_message = "Python type test"
6336 def analyse_types(self, env):
6339 def result_in_temp(self):
6340 return self.arg.result_in_temp()
6342 def is_ephemeral(self):
6343 return self.arg.is_ephemeral()
6345 def calculate_constant_result(self):
6349 def calculate_result_code(self):
6350 return self.arg.result()
6352 def generate_result_code(self, code):
6353 if self.type.typeobj_is_available():
6354 if not self.type.is_builtin_type:
6355 code.globalstate.use_utility_code(type_test_utility_code)
6358 self.type.type_test_code(self.arg.py_result(), self.notnone),
6359 code.error_goto(self.pos)))
6361 error(self.pos, "Cannot test type of extern C class "
6362 "without type object name specification")
6364 def generate_post_assignment_code(self, code):
6365 self.arg.generate_post_assignment_code(code)
6367 def free_temps(self, code):
6368 self.arg.free_temps(code)
6371 class NoneCheckNode(CoercionNode):
6372 # This node is used to check that a Python object is not None and
6373 # raises an appropriate exception (as specified by the creating
6376 def __init__(self, arg, exception_type_cname, exception_message):
6377 CoercionNode.__init__(self, arg)
6378 self.type = arg.type
6379 self.result_ctype = arg.ctype()
6380 self.exception_type_cname = exception_type_cname
6381 self.exception_message = exception_message
6383 def analyse_types(self, env):
6386 def may_be_none(self):
6389 def result_in_temp(self):
6390 return self.arg.result_in_temp()
6392 def calculate_result_code(self):
6393 return self.arg.result()
6395 def generate_result_code(self, code):
6397 "if (unlikely(%s == Py_None)) {" % self.arg.result())
6398 code.putln('PyErr_SetString(%s, "%s"); %s ' % (
6399 self.exception_type_cname,
6400 StringEncoding.escape_byte_string(
6401 self.exception_message.encode('UTF-8')),
6402 code.error_goto(self.pos)))
6405 def generate_post_assignment_code(self, code):
6406 self.arg.generate_post_assignment_code(code)
6408 def free_temps(self, code):
6409 self.arg.free_temps(code)
6412 class CoerceToPyTypeNode(CoercionNode):
6413 # This node is used to convert a C data type
6414 # to a Python object.
6416 type = py_object_type
6419 def __init__(self, arg, env, type=py_object_type):
6420 CoercionNode.__init__(self, arg)
6421 if not arg.type.create_to_py_utility_code(env):
6423 "Cannot convert '%s' to Python object" % arg.type)
6424 if type is not py_object_type:
6425 self.type = py_object_type
6426 elif arg.type.is_string:
6427 self.type = bytes_type
6428 elif arg.type is PyrexTypes.c_py_unicode_type:
6429 self.type = unicode_type
6431 gil_message = "Converting to Python object"
6433 def may_be_none(self):
6434 # FIXME: is this always safe?
6437 def coerce_to_boolean(self, env):
6438 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
6440 def coerce_to_integer(self, env):
6441 # If not already some C integer type, coerce to longint.
6442 if self.arg.type.is_int:
6445 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
6447 def analyse_types(self, env):
6448 # The arg is always already analysed
6451 def generate_result_code(self, code):
6452 function = self.arg.type.to_py_function
6453 code.putln('%s = %s(%s); %s' % (
6457 code.error_goto_if_null(self.result(), self.pos)))
6458 code.put_gotref(self.py_result())
6461 class CoerceIntToBytesNode(CoerceToPyTypeNode):
6462 # This node is used to convert a C int type to a Python bytes
6467 def __init__(self, arg, env):
6468 arg = arg.coerce_to_simple(env)
6469 CoercionNode.__init__(self, arg)
6470 self.type = Builtin.bytes_type
6472 def generate_result_code(self, code):
6474 arg_result = arg.result()
6475 if arg.type not in (PyrexTypes.c_char_type,
6476 PyrexTypes.c_uchar_type,
6477 PyrexTypes.c_schar_type):
6479 code.putln("if ((%s < 0) || (%s > 255)) {" % (
6480 arg_result, arg_result))
6482 code.putln("if (%s > 255) {" % arg_result)
6483 code.putln('PyErr_Format(PyExc_OverflowError, '
6484 '"value too large to pack into a byte"); %s' % (
6485 code.error_goto(self.pos)))
6488 if arg.type is not PyrexTypes.c_char_type:
6489 temp = code.funcstate.allocate_temp(PyrexTypes.c_char_type, manage_ref=False)
6490 code.putln("%s = (char)%s;" % (temp, arg_result))
6492 code.putln('%s = PyBytes_FromStringAndSize(&%s, 1); %s' % (
6495 code.error_goto_if_null(self.result(), self.pos)))
6496 if temp is not None:
6497 code.funcstate.release_temp(temp)
6498 code.put_gotref(self.py_result())
6501 class CoerceFromPyTypeNode(CoercionNode):
6502 # This node is used to convert a Python object
6505 def __init__(self, result_type, arg, env):
6506 CoercionNode.__init__(self, arg)
6507 self.type = result_type
6509 if not result_type.create_from_py_utility_code(env):
6511 "Cannot convert Python object to '%s'" % result_type)
6512 if self.type.is_string and self.arg.is_ephemeral():
6514 "Obtaining char * from temporary Python value")
6516 def analyse_types(self, env):
6517 # The arg is always already analysed
6520 def generate_result_code(self, code):
6521 function = self.type.from_py_function
6522 operand = self.arg.py_result()
6523 rhs = "%s(%s)" % (function, operand)
6524 if self.type.is_enum:
6525 rhs = typecast(self.type, c_long_type, rhs)
6526 code.putln('%s = %s; %s' % (
6529 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
6530 if self.type.is_pyobject:
6531 code.put_gotref(self.py_result())
6534 class CoerceToBooleanNode(CoercionNode):
6535 # This node is used when a result needs to be used
6536 # in a boolean context.
6538 type = PyrexTypes.c_bint_type
6540 _special_builtins = {
6541 Builtin.list_type : 'PyList_GET_SIZE',
6542 Builtin.tuple_type : 'PyTuple_GET_SIZE',
6543 Builtin.bytes_type : 'PyBytes_GET_SIZE',
6544 Builtin.unicode_type : 'PyUnicode_GET_SIZE',
6547 def __init__(self, arg, env):
6548 CoercionNode.__init__(self, arg)
6549 if arg.type.is_pyobject:
6552 def nogil_check(self, env):
6553 if self.arg.type.is_pyobject and self._special_builtins.get(self.arg.type) is None:
6556 gil_message = "Truth-testing Python object"
6558 def check_const(self):
6562 return self.arg.check_const()
6564 def calculate_result_code(self):
6565 return "(%s != 0)" % self.arg.result()
6567 def generate_result_code(self, code):
6568 if not self.is_temp:
6570 test_func = self._special_builtins.get(self.arg.type)
6571 if test_func is not None:
6572 code.putln("%s = (%s != Py_None) && (%s(%s) != 0);" % (
6574 self.arg.py_result(),
6576 self.arg.py_result()))
6579 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
6581 self.arg.py_result(),
6582 code.error_goto_if_neg(self.result(), self.pos)))
6584 class CoerceToComplexNode(CoercionNode):
6586 def __init__(self, arg, dst_type, env):
6587 if arg.type.is_complex:
6588 arg = arg.coerce_to_simple(env)
6589 self.type = dst_type
6590 CoercionNode.__init__(self, arg)
6591 dst_type.create_declaration_utility_code(env)
6593 def calculate_result_code(self):
6594 if self.arg.type.is_complex:
6595 real_part = "__Pyx_CREAL(%s)" % self.arg.result()
6596 imag_part = "__Pyx_CIMAG(%s)" % self.arg.result()
6598 real_part = self.arg.result()
6600 return "%s(%s, %s)" % (
6601 self.type.from_parts,
6605 def generate_result_code(self, code):
6608 class CoerceToTempNode(CoercionNode):
6609 # This node is used to force the result of another node
6610 # to be stored in a temporary. It is only used if the
6611 # argument node's result is not already in a temporary.
6613 def __init__(self, arg, env):
6614 CoercionNode.__init__(self, arg)
6615 self.type = self.arg.type
6616 self.constant_result = self.arg.constant_result
6618 if self.type.is_pyobject:
6619 self.result_ctype = py_object_type
6621 gil_message = "Creating temporary Python reference"
6623 def analyse_types(self, env):
6624 # The arg is always already analysed
6627 def coerce_to_boolean(self, env):
6628 self.arg = self.arg.coerce_to_boolean(env)
6629 if self.arg.is_simple():
6631 self.type = self.arg.type
6632 self.result_ctype = self.type
6635 def generate_result_code(self, code):
6636 #self.arg.generate_evaluation_code(code) # Already done
6637 # by generic generate_subexpr_evaluation_code!
6638 code.putln("%s = %s;" % (
6639 self.result(), self.arg.result_as(self.ctype())))
6640 if self.type.is_pyobject and self.use_managed_ref:
6641 code.put_incref(self.result(), self.ctype())
6644 class CloneNode(CoercionNode):
6645 # This node is employed when the result of another node needs
6646 # to be used multiple times. The argument node's result must
6647 # be in a temporary. This node "borrows" the result from the
6648 # argument node, and does not generate any evaluation or
6649 # disposal code for it. The original owner of the argument
6650 # node is responsible for doing those things.
6652 subexprs = [] # Arg is not considered a subexpr
6655 def __init__(self, arg):
6656 CoercionNode.__init__(self, arg)
6657 if hasattr(arg, 'type'):
6658 self.type = arg.type
6659 self.result_ctype = arg.result_ctype
6660 if hasattr(arg, 'entry'):
6661 self.entry = arg.entry
6664 return self.arg.result()
6666 def type_dependencies(self, env):
6667 return self.arg.type_dependencies(env)
6669 def infer_type(self, env):
6670 return self.arg.infer_type(env)
6672 def analyse_types(self, env):
6673 self.type = self.arg.type
6674 self.result_ctype = self.arg.result_ctype
6676 if hasattr(self.arg, 'entry'):
6677 self.entry = self.arg.entry
6679 def generate_evaluation_code(self, code):
6682 def generate_result_code(self, code):
6685 def generate_disposal_code(self, code):
6688 def free_temps(self, code):
6692 class ModuleRefNode(ExprNode):
6693 # Simple returns the module object
6695 type = py_object_type
6699 def analyse_types(self, env):
6702 def may_be_none(self):
6705 def calculate_result_code(self):
6706 return Naming.module_cname
6708 def generate_result_code(self, code):
6711 class DocstringRefNode(ExprNode):
6712 # Extracts the docstring of the body element
6715 type = py_object_type
6718 def __init__(self, pos, body):
6719 ExprNode.__init__(self, pos)
6720 assert body.type.is_pyobject
6723 def analyse_types(self, env):
6726 def generate_result_code(self, code):
6727 code.putln('%s = __Pyx_GetAttrString(%s, "__doc__"); %s' % (
6728 self.result(), self.body.result(),
6729 code.error_goto_if_null(self.result(), self.pos)))
6730 code.put_gotref(self.result())
6734 #------------------------------------------------------------------------------------
6736 # Runtime support code
6738 #------------------------------------------------------------------------------------
6740 get_name_interned_utility_code = UtilityCode(
6742 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
6745 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
6747 result = PyObject_GetAttr(dict, name);
6749 PyErr_SetObject(PyExc_NameError, name);
6754 #------------------------------------------------------------------------------------
6756 import_utility_code = UtilityCode(
6758 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
6761 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
6762 PyObject *py_import = 0;
6763 PyObject *empty_list = 0;
6764 PyObject *module = 0;
6765 PyObject *global_dict = 0;
6766 PyObject *empty_dict = 0;
6768 py_import = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
6774 empty_list = PyList_New(0);
6779 global_dict = PyModule_GetDict(%(GLOBALS)s);
6782 empty_dict = PyDict_New();
6785 module = PyObject_CallFunctionObjArgs(py_import,
6786 name, global_dict, empty_dict, list, NULL);
6788 Py_XDECREF(empty_list);
6789 Py_XDECREF(py_import);
6790 Py_XDECREF(empty_dict);
6794 "BUILTINS": Naming.builtins_cname,
6795 "GLOBALS": Naming.module_cname,
6798 #------------------------------------------------------------------------------------
6800 get_exception_utility_code = UtilityCode(
6802 static PyObject *__Pyx_GetExcValue(void); /*proto*/
6805 static PyObject *__Pyx_GetExcValue(void) {
6806 PyObject *type = 0, *value = 0, *tb = 0;
6807 PyObject *tmp_type, *tmp_value, *tmp_tb;
6808 PyObject *result = 0;
6809 PyThreadState *tstate = PyThreadState_Get();
6810 PyErr_Fetch(&type, &value, &tb);
6811 PyErr_NormalizeException(&type, &value, &tb);
6812 if (PyErr_Occurred())
6818 tmp_type = tstate->exc_type;
6819 tmp_value = tstate->exc_value;
6820 tmp_tb = tstate->exc_traceback;
6821 tstate->exc_type = type;
6822 tstate->exc_value = value;
6823 tstate->exc_traceback = tb;
6824 /* Make sure tstate is in a consistent state when we XDECREF
6825 these objects (XDECREF may run arbitrary code). */
6826 Py_XDECREF(tmp_type);
6827 Py_XDECREF(tmp_value);
6842 #------------------------------------------------------------------------------------
6844 type_test_utility_code = UtilityCode(
6846 static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
6849 static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
6850 if (unlikely(!type)) {
6851 PyErr_Format(PyExc_SystemError, "Missing type object");
6854 if (likely(PyObject_TypeCheck(obj, type)))
6856 PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s",
6857 Py_TYPE(obj)->tp_name, type->tp_name);
6862 #------------------------------------------------------------------------------------
6864 create_class_utility_code = UtilityCode(
6866 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
6869 static PyObject *__Pyx_CreateClass(
6870 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
6872 PyObject *py_modname;
6873 PyObject *result = 0;
6875 #if PY_MAJOR_VERSION < 3
6876 py_modname = PyString_FromString(modname);
6878 py_modname = PyUnicode_FromString(modname);
6882 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
6884 #if PY_MAJOR_VERSION < 3
6885 result = PyClass_New(bases, dict, name);
6887 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
6890 Py_XDECREF(py_modname);
6895 #------------------------------------------------------------------------------------
6897 cpp_exception_utility_code = UtilityCode(
6899 #ifndef __Pyx_CppExn2PyErr
6900 static void __Pyx_CppExn2PyErr() {
6902 if (PyErr_Occurred())
6903 ; // let the latest Python exn pass through and ignore the current one
6906 } catch (const std::out_of_range& exn) {
6907 // catch out_of_range explicitly so the proper Python exn may be raised
6908 PyErr_SetString(PyExc_IndexError, exn.what());
6909 } catch (const std::exception& exn) {
6910 PyErr_SetString(PyExc_RuntimeError, exn.what());
6914 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
6922 #------------------------------------------------------------------------------------
6924 raise_noneattr_error_utility_code = UtilityCode(
6926 static CYTHON_INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
6929 static CYTHON_INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
6930 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
6934 raise_noneindex_error_utility_code = UtilityCode(
6936 static CYTHON_INLINE void __Pyx_RaiseNoneIndexingError(void);
6939 static CYTHON_INLINE void __Pyx_RaiseNoneIndexingError(void) {
6940 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
6944 raise_none_iter_error_utility_code = UtilityCode(
6946 static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void);
6949 static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) {
6950 PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
6954 #------------------------------------------------------------------------------------
6956 getitem_dict_utility_code = UtilityCode(
6959 #if PY_MAJOR_VERSION >= 3
6960 static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) {
6962 if (unlikely(d == Py_None)) {
6963 __Pyx_RaiseNoneIndexingError();
6966 value = PyDict_GetItemWithError(d, key);
6967 if (unlikely(!value)) {
6968 if (!PyErr_Occurred())
6969 PyErr_SetObject(PyExc_KeyError, key);
6976 #define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key)
6979 requires = [raise_noneindex_error_utility_code])
6981 #------------------------------------------------------------------------------------
6983 getitem_int_pyunicode_utility_code = UtilityCode(
6985 #define __Pyx_GetItemInt_Unicode(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
6986 __Pyx_GetItemInt_Unicode_Fast(o, i) : \\
6987 __Pyx_GetItemInt_Unicode_Generic(o, to_py_func(i)))
6989 static CYTHON_INLINE Py_UNICODE __Pyx_GetItemInt_Unicode_Fast(PyObject* ustring, Py_ssize_t i) {
6990 if (likely((0 <= i) & (i < PyUnicode_GET_SIZE(ustring)))) {
6991 return PyUnicode_AS_UNICODE(ustring)[i];
6992 } else if ((-PyUnicode_GET_SIZE(ustring) <= i) & (i < 0)) {
6993 i += PyUnicode_GET_SIZE(ustring);
6994 return PyUnicode_AS_UNICODE(ustring)[i];
6996 PyErr_SetString(PyExc_IndexError, "string index out of range");
6997 return (Py_UNICODE)-1;
7001 static CYTHON_INLINE Py_UNICODE __Pyx_GetItemInt_Unicode_Generic(PyObject* ustring, PyObject* j) {
7003 PyObject *uchar_string;
7004 if (!j) return (Py_UNICODE)-1;
7005 uchar_string = PyObject_GetItem(ustring, j);
7007 if (!uchar_string) return (Py_UNICODE)-1;
7008 uchar = PyUnicode_AS_UNICODE(uchar_string)[0];
7009 Py_DECREF(uchar_string);
7014 getitem_int_utility_code = UtilityCode(
7017 static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
7019 if (!j) return NULL;
7020 r = PyObject_GetItem(o, j);
7027 #define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
7028 __Pyx_GetItemInt_%(type)s_Fast(o, i) : \\
7029 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
7031 static CYTHON_INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i) {
7032 if (likely(o != Py_None)) {
7033 if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
7034 PyObject *r = Py%(type)s_GET_ITEM(o, i);
7038 else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
7039 PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
7044 return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
7046 """ % {'type' : type_name} for type_name in ('List', 'Tuple')
7049 #define __Pyx_GetItemInt(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
7050 __Pyx_GetItemInt_Fast(o, i) : \\
7051 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
7053 static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i) {
7055 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
7056 r = PyList_GET_ITEM(o, i);
7059 else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
7060 r = PyTuple_GET_ITEM(o, i);
7063 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
7064 r = PySequence_GetItem(o, i);
7067 r = __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
7077 #------------------------------------------------------------------------------------
7079 setitem_int_utility_code = UtilityCode(
7081 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
7082 __Pyx_SetItemInt_Fast(o, i, v) : \\
7083 __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
7085 static CYTHON_INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
7088 r = PyObject_SetItem(o, j, v);
7093 static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v) {
7094 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
7096 Py_DECREF(PyList_GET_ITEM(o, i));
7097 PyList_SET_ITEM(o, i, v);
7100 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
7101 return PySequence_SetItem(o, i, v);
7103 PyObject *j = PyInt_FromSsize_t(i);
7104 return __Pyx_SetItemInt_Generic(o, j, v);
7111 #------------------------------------------------------------------------------------
7113 delitem_int_utility_code = UtilityCode(
7115 #define __Pyx_DelItemInt(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
7116 __Pyx_DelItemInt_Fast(o, i) : \\
7117 __Pyx_DelItem_Generic(o, to_py_func(i)))
7119 static CYTHON_INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
7122 r = PyObject_DelItem(o, j);
7127 static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i) {
7128 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
7129 return PySequence_DelItem(o, i);
7131 PyObject *j = PyInt_FromSsize_t(i);
7132 return __Pyx_DelItem_Generic(o, j);
7139 #------------------------------------------------------------------------------------
7141 raise_too_many_values_to_unpack = UtilityCode(
7143 static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(void);
7146 static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(void) {
7147 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
7151 raise_need_more_values_to_unpack = UtilityCode(
7153 static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
7156 static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
7157 PyErr_Format(PyExc_ValueError,
7158 #if PY_VERSION_HEX < 0x02050000
7159 "need more than %d value%s to unpack", (int)index,
7161 "need more than %zd value%s to unpack", index,
7163 (index == 1) ? "" : "s");
7167 #------------------------------------------------------------------------------------
7169 tuple_unpacking_error_code = UtilityCode(
7171 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
7174 static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
7176 __Pyx_RaiseNoneNotIterableError();
7177 } else if (PyTuple_GET_SIZE(t) < index) {
7178 __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
7180 __Pyx_RaiseTooManyValuesError();
7184 requires = [raise_none_iter_error_utility_code,
7185 raise_need_more_values_to_unpack,
7186 raise_too_many_values_to_unpack]
7189 unpacking_utility_code = UtilityCode(
7191 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
7192 static int __Pyx_EndUnpack(PyObject *); /*proto*/
7195 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
7197 if (!(item = PyIter_Next(iter))) {
7198 if (!PyErr_Occurred()) {
7199 __Pyx_RaiseNeedMoreValuesError(index);
7205 static int __Pyx_EndUnpack(PyObject *iter) {
7207 if ((item = PyIter_Next(iter))) {
7209 __Pyx_RaiseTooManyValuesError();
7212 else if (!PyErr_Occurred())
7218 requires = [raise_need_more_values_to_unpack,
7219 raise_too_many_values_to_unpack]
7222 #------------------------------------------------------------------------------------
7224 # CPython supports calling functions with non-dict kwargs by
7225 # converting them to a dict first
7227 kwargs_call_utility_code = UtilityCode(
7229 static PyObject* __Pyx_PyEval_CallObjectWithKeywords(PyObject*, PyObject*, PyObject*); /*proto*/
7232 static PyObject* __Pyx_PyEval_CallObjectWithKeywords(PyObject *callable, PyObject *args, PyObject *kwargs) {
7234 if (likely(PyDict_Check(kwargs))) {
7235 return PyEval_CallObjectWithKeywords(callable, args, kwargs);
7237 PyObject* real_dict;
7238 real_dict = PyObject_CallFunctionObjArgs((PyObject*)&PyDict_Type, kwargs, NULL);
7239 if (unlikely(!real_dict))
7241 result = PyEval_CallObjectWithKeywords(callable, args, real_dict);
7242 Py_DECREF(real_dict);
7243 return result; /* may be NULL */
7250 #------------------------------------------------------------------------------------
7252 int_pow_utility_code = UtilityCode(
7254 static CYTHON_INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
7257 static CYTHON_INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
7269 if (unlikely(e<0)) return 0;
7272 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
7280 # ------------------------------ Division ------------------------------------
7282 div_int_utility_code = UtilityCode(
7284 static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
7287 static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
7289 %(type)s r = a - q*b;
7290 q -= ((r != 0) & ((r ^ b) < 0));
7295 mod_int_utility_code = UtilityCode(
7297 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
7300 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
7301 %(type)s r = a %% b;
7302 r += ((r != 0) & ((r ^ b) < 0)) * b;
7307 mod_float_utility_code = UtilityCode(
7309 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
7312 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
7313 %(type)s r = fmod%(math_h_modifier)s(a, b);
7314 r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
7319 cdivision_warning_utility_code = UtilityCode(
7321 static int __Pyx_cdivision_warning(void); /* proto */
7324 static int __Pyx_cdivision_warning(void) {
7325 return PyErr_WarnExplicit(PyExc_RuntimeWarning,
7326 "division with oppositely signed operands, C and Python semantics differ",
7333 'FILENAME': Naming.filename_cname,
7334 'LINENO': Naming.lineno_cname,
7338 division_overflow_test_code = UtilityCode(
7340 #define UNARY_NEG_WOULD_OVERFLOW(x) \
7341 (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
7345 binding_cfunc_utility_code = UtilityCode(
7347 #define %(binding_cfunc)s_USED 1
7350 PyCFunctionObject func;
7351 } %(binding_cfunc)s_object;
7353 PyTypeObject %(binding_cfunc)s_type;
7354 PyTypeObject *%(binding_cfunc)s = NULL;
7356 PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module); /* proto */
7357 #define %(binding_cfunc)s_New(ml, self) %(binding_cfunc)s_NewEx(ml, self, NULL)
7359 int %(binding_cfunc)s_init(void); /* proto */
7360 """ % Naming.__dict__,
7363 PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) {
7364 %(binding_cfunc)s_object *op = PyObject_GC_New(%(binding_cfunc)s_object, %(binding_cfunc)s);
7369 op->func.m_self = self;
7371 op->func.m_module = module;
7372 _PyObject_GC_TRACK(op);
7373 return (PyObject *)op;
7376 static void %(binding_cfunc)s_dealloc(%(binding_cfunc)s_object *m) {
7377 _PyObject_GC_UNTRACK(m);
7378 Py_XDECREF(m->func.m_self);
7379 Py_XDECREF(m->func.m_module);
7383 static PyObject *%(binding_cfunc)s_descr_get(PyObject *func, PyObject *obj, PyObject *type) {
7386 return PyMethod_New(func, obj, type);
7389 int %(binding_cfunc)s_init(void) {
7390 %(binding_cfunc)s_type = PyCFunction_Type;
7391 %(binding_cfunc)s_type.tp_name = "cython_binding_builtin_function_or_method";
7392 %(binding_cfunc)s_type.tp_dealloc = (destructor)%(binding_cfunc)s_dealloc;
7393 %(binding_cfunc)s_type.tp_descr_get = %(binding_cfunc)s_descr_get;
7394 if (PyType_Ready(&%(binding_cfunc)s_type) < 0) {
7397 %(binding_cfunc)s = &%(binding_cfunc)s_type;
7401 """ % Naming.__dict__)