Cython has moved to github.

cython-devel

view Cython/Compiler/ExprNodes.py @ 2741:f1f5f3768cdb

fix #463: TypeofNode crashes when typeof() is called on expressions
author Stefan Behnel <scoder@users.berlios.de>
date Sat Dec 05 17:37:05 2009 +0100 (2 years ago)
parents 28a1a87cbb5a
children 48d0197cfee6
line source
1 #
2 # Pyrex - Parse tree nodes for expressions
3 #
5 import operator
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
10 import StringEncoding
11 import Naming
12 import Nodes
13 from Nodes import Node
14 import PyrexTypes
15 from PyrexTypes import py_object_type, c_long_type, typecast, error_type, unspecified_type
16 from Builtin import list_type, tuple_type, set_type, dict_type, \
17 unicode_type, str_type, bytes_type, type_type
18 import Builtin
19 import Symtab
20 import Options
21 from Annotate import AnnotationItem
23 from Cython.Debugging import print_call_chain
24 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
25 debug_coercion
27 try:
28 set
29 except NameError:
30 from sets import Set as set
32 class NotConstant(object): pass # just for the name
33 not_a_constant = NotConstant()
34 constant_value_not_set = object()
36 # error messages when coercing from key[0] to key[1]
37 find_coercion_error = {
38 # string related errors
39 (Builtin.unicode_type, Builtin.bytes_type) : "Cannot convert Unicode string to 'bytes' implicitly, encoding required.",
40 (Builtin.unicode_type, Builtin.str_type) : "Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding.",
41 (Builtin.unicode_type, PyrexTypes.c_char_ptr_type) : "Unicode objects do not support coercion to C types.",
42 (Builtin.bytes_type, Builtin.unicode_type) : "Cannot convert 'bytes' object to unicode implicitly, decoding required",
43 (Builtin.bytes_type, Builtin.str_type) : "Cannot convert 'bytes' object to str implicitly. This is not portable to Py3.",
44 (Builtin.str_type, Builtin.unicode_type) : "str objects do not support coercion to unicode, use a unicode string literal instead (u'')",
45 (Builtin.str_type, Builtin.bytes_type) : "Cannot convert 'str' to 'bytes' implicitly. This is not portable.",
46 (Builtin.str_type, PyrexTypes.c_char_ptr_type) : "'str' objects do not support coercion to C types (use 'bytes'?).",
47 (PyrexTypes.c_char_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
48 (PyrexTypes.c_uchar_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
49 }.get
52 class ExprNode(Node):
53 # subexprs [string] Class var holding names of subexpr node attrs
54 # type PyrexType Type of the result
55 # result_code string Code fragment
56 # result_ctype string C type of result_code if different from type
57 # is_temp boolean Result is in a temporary variable
58 # is_sequence_constructor
59 # boolean Is a list or tuple constructor expression
60 # is_starred boolean Is a starred expression (e.g. '*a')
61 # saved_subexpr_nodes
62 # [ExprNode or [ExprNode or None] or None]
63 # Cached result of subexpr_nodes()
64 # use_managed_ref boolean use ref-counted temps/assignments/etc.
66 result_ctype = None
67 type = None
68 temp_code = None
69 old_temp = None # error checker for multiple frees etc.
70 use_managed_ref = True # can be set by optimisation transforms
72 # The Analyse Expressions phase for expressions is split
73 # into two sub-phases:
74 #
75 # Analyse Types
76 # Determines the result type of the expression based
77 # on the types of its sub-expressions, and inserts
78 # coercion nodes into the expression tree where needed.
79 # Marks nodes which will need to have temporary variables
80 # allocated.
81 #
82 # Allocate Temps
83 # Allocates temporary variables where needed, and fills
84 # in the result_code field of each node.
85 #
86 # ExprNode provides some convenience routines which
87 # perform both of the above phases. These should only
88 # be called from statement nodes, and only when no
89 # coercion nodes need to be added around the expression
90 # being analysed. In that case, the above two phases
91 # should be invoked separately.
92 #
93 # Framework code in ExprNode provides much of the common
94 # processing for the various phases. It makes use of the
95 # 'subexprs' class attribute of ExprNodes, which should
96 # contain a list of the names of attributes which can
97 # hold sub-nodes or sequences of sub-nodes.
98 #
99 # The framework makes use of a number of abstract methods.
100 # Their responsibilities are as follows.
101 #
102 # Declaration Analysis phase
103 #
104 # analyse_target_declaration
105 # Called during the Analyse Declarations phase to analyse
106 # the LHS of an assignment or argument of a del statement.
107 # Nodes which cannot be the LHS of an assignment need not
108 # implement it.
109 #
110 # Expression Analysis phase
111 #
112 # analyse_types
113 # - Call analyse_types on all sub-expressions.
114 # - Check operand types, and wrap coercion nodes around
115 # sub-expressions where needed.
116 # - Set the type of this node.
117 # - If a temporary variable will be required for the
118 # result, set the is_temp flag of this node.
119 #
120 # analyse_target_types
121 # Called during the Analyse Types phase to analyse
122 # the LHS of an assignment or argument of a del
123 # statement. Similar responsibilities to analyse_types.
124 #
125 # target_code
126 # Called by the default implementation of allocate_target_temps.
127 # Should return a C lvalue for assigning to the node. The default
128 # implementation calls calculate_result_code.
129 #
130 # check_const
131 # - Check that this node and its subnodes form a
132 # legal constant expression. If so, do nothing,
133 # otherwise call not_const.
134 #
135 # The default implementation of check_const
136 # assumes that the expression is not constant.
137 #
138 # check_const_addr
139 # - Same as check_const, except check that the
140 # expression is a C lvalue whose address is
141 # constant. Otherwise, call addr_not_const.
142 #
143 # The default implementation of calc_const_addr
144 # assumes that the expression is not a constant
145 # lvalue.
146 #
147 # Code Generation phase
148 #
149 # generate_evaluation_code
150 # - Call generate_evaluation_code for sub-expressions.
151 # - Perform the functions of generate_result_code
152 # (see below).
153 # - If result is temporary, call generate_disposal_code
154 # on all sub-expressions.
155 #
156 # A default implementation of generate_evaluation_code
157 # is provided which uses the following abstract methods:
158 #
159 # generate_result_code
160 # - Generate any C statements necessary to calculate
161 # the result of this node from the results of its
162 # sub-expressions.
163 #
164 # calculate_result_code
165 # - Should return a C code fragment evaluating to the
166 # result. This is only called when the result is not
167 # a temporary.
168 #
169 # generate_assignment_code
170 # Called on the LHS of an assignment.
171 # - Call generate_evaluation_code for sub-expressions.
172 # - Generate code to perform the assignment.
173 # - If the assignment absorbed a reference, call
174 # generate_post_assignment_code on the RHS,
175 # otherwise call generate_disposal_code on it.
176 #
177 # generate_deletion_code
178 # Called on an argument of a del statement.
179 # - Call generate_evaluation_code for sub-expressions.
180 # - Generate code to perform the deletion.
181 # - Call generate_disposal_code on all sub-expressions.
182 #
183 #
185 is_sequence_constructor = 0
186 is_attribute = 0
188 saved_subexpr_nodes = None
189 is_temp = 0
190 is_target = 0
191 is_starred = 0
193 constant_result = constant_value_not_set
195 try:
196 _get_child_attrs = operator.attrgetter('subexprs')
197 except AttributeError:
198 # Python 2.3
199 def _get_child_attrs(self):
200 return self.subexprs
201 child_attrs = property(fget=_get_child_attrs)
203 def not_implemented(self, method_name):
204 print_call_chain(method_name, "not implemented") ###
205 raise InternalError(
206 "%s.%s not implemented" %
207 (self.__class__.__name__, method_name))
209 def is_lvalue(self):
210 return 0
212 def is_ephemeral(self):
213 # An ephemeral node is one whose result is in
214 # a Python temporary and we suspect there are no
215 # other references to it. Certain operations are
216 # disallowed on such values, since they are
217 # likely to result in a dangling pointer.
218 return self.type.is_pyobject and self.is_temp
220 def subexpr_nodes(self):
221 # Extract a list of subexpression nodes based
222 # on the contents of the subexprs class attribute.
223 nodes = []
224 for name in self.subexprs:
225 item = getattr(self, name)
226 if item is not None:
227 if type(item) is list:
228 nodes.extend(item)
229 else:
230 nodes.append(item)
231 return nodes
233 def result(self):
234 if self.is_temp:
235 return self.temp_code
236 else:
237 return self.calculate_result_code()
239 def result_as(self, type = None):
240 # Return the result code cast to the specified C type.
241 return typecast(type, self.ctype(), self.result())
243 def py_result(self):
244 # Return the result code cast to PyObject *.
245 return self.result_as(py_object_type)
247 def ctype(self):
248 # Return the native C type of the result (i.e. the
249 # C type of the result_code expression).
250 return self.result_ctype or self.type
252 def get_constant_c_result_code(self):
253 # Return the constant value of this node as a result code
254 # string, or None if the node is not constant. This method
255 # can be called when the constant result code is required
256 # before the code generation phase.
257 #
258 # The return value is a string that can represent a simple C
259 # value, a constant C name or a constant C expression. If the
260 # node type depends on Python code, this must return None.
261 return None
263 def calculate_constant_result(self):
264 # Calculate the constant compile time result value of this
265 # expression and store it in ``self.constant_result``. Does
266 # nothing by default, thus leaving ``self.constant_result``
267 # unknown. If valid, the result can be an arbitrary Python
268 # value.
269 #
270 # This must only be called when it is assured that all
271 # sub-expressions have a valid constant_result value. The
272 # ConstantFolding transform will do this.
273 pass
275 def compile_time_value(self, denv):
276 # Return value of compile-time expression, or report error.
277 error(self.pos, "Invalid compile-time expression")
279 def compile_time_value_error(self, e):
280 error(self.pos, "Error in compile-time expression: %s: %s" % (
281 e.__class__.__name__, e))
283 # ------------- Declaration Analysis ----------------
285 def analyse_target_declaration(self, env):
286 error(self.pos, "Cannot assign to or delete this")
288 # ------------- Expression Analysis ----------------
290 def analyse_const_expression(self, env):
291 # Called during the analyse_declarations phase of a
292 # constant expression. Analyses the expression's type,
293 # checks whether it is a legal const expression,
294 # and determines its value.
295 self.analyse_types(env)
296 return self.check_const()
298 def analyse_expressions(self, env):
299 # Convenience routine performing both the Type
300 # Analysis and Temp Allocation phases for a whole
301 # expression.
302 self.analyse_types(env)
304 def analyse_target_expression(self, env, rhs):
305 # Convenience routine performing both the Type
306 # Analysis and Temp Allocation phases for the LHS of
307 # an assignment.
308 self.analyse_target_types(env)
310 def analyse_boolean_expression(self, env):
311 # Analyse expression and coerce to a boolean.
312 self.analyse_types(env)
313 bool = self.coerce_to_boolean(env)
314 return bool
316 def analyse_temp_boolean_expression(self, env):
317 # Analyse boolean expression and coerce result into
318 # a temporary. This is used when a branch is to be
319 # performed on the result and we won't have an
320 # opportunity to ensure disposal code is executed
321 # afterwards. By forcing the result into a temporary,
322 # we ensure that all disposal has been done by the
323 # time we get the result.
324 self.analyse_types(env)
325 bool = self.coerce_to_boolean(env)
326 temp_bool = bool.coerce_to_temp(env)
327 return temp_bool
329 # --------------- Type Inference -----------------
331 def type_dependencies(self, env):
332 # Returns the list of entries whose types must be determined
333 # before the type of self can be infered.
334 if hasattr(self, 'type') and self.type is not None:
335 return ()
336 return sum([node.type_dependencies(env) for node in self.subexpr_nodes()], ())
338 def infer_type(self, env):
339 # Attempt to deduce the type of self.
340 # Differs from analyse_types as it avoids unnecessary
341 # analysis of subexpressions, but can assume everything
342 # in self.type_dependencies() has been resolved.
343 if hasattr(self, 'type') and self.type is not None:
344 return self.type
345 elif hasattr(self, 'entry') and self.entry is not None:
346 return self.entry.type
347 else:
348 self.not_implemented("infer_type")
350 # --------------- Type Analysis ------------------
352 def analyse_as_module(self, env):
353 # If this node can be interpreted as a reference to a
354 # cimported module, return its scope, else None.
355 return None
357 def analyse_as_type(self, env):
358 # If this node can be interpreted as a reference to a
359 # type, return that type, else None.
360 return None
362 def analyse_as_extension_type(self, env):
363 # If this node can be interpreted as a reference to an
364 # extension type, return its type, else None.
365 return None
367 def analyse_types(self, env):
368 self.not_implemented("analyse_types")
370 def analyse_target_types(self, env):
371 self.analyse_types(env)
373 def nogil_check(self, env):
374 # By default, any expression based on Python objects is
375 # prevented in nogil environments. Subtypes must override
376 # this if they can work without the GIL.
377 if self.type.is_pyobject:
378 self.gil_error()
380 def gil_assignment_check(self, env):
381 if env.nogil and self.type.is_pyobject:
382 error(self.pos, "Assignment of Python object not allowed without gil")
384 def check_const(self):
385 self.not_const()
386 return False
388 def not_const(self):
389 error(self.pos, "Not allowed in a constant expression")
391 def check_const_addr(self):
392 self.addr_not_const()
393 return False
395 def addr_not_const(self):
396 error(self.pos, "Address is not constant")
398 # ----------------- Result Allocation -----------------
400 def result_in_temp(self):
401 # Return true if result is in a temporary owned by
402 # this node or one of its subexpressions. Overridden
403 # by certain nodes which can share the result of
404 # a subnode.
405 return self.is_temp
407 def target_code(self):
408 # Return code fragment for use as LHS of a C assignment.
409 return self.calculate_result_code()
411 def calculate_result_code(self):
412 self.not_implemented("calculate_result_code")
414 # def release_target_temp(self, env):
415 # # Release temporaries used by LHS of an assignment.
416 # self.release_subexpr_temps(env)
418 def allocate_temp_result(self, code):
419 if self.temp_code:
420 raise RuntimeError("Temp allocated multiple times in %r: %r" % (self.__class__.__name__, self.pos))
421 type = self.type
422 if not type.is_void:
423 if type.is_pyobject:
424 type = PyrexTypes.py_object_type
425 self.temp_code = code.funcstate.allocate_temp(
426 type, manage_ref=self.use_managed_ref)
427 else:
428 self.temp_code = None
430 def release_temp_result(self, code):
431 if not self.temp_code:
432 if self.old_temp:
433 raise RuntimeError("temp %s released multiple times in %s" % (
434 self.old_temp, self.__class__.__name__))
435 else:
436 raise RuntimeError("no temp, but release requested in %s" % (
437 self.__class__.__name__))
438 code.funcstate.release_temp(self.temp_code)
439 self.old_temp = self.temp_code
440 self.temp_code = None
442 # ---------------- Code Generation -----------------
444 def make_owned_reference(self, code):
445 # If result is a pyobject, make sure we own
446 # a reference to it.
447 if self.type.is_pyobject and not self.result_in_temp():
448 code.put_incref(self.result(), self.ctype())
450 def generate_evaluation_code(self, code):
451 code.mark_pos(self.pos)
453 # Generate code to evaluate this node and
454 # its sub-expressions, and dispose of any
455 # temporary results of its sub-expressions.
456 self.generate_subexpr_evaluation_code(code)
458 if self.is_temp:
459 self.allocate_temp_result(code)
461 self.generate_result_code(code)
462 if self.is_temp:
463 # If we are temp we do not need to wait until this node is disposed
464 # before disposing children.
465 self.generate_subexpr_disposal_code(code)
466 self.free_subexpr_temps(code)
468 def generate_subexpr_evaluation_code(self, code):
469 for node in self.subexpr_nodes():
470 node.generate_evaluation_code(code)
472 def generate_result_code(self, code):
473 self.not_implemented("generate_result_code")
475 def generate_disposal_code(self, code):
476 if self.is_temp:
477 if self.type.is_pyobject:
478 code.put_decref_clear(self.result(), self.ctype())
479 else:
480 # Already done if self.is_temp
481 self.generate_subexpr_disposal_code(code)
483 def generate_subexpr_disposal_code(self, code):
484 # Generate code to dispose of temporary results
485 # of all sub-expressions.
486 for node in self.subexpr_nodes():
487 node.generate_disposal_code(code)
489 def generate_post_assignment_code(self, code):
490 if self.is_temp:
491 if self.type.is_pyobject:
492 code.putln("%s = 0;" % self.result())
493 else:
494 self.generate_subexpr_disposal_code(code)
496 def generate_assignment_code(self, rhs, code):
497 # Stub method for nodes which are not legal as
498 # the LHS of an assignment. An error will have
499 # been reported earlier.
500 pass
502 def generate_deletion_code(self, code):
503 # Stub method for nodes that are not legal as
504 # the argument of a del statement. An error
505 # will have been reported earlier.
506 pass
508 def free_temps(self, code):
509 if self.is_temp:
510 if not self.type.is_void:
511 self.release_temp_result(code)
512 else:
513 self.free_subexpr_temps(code)
515 def free_subexpr_temps(self, code):
516 for sub in self.subexpr_nodes():
517 sub.free_temps(code)
519 # ---------------- Annotation ---------------------
521 def annotate(self, code):
522 for node in self.subexpr_nodes():
523 node.annotate(code)
525 # ----------------- Coercion ----------------------
527 def coerce_to(self, dst_type, env):
528 # Coerce the result so that it can be assigned to
529 # something of type dst_type. If processing is necessary,
530 # wraps this node in a coercion node and returns that.
531 # Otherwise, returns this node unchanged.
532 #
533 # This method is called during the analyse_expressions
534 # phase of the src_node's processing.
535 src = self
536 src_type = self.type
537 src_is_py_type = src_type.is_pyobject
538 dst_is_py_type = dst_type.is_pyobject
540 if self.check_for_coercion_error(dst_type):
541 return self
543 if dst_type.is_pyobject:
544 if not src.type.is_pyobject:
545 src = CoerceToPyTypeNode(src, env)
546 if not src.type.subtype_of(dst_type):
547 if not isinstance(src, NoneNode):
548 src = PyTypeTestNode(src, dst_type, env)
549 elif src.type.is_pyobject:
550 src = CoerceFromPyTypeNode(dst_type, src, env)
551 elif (dst_type.is_complex
552 and src_type != dst_type
553 and dst_type.assignable_from(src_type)):
554 src = CoerceToComplexNode(src, dst_type, env)
555 else: # neither src nor dst are py types
556 # Added the string comparison, since for c types that
557 # is enough, but Cython gets confused when the types are
558 # in different pxi files.
559 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
560 self.fail_assignment(dst_type)
561 return src
563 def fail_assignment(self, dst_type):
564 error(self.pos, "Cannot assign type '%s' to '%s'" % (self.type, dst_type))
566 def check_for_coercion_error(self, dst_type, fail=False, default=None):
567 if fail and not default:
568 default = "Cannot assign type '%(FROM)s' to '%(TO)s'"
569 message = find_coercion_error((self.type, dst_type), default)
570 if message is not None:
571 error(self.pos, message % {'FROM': self.type, 'TO': dst_type})
572 return True
573 if fail:
574 self.fail_assignment(dst_type)
575 return True
576 return False
578 def coerce_to_pyobject(self, env):
579 return self.coerce_to(PyrexTypes.py_object_type, env)
581 def coerce_to_boolean(self, env):
582 # Coerce result to something acceptable as
583 # a boolean value.
584 type = self.type
585 if type.is_pyobject or type.is_ptr or type.is_float:
586 return CoerceToBooleanNode(self, env)
587 else:
588 if not type.is_int and not type.is_error:
589 error(self.pos,
590 "Type '%s' not acceptable as a boolean" % type)
591 return self
593 def coerce_to_integer(self, env):
594 # If not already some C integer type, coerce to longint.
595 if self.type.is_int:
596 return self
597 else:
598 return self.coerce_to(PyrexTypes.c_long_type, env)
600 def coerce_to_temp(self, env):
601 # Ensure that the result is in a temporary.
602 if self.result_in_temp():
603 return self
604 else:
605 return CoerceToTempNode(self, env)
607 def coerce_to_simple(self, env):
608 # Ensure that the result is simple (see is_simple).
609 if self.is_simple():
610 return self
611 else:
612 return self.coerce_to_temp(env)
614 def is_simple(self):
615 # A node is simple if its result is something that can
616 # be referred to without performing any operations, e.g.
617 # a constant, local var, C global var, struct member
618 # reference, or temporary.
619 return self.result_in_temp()
621 def as_cython_attribute(self):
622 return None
624 class AtomicExprNode(ExprNode):
625 # Abstract base class for expression nodes which have
626 # no sub-expressions.
628 subexprs = []
630 # Override to optimize -- we know we have no children
631 def generate_subexpr_evaluation_code(self, code):
632 pass
633 def generate_subexpr_disposal_code(self, code):
634 pass
636 class PyConstNode(AtomicExprNode):
637 # Abstract base class for constant Python values.
639 is_literal = 1
640 type = py_object_type
642 def is_simple(self):
643 return 1
645 def analyse_types(self, env):
646 pass
648 def calculate_result_code(self):
649 return self.value
651 def generate_result_code(self, code):
652 pass
655 class NoneNode(PyConstNode):
656 # The constant value None
658 value = "Py_None"
660 constant_result = None
662 nogil_check = None
664 def compile_time_value(self, denv):
665 return None
667 class EllipsisNode(PyConstNode):
668 # '...' in a subscript list.
670 value = "Py_Ellipsis"
672 constant_result = Ellipsis
674 def compile_time_value(self, denv):
675 return Ellipsis
678 class ConstNode(AtomicExprNode):
679 # Abstract base type for literal constant nodes.
680 #
681 # value string C code fragment
683 is_literal = 1
684 nogil_check = None
686 def is_simple(self):
687 return 1
689 def analyse_types(self, env):
690 pass # Types are held in class variables
692 def check_const(self):
693 return True
695 def get_constant_c_result_code(self):
696 return self.calculate_result_code()
698 def calculate_result_code(self):
699 return str(self.value)
701 def generate_result_code(self, code):
702 pass
705 class BoolNode(ConstNode):
706 type = PyrexTypes.c_bint_type
707 # The constant value True or False
709 def calculate_constant_result(self):
710 self.constant_result = self.value
712 def compile_time_value(self, denv):
713 return self.value
715 def calculate_result_code(self):
716 return str(int(self.value))
719 class NullNode(ConstNode):
720 type = PyrexTypes.c_null_ptr_type
721 value = "NULL"
722 constant_result = 0
724 def get_constant_c_result_code(self):
725 return self.value
728 class CharNode(ConstNode):
729 type = PyrexTypes.c_char_type
731 def calculate_constant_result(self):
732 self.constant_result = ord(self.value)
734 def compile_time_value(self, denv):
735 return ord(self.value)
737 def calculate_result_code(self):
738 return "'%s'" % StringEncoding.escape_char(self.value)
741 class IntNode(ConstNode):
743 # unsigned "" or "U"
744 # longness "" or "L" or "LL"
746 unsigned = ""
747 longness = ""
748 type = PyrexTypes.c_long_type
750 def coerce_to(self, dst_type, env):
751 if dst_type.is_numeric and not dst_type.is_complex:
752 self.type = PyrexTypes.c_long_type
753 return self
754 # Arrange for a Python version of the number to be pre-allocated
755 # when coercing to a Python type.
756 if dst_type.is_pyobject:
757 self.type = PyrexTypes.py_object_type
758 # We still need to perform normal coerce_to processing on the
759 # result, because we might be coercing to an extension type,
760 # in which case a type test node will be needed.
761 return ConstNode.coerce_to(self, dst_type, env)
763 def coerce_to_boolean(self, env):
764 self.type = PyrexTypes.c_bint_type
765 return self
767 def generate_evaluation_code(self, code):
768 if self.type.is_pyobject:
769 self.result_code = code.get_py_num(self.value, self.longness)
770 else:
771 self.result_code = self.get_constant_c_result_code()
773 def get_constant_c_result_code(self):
774 return str(self.value) + self.unsigned + self.longness
776 def calculate_result_code(self):
777 return self.result_code
779 def calculate_constant_result(self):
780 self.constant_result = int(self.value, 0)
782 def compile_time_value(self, denv):
783 return int(self.value, 0)
786 class FloatNode(ConstNode):
787 type = PyrexTypes.c_double_type
789 def calculate_constant_result(self):
790 self.constant_result = float(self.value)
792 def compile_time_value(self, denv):
793 return float(self.value)
795 def calculate_result_code(self):
796 strval = repr(float(self.value))
797 if strval == 'nan':
798 return "(Py_HUGE_VAL * 0)"
799 elif strval == 'inf':
800 return "Py_HUGE_VAL"
801 elif strval == '-inf':
802 return "(-Py_HUGE_VAL)"
803 else:
804 return strval
807 class BytesNode(ConstNode):
808 # A char* or bytes literal
809 #
810 # value BytesLiteral
812 type = PyrexTypes.c_char_ptr_type
814 def compile_time_value(self, denv):
815 return self.value
817 def analyse_as_type(self, env):
818 type = PyrexTypes.parse_basic_type(self.value)
819 if type is not None:
820 return type
821 from TreeFragment import TreeFragment
822 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
823 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
824 sizeof_node = declaration.root.stats[0].expr
825 sizeof_node.analyse_types(env)
826 if isinstance(sizeof_node, SizeofTypeNode):
827 return sizeof_node.arg_type
829 def can_coerce_to_char_literal(self):
830 return len(self.value) == 1
832 def coerce_to(self, dst_type, env):
833 if dst_type == PyrexTypes.c_char_ptr_type:
834 self.type = PyrexTypes.c_char_ptr_type
835 return self
836 elif dst_type == PyrexTypes.c_uchar_ptr_type:
837 self.type = PyrexTypes.c_char_ptr_type
838 return CastNode(self, PyrexTypes.c_uchar_ptr_type)
840 if dst_type.is_int:
841 if not self.can_coerce_to_char_literal():
842 error(self.pos, "Only single-character strings can be coerced into ints.")
843 return self
844 return CharNode(self.pos, value=self.value)
846 node = self
847 if not self.type.is_pyobject:
848 if dst_type in (py_object_type, Builtin.bytes_type):
849 node = self.as_py_string_node(env)
850 elif dst_type.is_pyobject:
851 self.fail_assignment(dst_type)
852 return self
853 else:
854 node = self
855 elif dst_type.is_pyobject and dst_type is not py_object_type:
856 self.check_for_coercion_error(dst_type, fail=True)
857 return self
859 # We still need to perform normal coerce_to processing on the
860 # result, because we might be coercing to an extension type,
861 # in which case a type test node will be needed.
862 return ConstNode.coerce_to(node, dst_type, env)
864 def as_py_string_node(self, env):
865 # Return a new BytesNode with the same value as this node
866 # but whose type is a Python type instead of a C type.
867 return BytesNode(self.pos, value = self.value, type = Builtin.bytes_type)
869 def generate_evaluation_code(self, code):
870 if self.type.is_pyobject:
871 self.result_code = code.get_py_string_const(self.value)
872 else:
873 self.result_code = code.get_string_const(self.value)
875 def get_constant_c_result_code(self):
876 return None # FIXME
878 def calculate_result_code(self):
879 return self.result_code
882 class UnicodeNode(PyConstNode):
883 # A Python unicode object
884 #
885 # value EncodedString
887 type = unicode_type
889 def coerce_to(self, dst_type, env):
890 if dst_type is self.type:
891 pass
892 elif not dst_type.is_pyobject:
893 error(self.pos, "Unicode objects do not support coercion to C types.")
894 elif dst_type is not py_object_type:
895 if not self.check_for_coercion_error(dst_type):
896 self.fail_assignment(dst_type)
897 return self
899 def generate_evaluation_code(self, code):
900 self.result_code = code.get_py_string_const(self.value)
902 def calculate_result_code(self):
903 return self.result_code
905 def compile_time_value(self, env):
906 return self.value
909 class StringNode(PyConstNode):
910 # A Python str object, i.e. a byte string in Python 2.x and a
911 # unicode string in Python 3.x
912 #
913 # value BytesLiteral or EncodedString
914 # is_identifier boolean
916 type = str_type
917 is_identifier = None
919 def coerce_to(self, dst_type, env):
920 if dst_type is not py_object_type and not str_type.subtype_of(dst_type):
921 # if dst_type is Builtin.bytes_type:
922 # # special case: bytes = 'str literal'
923 # return BytesNode(self.pos, value=self.value)
924 if not dst_type.is_pyobject:
925 return BytesNode(self.pos, value=self.value).coerce_to(dst_type, env)
926 self.check_for_coercion_error(dst_type, fail=True)
928 # this will be a unicode string in Py3, so make sure we can decode it
929 if self.value.encoding:
930 encoding = self.value.encoding
931 try:
932 self.value.decode(encoding)
933 except UnicodeDecodeError:
934 error(self.pos, "String decoding as '%s' failed. Consider using a byte string or unicode string explicitly, or adjust the source code encoding." % encoding)
936 return self
938 def can_coerce_to_char_literal(self):
939 return not self.is_identifier and len(self.value) == 1
941 def generate_evaluation_code(self, code):
942 self.result_code = code.get_py_string_const(
943 self.value, identifier=self.is_identifier, is_str=True)
945 def get_constant_c_result_code(self):
946 return None
948 def calculate_result_code(self):
949 return self.result_code
951 def compile_time_value(self, env):
952 return self.value
955 class IdentifierStringNode(StringNode):
956 # A special str value that represents an identifier (bytes in Py2,
957 # unicode in Py3).
958 is_identifier = True
961 class LongNode(AtomicExprNode):
962 # Python long integer literal
963 #
964 # value string
966 type = py_object_type
968 def calculate_constant_result(self):
969 self.constant_result = long(self.value)
971 def compile_time_value(self, denv):
972 return long(self.value)
974 def analyse_types(self, env):
975 self.is_temp = 1
977 gil_message = "Constructing Python long int"
979 def generate_result_code(self, code):
980 code.putln(
981 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
982 self.result(),
983 self.value,
984 code.error_goto_if_null(self.result(), self.pos)))
985 code.put_gotref(self.py_result())
988 class ImagNode(AtomicExprNode):
989 # Imaginary number literal
990 #
991 # value float imaginary part
993 type = PyrexTypes.c_double_complex_type
995 def calculate_constant_result(self):
996 self.constant_result = complex(0.0, self.value)
998 def compile_time_value(self, denv):
999 return complex(0.0, self.value)
1001 def analyse_types(self, env):
1002 self.type.create_declaration_utility_code(env)
1004 def coerce_to(self, dst_type, env):
1005 # Arrange for a Python version of the number to be pre-allocated
1006 # when coercing to a Python type.
1007 if dst_type.is_pyobject:
1008 self.is_temp = 1
1009 self.type = PyrexTypes.py_object_type
1010 # We still need to perform normal coerce_to processing on the
1011 # result, because we might be coercing to an extension type,
1012 # in which case a type test node will be needed.
1013 return AtomicExprNode.coerce_to(self, dst_type, env)
1015 gil_message = "Constructing complex number"
1017 def calculate_result_code(self):
1018 if self.type.is_pyobject:
1019 return self.result()
1020 else:
1021 return "%s(0, %r)" % (self.type.from_parts, float(self.value))
1023 def generate_result_code(self, code):
1024 if self.type.is_pyobject:
1025 code.putln(
1026 "%s = PyComplex_FromDoubles(0.0, %r); %s" % (
1027 self.result(),
1028 float(self.value),
1029 code.error_goto_if_null(self.result(), self.pos)))
1030 code.put_gotref(self.py_result())
1034 class NameNode(AtomicExprNode):
1035 # Reference to a local or global variable name.
1037 # name string Python name of the variable
1038 # entry Entry Symbol table entry
1039 # type_entry Entry For extension type names, the original type entry
1041 is_name = True
1042 is_cython_module = False
1043 cython_attribute = None
1044 lhs_of_first_assignment = False
1045 is_used_as_rvalue = 0
1046 entry = None
1047 type_entry = None
1049 def create_analysed_rvalue(pos, env, entry):
1050 node = NameNode(pos)
1051 node.analyse_types(env, entry=entry)
1052 return node
1054 def as_cython_attribute(self):
1055 return self.cython_attribute
1057 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
1059 def type_dependencies(self, env):
1060 if self.entry is None:
1061 self.entry = env.lookup(self.name)
1062 if self.entry is not None and self.entry.type.is_unspecified:
1063 return (self.entry,)
1064 else:
1065 return ()
1067 def infer_type(self, env):
1068 if self.entry is None:
1069 self.entry = env.lookup(self.name)
1070 if self.entry is None:
1071 return py_object_type
1072 elif (self.entry.type.is_extension_type or self.entry.type.is_builtin_type) and \
1073 self.name == self.entry.type.name:
1074 # Unfortunately the type attribute of type objects
1075 # is used for the pointer to the type they represent.
1076 return type_type
1077 else:
1078 return self.entry.type
1080 def compile_time_value(self, denv):
1081 try:
1082 return denv.lookup(self.name)
1083 except KeyError:
1084 error(self.pos, "Compile-time name '%s' not defined" % self.name)
1086 def get_constant_c_result_code(self):
1087 if not self.entry or self.entry.type.is_pyobject:
1088 return None
1089 return self.entry.cname
1091 def coerce_to(self, dst_type, env):
1092 # If coercing to a generic pyobject and this is a builtin
1093 # C function with a Python equivalent, manufacture a NameNode
1094 # referring to the Python builtin.
1095 #print "NameNode.coerce_to:", self.name, dst_type ###
1096 if dst_type is py_object_type:
1097 entry = self.entry
1098 if entry and entry.is_cfunction:
1099 var_entry = entry.as_variable
1100 if var_entry:
1101 if var_entry.is_builtin and Options.cache_builtins:
1102 var_entry = env.declare_builtin(var_entry.name, self.pos)
1103 node = NameNode(self.pos, name = self.name)
1104 node.entry = var_entry
1105 node.analyse_rvalue_entry(env)
1106 return node
1107 return super(NameNode, self).coerce_to(dst_type, env)
1109 def analyse_as_module(self, env):
1110 # Try to interpret this as a reference to a cimported module.
1111 # Returns the module scope, or None.
1112 entry = self.entry
1113 if not entry:
1114 entry = env.lookup(self.name)
1115 if entry and entry.as_module:
1116 return entry.as_module
1117 return None
1119 def analyse_as_type(self, env):
1120 if self.cython_attribute:
1121 type = PyrexTypes.parse_basic_type(self.cython_attribute)
1122 else:
1123 type = PyrexTypes.parse_basic_type(self.name)
1124 if type:
1125 return type
1126 entry = self.entry
1127 if not entry:
1128 entry = env.lookup(self.name)
1129 if entry and entry.is_type:
1130 return entry.type
1131 else:
1132 return None
1134 def analyse_as_extension_type(self, env):
1135 # Try to interpret this as a reference to an extension type.
1136 # Returns the extension type, or None.
1137 entry = self.entry
1138 if not entry:
1139 entry = env.lookup(self.name)
1140 if entry and entry.is_type and entry.type.is_extension_type:
1141 return entry.type
1142 else:
1143 return None
1145 def analyse_target_declaration(self, env):
1146 if not self.entry:
1147 self.entry = env.lookup_here(self.name)
1148 if not self.entry:
1149 if env.directives['infer_types'] != 'none':
1150 type = unspecified_type
1151 else:
1152 type = py_object_type
1153 self.entry = env.declare_var(self.name, type, self.pos)
1154 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1155 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1156 if self.entry.is_declared_generic:
1157 self.result_ctype = py_object_type
1159 def analyse_types(self, env):
1160 if self.entry is None:
1161 self.entry = env.lookup(self.name)
1162 if not self.entry:
1163 self.entry = env.declare_builtin(self.name, self.pos)
1164 if not self.entry:
1165 self.type = PyrexTypes.error_type
1166 return
1167 entry = self.entry
1168 if entry:
1169 entry.used = 1
1170 if entry.type.is_buffer:
1171 import Buffer
1172 Buffer.used_buffer_aux_vars(entry)
1173 if entry.utility_code:
1174 env.use_utility_code(entry.utility_code)
1175 self.analyse_rvalue_entry(env)
1177 def analyse_target_types(self, env):
1178 self.analyse_entry(env)
1179 if not self.is_lvalue():
1180 error(self.pos, "Assignment to non-lvalue '%s'"
1181 % self.name)
1182 self.type = PyrexTypes.error_type
1183 self.entry.used = 1
1184 if self.entry.type.is_buffer:
1185 import Buffer
1186 Buffer.used_buffer_aux_vars(self.entry)
1188 def analyse_rvalue_entry(self, env):
1189 #print "NameNode.analyse_rvalue_entry:", self.name ###
1190 #print "Entry:", self.entry.__dict__ ###
1191 self.analyse_entry(env)
1192 entry = self.entry
1193 if entry.is_declared_generic:
1194 self.result_ctype = py_object_type
1195 if entry.is_pyglobal or entry.is_builtin:
1196 if Options.cache_builtins and entry.is_builtin:
1197 self.is_temp = 0
1198 else:
1199 self.is_temp = 1
1200 self.is_used_as_rvalue = 1
1201 env.use_utility_code(get_name_interned_utility_code)
1203 def nogil_check(self, env):
1204 if self.is_used_as_rvalue:
1205 entry = self.entry
1206 if entry.is_builtin:
1207 # if not Options.cache_builtins: # cached builtins are ok
1208 self.gil_error()
1209 elif entry.is_pyglobal:
1210 self.gil_error()
1212 gil_message = "Accessing Python global or builtin"
1214 def analyse_entry(self, env):
1215 #print "NameNode.analyse_entry:", self.name ###
1216 self.check_identifier_kind()
1217 entry = self.entry
1218 type = entry.type
1219 self.type = type
1221 def check_identifier_kind(self):
1222 # Check that this is an appropriate kind of name for use in an
1223 # expression. Also finds the variable entry associated with
1224 # an extension type.
1225 entry = self.entry
1226 if entry.is_type and entry.type.is_extension_type:
1227 self.type_entry = entry
1228 if not (entry.is_const or entry.is_variable
1229 or entry.is_builtin or entry.is_cfunction):
1230 if self.entry.as_variable:
1231 self.entry = self.entry.as_variable
1232 else:
1233 error(self.pos,
1234 "'%s' is not a constant, variable or function identifier" % self.name)
1236 def is_simple(self):
1237 # If it's not a C variable, it'll be in a temp.
1238 return 1
1240 def calculate_target_results(self, env):
1241 pass
1243 def check_const(self):
1244 entry = self.entry
1245 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1246 self.not_const()
1247 return False
1248 return True
1250 def check_const_addr(self):
1251 entry = self.entry
1252 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1253 self.addr_not_const()
1254 return False
1255 return True
1257 def is_lvalue(self):
1258 return self.entry.is_variable and \
1259 not self.entry.type.is_array and \
1260 not self.entry.is_readonly
1262 def is_ephemeral(self):
1263 # Name nodes are never ephemeral, even if the
1264 # result is in a temporary.
1265 return 0
1267 def calculate_result_code(self):
1268 entry = self.entry
1269 if not entry:
1270 return "<error>" # There was an error earlier
1271 return entry.cname
1273 def generate_result_code(self, code):
1274 assert hasattr(self, 'entry')
1275 entry = self.entry
1276 if entry is None:
1277 return # There was an error earlier
1278 if entry.is_builtin and Options.cache_builtins:
1279 return # Lookup already cached
1280 elif entry.is_pyglobal or entry.is_builtin:
1281 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1282 interned_cname = code.intern_identifier(self.entry.name)
1283 if entry.is_builtin:
1284 namespace = Naming.builtins_cname
1285 else: # entry.is_pyglobal
1286 namespace = entry.scope.namespace_cname
1287 code.putln(
1288 '%s = __Pyx_GetName(%s, %s); %s' % (
1289 self.result(),
1290 namespace,
1291 interned_cname,
1292 code.error_goto_if_null(self.result(), self.pos)))
1293 code.put_gotref(self.py_result())
1295 elif entry.is_local and False:
1296 # control flow not good enough yet
1297 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1298 if assigned is False:
1299 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1300 elif not Options.init_local_none and assigned is None:
1301 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
1302 (entry.cname, entry.name, code.error_goto(self.pos)))
1303 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1305 def generate_assignment_code(self, rhs, code):
1306 #print "NameNode.generate_assignment_code:", self.name ###
1307 entry = self.entry
1308 if entry is None:
1309 return # There was an error earlier
1311 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1312 and not self.lhs_of_first_assignment):
1313 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1315 # is_pyglobal seems to be True for module level-globals only.
1316 # We use this to access class->tp_dict if necessary.
1317 if entry.is_pyglobal:
1318 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1319 interned_cname = code.intern_identifier(self.entry.name)
1320 namespace = self.entry.scope.namespace_cname
1321 if entry.is_member:
1322 # if the entry is a member we have to cheat: SetAttr does not work
1323 # on types, so we create a descriptor which is then added to tp_dict
1324 code.put_error_if_neg(self.pos,
1325 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1326 namespace,
1327 interned_cname,
1328 rhs.py_result()))
1329 rhs.generate_disposal_code(code)
1330 rhs.free_temps(code)
1331 # in Py2.6+, we need to invalidate the method cache
1332 code.putln("PyType_Modified(%s);" %
1333 entry.scope.parent_type.typeptr_cname)
1334 else:
1335 code.put_error_if_neg(self.pos,
1336 'PyObject_SetAttr(%s, %s, %s)' % (
1337 namespace,
1338 interned_cname,
1339 rhs.py_result()))
1340 if debug_disposal_code:
1341 print("NameNode.generate_assignment_code:")
1342 print("...generating disposal code for %s" % rhs)
1343 rhs.generate_disposal_code(code)
1344 rhs.free_temps(code)
1345 else:
1346 if self.type.is_buffer:
1347 # Generate code for doing the buffer release/acquisition.
1348 # This might raise an exception in which case the assignment (done
1349 # below) will not happen.
1351 # The reason this is not in a typetest-like node is because the
1352 # variables that the acquired buffer info is stored to is allocated
1353 # per entry and coupled with it.
1354 self.generate_acquire_buffer(rhs, code)
1356 if self.type.is_pyobject:
1357 #print "NameNode.generate_assignment_code: to", self.name ###
1358 #print "...from", rhs ###
1359 #print "...LHS type", self.type, "ctype", self.ctype() ###
1360 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1361 if self.use_managed_ref:
1362 rhs.make_owned_reference(code)
1363 if entry.is_cglobal:
1364 code.put_gotref(self.py_result())
1365 if self.use_managed_ref and not self.lhs_of_first_assignment:
1366 if entry.is_local and not Options.init_local_none:
1367 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1368 if initalized is True:
1369 code.put_decref(self.result(), self.ctype())
1370 elif initalized is None:
1371 code.put_xdecref(self.result(), self.ctype())
1372 else:
1373 code.put_decref(self.result(), self.ctype())
1374 if self.use_managed_ref:
1375 if entry.is_cglobal:
1376 code.put_giveref(rhs.py_result())
1377 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1378 if debug_disposal_code:
1379 print("NameNode.generate_assignment_code:")
1380 print("...generating post-assignment code for %s" % rhs)
1381 rhs.generate_post_assignment_code(code)
1382 rhs.free_temps(code)
1384 def generate_acquire_buffer(self, rhs, code):
1385 # rhstmp is only used in case the rhs is a complicated expression leading to
1386 # the object, to avoid repeating the same C expression for every reference
1387 # to the rhs. It does NOT hold a reference.
1388 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1389 if pretty_rhs:
1390 rhstmp = rhs.result_as(self.ctype())
1391 else:
1392 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1393 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1395 buffer_aux = self.entry.buffer_aux
1396 bufstruct = buffer_aux.buffer_info_var.cname
1397 import Buffer
1398 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1399 is_initialized=not self.lhs_of_first_assignment,
1400 pos=self.pos, code=code)
1402 if not pretty_rhs:
1403 code.putln("%s = 0;" % rhstmp)
1404 code.funcstate.release_temp(rhstmp)
1406 def generate_deletion_code(self, code):
1407 if self.entry is None:
1408 return # There was an error earlier
1409 if not self.entry.is_pyglobal:
1410 error(self.pos, "Deletion of local or C global name not supported")
1411 return
1412 code.put_error_if_neg(self.pos,
1413 '__Pyx_DelAttrString(%s, "%s")' % (
1414 Naming.module_cname,
1415 self.entry.name))
1417 def annotate(self, code):
1418 if hasattr(self, 'is_called') and self.is_called:
1419 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1420 if self.type.is_pyobject:
1421 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1422 else:
1423 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1425 class BackquoteNode(ExprNode):
1426 # `expr`
1428 # arg ExprNode
1430 type = py_object_type
1432 subexprs = ['arg']
1434 def analyse_types(self, env):
1435 self.arg.analyse_types(env)
1436 self.arg = self.arg.coerce_to_pyobject(env)
1437 self.is_temp = 1
1439 gil_message = "Backquote expression"
1441 def calculate_constant_result(self):
1442 self.constant_result = repr(self.arg.constant_result)
1444 def generate_result_code(self, code):
1445 code.putln(
1446 "%s = PyObject_Repr(%s); %s" % (
1447 self.result(),
1448 self.arg.py_result(),
1449 code.error_goto_if_null(self.result(), self.pos)))
1450 code.put_gotref(self.py_result())
1454 class ImportNode(ExprNode):
1455 # Used as part of import statement implementation.
1456 # Implements result =
1457 # __import__(module_name, globals(), None, name_list)
1459 # module_name StringNode dotted name of module
1460 # name_list ListNode or None list of names to be imported
1462 type = py_object_type
1464 subexprs = ['module_name', 'name_list']
1466 def analyse_types(self, env):
1467 self.module_name.analyse_types(env)
1468 self.module_name = self.module_name.coerce_to_pyobject(env)
1469 if self.name_list:
1470 self.name_list.analyse_types(env)
1471 self.name_list.coerce_to_pyobject(env)
1472 self.is_temp = 1
1473 env.use_utility_code(import_utility_code)
1475 gil_message = "Python import"
1477 def generate_result_code(self, code):
1478 if self.name_list:
1479 name_list_code = self.name_list.py_result()
1480 else:
1481 name_list_code = "0"
1482 code.putln(
1483 "%s = __Pyx_Import(%s, %s); %s" % (
1484 self.result(),
1485 self.module_name.py_result(),
1486 name_list_code,
1487 code.error_goto_if_null(self.result(), self.pos)))
1488 code.put_gotref(self.py_result())
1491 class IteratorNode(ExprNode):
1492 # Used as part of for statement implementation.
1494 # allocate_counter_temp/release_counter_temp needs to be called
1495 # by parent (ForInStatNode)
1497 # Implements result = iter(sequence)
1499 # sequence ExprNode
1501 type = py_object_type
1503 subexprs = ['sequence']
1505 def analyse_types(self, env):
1506 self.sequence.analyse_types(env)
1507 self.sequence = self.sequence.coerce_to_pyobject(env)
1508 self.is_temp = 1
1510 gil_message = "Iterating over Python object"
1512 def allocate_counter_temp(self, code):
1513 self.counter_cname = code.funcstate.allocate_temp(
1514 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1516 def release_counter_temp(self, code):
1517 code.funcstate.release_temp(self.counter_cname)
1519 def generate_result_code(self, code):
1520 is_builtin_sequence = self.sequence.type is list_type or \
1521 self.sequence.type is tuple_type
1522 may_be_a_sequence = is_builtin_sequence or not self.sequence.type.is_builtin_type
1523 if is_builtin_sequence:
1524 code.putln(
1525 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1526 elif may_be_a_sequence:
1527 code.putln(
1528 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1529 self.sequence.py_result(),
1530 self.sequence.py_result()))
1531 if may_be_a_sequence:
1532 code.putln(
1533 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
1534 self.counter_cname,
1535 self.result(),
1536 self.sequence.py_result(),
1537 self.result()))
1538 code.putln("} else {")
1539 if is_builtin_sequence:
1540 code.putln(
1541 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1542 code.error_goto(self.pos))
1543 else:
1544 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1545 self.counter_cname,
1546 self.result(),
1547 self.sequence.py_result(),
1548 code.error_goto_if_null(self.result(), self.pos)))
1549 code.put_gotref(self.py_result())
1550 if may_be_a_sequence:
1551 code.putln("}")
1554 class NextNode(AtomicExprNode):
1555 # Used as part of for statement implementation.
1556 # Implements result = iterator.next()
1557 # Created during analyse_types phase.
1558 # The iterator is not owned by this node.
1560 # iterator ExprNode
1562 type = py_object_type
1564 def __init__(self, iterator, env):
1565 self.pos = iterator.pos
1566 self.iterator = iterator
1567 self.is_temp = 1
1569 def generate_result_code(self, code):
1570 sequence_type = self.iterator.sequence.type
1571 if sequence_type is list_type:
1572 type_checks = [(list_type, "List")]
1573 elif sequence_type is tuple_type:
1574 type_checks = [(tuple_type, "Tuple")]
1575 elif not sequence_type.is_builtin_type:
1576 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1577 else:
1578 type_checks = []
1580 for py_type, prefix in type_checks:
1581 if len(type_checks) > 1:
1582 code.putln(
1583 "if (likely(Py%s_CheckExact(%s))) {" % (
1584 prefix, self.iterator.py_result()))
1585 code.putln(
1586 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1587 self.iterator.counter_cname,
1588 prefix,
1589 self.iterator.py_result()))
1590 code.putln(
1591 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1592 self.result(),
1593 prefix,
1594 self.iterator.py_result(),
1595 self.iterator.counter_cname,
1596 self.result(),
1597 self.iterator.counter_cname))
1598 if len(type_checks) > 1:
1599 code.put("} else ")
1600 if len(type_checks) == 1:
1601 return
1602 code.putln("{")
1603 code.putln(
1604 "%s = PyIter_Next(%s);" % (
1605 self.result(),
1606 self.iterator.py_result()))
1607 code.putln(
1608 "if (!%s) {" %
1609 self.result())
1610 code.putln(code.error_goto_if_PyErr(self.pos))
1611 code.putln("break;")
1612 code.putln("}")
1613 code.put_gotref(self.py_result())
1614 code.putln("}")
1617 class ExcValueNode(AtomicExprNode):
1618 # Node created during analyse_types phase
1619 # of an ExceptClauseNode to fetch the current
1620 # exception value.
1622 type = py_object_type
1624 def __init__(self, pos, env):
1625 ExprNode.__init__(self, pos)
1627 def set_var(self, var):
1628 self.var = var
1630 def calculate_result_code(self):
1631 return self.var
1633 def generate_result_code(self, code):
1634 pass
1636 def analyse_types(self, env):
1637 pass
1640 class TempNode(ExprNode):
1641 # Node created during analyse_types phase
1642 # of some nodes to hold a temporary value.
1644 # Note: One must call "allocate" and "release" on
1645 # the node during code generation to get/release the temp.
1646 # This is because the temp result is often used outside of
1647 # the regular cycle.
1649 subexprs = []
1651 def __init__(self, pos, type, env):
1652 ExprNode.__init__(self, pos)
1653 self.type = type
1654 if type.is_pyobject:
1655 self.result_ctype = py_object_type
1656 self.is_temp = 1
1658 def analyse_types(self, env):
1659 return self.type
1661 def generate_result_code(self, code):
1662 pass
1664 def allocate(self, code):
1665 self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=True)
1667 def release(self, code):
1668 code.funcstate.release_temp(self.temp_cname)
1669 self.temp_cname = None
1671 def result(self):
1672 try:
1673 return self.temp_cname
1674 except:
1675 assert False, "Remember to call allocate/release on TempNode"
1676 raise
1678 # Do not participate in normal temp alloc/dealloc:
1679 def allocate_temp_result(self, code):
1680 pass
1682 def release_temp_result(self, code):
1683 pass
1685 class PyTempNode(TempNode):
1686 # TempNode holding a Python value.
1688 def __init__(self, pos, env):
1689 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1691 class RawCNameExprNode(ExprNode):
1692 subexprs = []
1694 def __init__(self, pos, type=None):
1695 self.pos = pos
1696 self.type = type
1698 def analyse_types(self, env):
1699 return self.type
1701 def set_cname(self, cname):
1702 self.cname = cname
1704 def result(self):
1705 return self.cname
1707 def generate_result_code(self, code):
1708 pass
1711 #-------------------------------------------------------------------
1713 # Trailer nodes
1715 #-------------------------------------------------------------------
1717 class IndexNode(ExprNode):
1718 # Sequence indexing.
1720 # base ExprNode
1721 # index ExprNode
1722 # indices [ExprNode]
1723 # is_buffer_access boolean Whether this is a buffer access.
1725 # indices is used on buffer access, index on non-buffer access.
1726 # The former contains a clean list of index parameters, the
1727 # latter whatever Python object is needed for index access.
1729 subexprs = ['base', 'index', 'indices']
1730 indices = None
1732 def __init__(self, pos, index, *args, **kw):
1733 ExprNode.__init__(self, pos, index=index, *args, **kw)
1734 self._index = index
1736 def calculate_constant_result(self):
1737 self.constant_result = \
1738 self.base.constant_result[self.index.constant_result]
1740 def compile_time_value(self, denv):
1741 base = self.base.compile_time_value(denv)
1742 index = self.index.compile_time_value(denv)
1743 try:
1744 return base[index]
1745 except Exception, e:
1746 self.compile_time_value_error(e)
1748 def is_ephemeral(self):
1749 return self.base.is_ephemeral()
1751 def analyse_target_declaration(self, env):
1752 pass
1754 def analyse_as_type(self, env):
1755 base_type = self.base.analyse_as_type(env)
1756 if base_type and not base_type.is_pyobject:
1757 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1758 return None
1760 def type_dependencies(self, env):
1761 return self.base.type_dependencies(env)
1763 def infer_type(self, env):
1764 if isinstance(self.base, (StringNode, UnicodeNode)): # FIXME: BytesNode?
1765 return py_object_type
1766 base_type = self.base.infer_type(env)
1767 if base_type.is_ptr or base_type.is_array:
1768 return base_type.base_type
1769 else:
1770 # TODO: Handle buffers (hopefully without too much redundancy).
1771 return py_object_type
1773 def analyse_types(self, env):
1774 self.analyse_base_and_index_types(env, getting = 1)
1776 def analyse_target_types(self, env):
1777 self.analyse_base_and_index_types(env, setting = 1)
1779 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1780 # Note: This might be cleaned up by having IndexNode
1781 # parsed in a saner way and only construct the tuple if
1782 # needed.
1784 # Note that this function must leave IndexNode in a cloneable state.
1785 # For buffers, self.index is packed out on the initial analysis, and
1786 # when cloning self.indices is copied.
1787 self.is_buffer_access = False
1789 self.base.analyse_types(env)
1790 if self.base.type.is_error:
1791 # Do not visit child tree if base is undeclared to avoid confusing
1792 # error messages
1793 self.type = PyrexTypes.error_type
1794 return
1796 # Handle the case where base is a literal char* (and we expect a string, not an int)
1797 if isinstance(self.base, BytesNode):
1798 self.base = self.base.coerce_to_pyobject(env)
1800 skip_child_analysis = False
1801 buffer_access = False
1802 if self.base.type.is_buffer:
1803 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1804 if self.indices:
1805 indices = self.indices
1806 else:
1807 if isinstance(self.index, TupleNode):
1808 indices = self.index.args
1809 else:
1810 indices = [self.index]
1811 if len(indices) == self.base.type.ndim:
1812 buffer_access = True
1813 skip_child_analysis = True
1814 for x in indices:
1815 x.analyse_types(env)
1816 if not x.type.is_int:
1817 buffer_access = False
1819 # On cloning, indices is cloned. Otherwise, unpack index into indices
1820 assert not (buffer_access and isinstance(self.index, CloneNode))
1822 if buffer_access:
1823 self.indices = indices
1824 self.index = None
1825 self.type = self.base.type.dtype
1826 self.is_buffer_access = True
1827 self.buffer_type = self.base.entry.type
1829 if getting and self.type.is_pyobject:
1830 self.is_temp = True
1831 if setting:
1832 if not self.base.entry.type.writable:
1833 error(self.pos, "Writing to readonly buffer")
1834 else:
1835 self.base.entry.buffer_aux.writable_needed = True
1836 else:
1837 if isinstance(self.index, TupleNode):
1838 self.index.analyse_types(env, skip_children=skip_child_analysis)
1839 elif not skip_child_analysis:
1840 self.index.analyse_types(env)
1841 self.original_index_type = self.index.type
1842 if self.base.type.is_pyobject:
1843 if self.index.type.is_int:
1844 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1845 else:
1846 self.index = self.index.coerce_to_pyobject(env)
1847 self.type = py_object_type
1848 self.is_temp = 1
1849 else:
1850 if self.base.type.is_ptr or self.base.type.is_array:
1851 self.type = self.base.type.base_type
1852 else:
1853 error(self.pos,
1854 "Attempting to index non-array type '%s'" %
1855 self.base.type)
1856 self.type = PyrexTypes.error_type
1857 if self.index.type.is_pyobject:
1858 self.index = self.index.coerce_to(
1859 PyrexTypes.c_py_ssize_t_type, env)
1860 if not self.index.type.is_int:
1861 error(self.pos,
1862 "Invalid index type '%s'" %
1863 self.index.type)
1864 gil_message = "Indexing Python object"
1866 def nogil_check(self, env):
1867 if self.is_buffer_access:
1868 if env.directives['boundscheck']:
1869 error(self.pos, "Cannot check buffer index bounds without gil; use boundscheck(False) directive")
1870 return
1871 elif self.type.is_pyobject:
1872 error(self.pos, "Cannot access buffer with object dtype without gil")
1873 return
1874 super(IndexNode, self).nogil_check(env)
1877 def check_const_addr(self):
1878 return self.base.check_const_addr() and self.index.check_const()
1880 def is_lvalue(self):
1881 return 1
1883 def calculate_result_code(self):
1884 if self.is_buffer_access:
1885 return "(*%s)" % self.buffer_ptr_code
1886 else:
1887 return "(%s[%s])" % (
1888 self.base.result(), self.index.result())
1890 def extra_index_params(self):
1891 if self.index.type.is_int:
1892 if self.original_index_type.signed:
1893 size_adjustment = ""
1894 else:
1895 size_adjustment = "+1"
1896 return ", sizeof(%s)%s, %s" % (self.original_index_type.declaration_code(""), size_adjustment, self.original_index_type.to_py_function)
1897 else:
1898 return ""
1900 def generate_subexpr_evaluation_code(self, code):
1901 self.base.generate_evaluation_code(code)
1902 if not self.indices:
1903 self.index.generate_evaluation_code(code)
1904 else:
1905 for i in self.indices:
1906 i.generate_evaluation_code(code)
1908 def generate_subexpr_disposal_code(self, code):
1909 self.base.generate_disposal_code(code)
1910 if not self.indices:
1911 self.index.generate_disposal_code(code)
1912 else:
1913 for i in self.indices:
1914 i.generate_disposal_code(code)
1916 def free_subexpr_temps(self, code):
1917 self.base.free_temps(code)
1918 if not self.indices:
1919 self.index.free_temps(code)
1920 else:
1921 for i in self.indices:
1922 i.free_temps(code)
1924 def generate_result_code(self, code):
1925 if self.is_buffer_access:
1926 if code.globalstate.directives['nonecheck']:
1927 self.put_nonecheck(code)
1928 self.buffer_ptr_code = self.buffer_lookup_code(code)
1929 if self.type.is_pyobject:
1930 # is_temp is True, so must pull out value and incref it.
1931 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1932 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
1933 elif self.type.is_pyobject:
1934 if self.index.type.is_int:
1935 index_code = self.index.result()
1936 if self.base.type is list_type:
1937 function = "__Pyx_GetItemInt_List"
1938 elif self.base.type is tuple_type:
1939 function = "__Pyx_GetItemInt_Tuple"
1940 else:
1941 function = "__Pyx_GetItemInt"
1942 code.globalstate.use_utility_code(getitem_int_utility_code)
1943 else:
1944 function = "PyObject_GetItem"
1945 index_code = self.index.py_result()
1946 sign_code = ""
1947 code.putln(
1948 "%s = %s(%s, %s%s); if (!%s) %s" % (
1949 self.result(),
1950 function,
1951 self.base.py_result(),
1952 index_code,
1953 self.extra_index_params(),
1954 self.result(),
1955 code.error_goto(self.pos)))
1956 code.put_gotref(self.py_result())
1958 def generate_setitem_code(self, value_code, code):
1959 if self.index.type.is_int:
1960 function = "__Pyx_SetItemInt"
1961 index_code = self.index.result()
1962 code.globalstate.use_utility_code(setitem_int_utility_code)
1963 else:
1964 index_code = self.index.py_result()
1965 if self.base.type is dict_type:
1966 function = "PyDict_SetItem"
1967 # It would seem that we could specalized lists/tuples, but that
1968 # shouldn't happen here.
1969 # Both PyList_SetItem PyTuple_SetItem and a Py_ssize_t as input,
1970 # not a PyObject*, and bad conversion here would give the wrong
1971 # exception. Also, tuples are supposed to be immutable, and raise
1972 # TypeErrors when trying to set their entries (PyTuple_SetItem
1973 # is for creating new tuples from).
1974 else:
1975 function = "PyObject_SetItem"
1976 code.putln(
1977 "if (%s(%s, %s, %s%s) < 0) %s" % (
1978 function,
1979 self.base.py_result(),
1980 index_code,
1981 value_code,
1982 self.extra_index_params(),
1983 code.error_goto(self.pos)))
1985 def generate_buffer_setitem_code(self, rhs, code, op=""):
1986 # Used from generate_assignment_code and InPlaceAssignmentNode
1987 if code.globalstate.directives['nonecheck']:
1988 self.put_nonecheck(code)
1989 ptrexpr = self.buffer_lookup_code(code)
1990 if self.buffer_type.dtype.is_pyobject:
1991 # Must manage refcounts. Decref what is already there
1992 # and incref what we put in.
1993 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
1994 rhs_code = rhs.result()
1995 code.putln("%s = %s;" % (ptr, ptrexpr))
1996 code.put_gotref("*%s" % ptr)
1997 code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
1998 ptr, rhs_code
1999 ))
2000 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
2001 code.put_giveref("*%s" % ptr)
2002 code.funcstate.release_temp(ptr)
2003 else:
2004 # Simple case
2005 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
2007 def generate_assignment_code(self, rhs, code):
2008 self.generate_subexpr_evaluation_code(code)
2009 if self.is_buffer_access:
2010 self.generate_buffer_setitem_code(rhs, code)
2011 elif self.type.is_pyobject:
2012 self.generate_setitem_code(rhs.py_result(), code)
2013 else:
2014 code.putln(
2015 "%s = %s;" % (
2016 self.result(), rhs.result()))
2017 self.generate_subexpr_disposal_code(code)
2018 self.free_subexpr_temps(code)
2019 rhs.generate_disposal_code(code)
2020 rhs.free_temps(code)
2022 def generate_deletion_code(self, code):
2023 self.generate_subexpr_evaluation_code(code)
2024 #if self.type.is_pyobject:
2025 if self.index.type.is_int:
2026 function = "__Pyx_DelItemInt"
2027 index_code = self.index.result()
2028 code.globalstate.use_utility_code(delitem_int_utility_code)
2029 else:
2030 index_code = self.index.py_result()
2031 if self.base.type is dict_type:
2032 function = "PyDict_DelItem"
2033 else:
2034 function = "PyObject_DelItem"
2035 code.putln(
2036 "if (%s(%s, %s%s) < 0) %s" % (
2037 function,
2038 self.base.py_result(),
2039 index_code,
2040 self.extra_index_params(),
2041 code.error_goto(self.pos)))
2042 self.generate_subexpr_disposal_code(code)
2043 self.free_subexpr_temps(code)
2045 def buffer_lookup_code(self, code):
2046 # Assign indices to temps
2047 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
2048 for temp, index in zip(index_temps, self.indices):
2049 code.putln("%s = %s;" % (temp, index.result()))
2050 # Generate buffer access code using these temps
2051 import Buffer
2052 # The above could happen because child_attrs is wrong somewhere so that
2053 # options are not propagated.
2054 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
2055 index_signeds=[i.type.signed for i in self.indices],
2056 index_cnames=index_temps,
2057 directives=code.globalstate.directives,
2058 pos=self.pos, code=code)
2060 def put_nonecheck(self, code):
2061 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
2062 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
2063 code.putln("__Pyx_RaiseNoneIndexingError();")
2064 code.putln(code.error_goto(self.pos))
2065 code.putln("}")
2067 class SliceIndexNode(ExprNode):
2068 # 2-element slice indexing
2070 # base ExprNode
2071 # start ExprNode or None
2072 # stop ExprNode or None
2074 subexprs = ['base', 'start', 'stop']
2076 def infer_type(self, env):
2077 base_type = self.base.infer_type(env)
2078 if base_type.is_string:
2079 return bytes_type
2080 elif base_type in (bytes_type, str_type, unicode_type,
2081 list_type, tuple_type):
2082 return base_type
2083 return py_object_type
2085 def calculate_constant_result(self):
2086 self.constant_result = self.base.constant_result[
2087 self.start.constant_result : self.stop.constant_result]
2089 def compile_time_value(self, denv):
2090 base = self.base.compile_time_value(denv)
2091 if self.start is None:
2092 start = 0
2093 else:
2094 start = self.start.compile_time_value(denv)
2095 if self.stop is None:
2096 stop = None
2097 else:
2098 stop = self.stop.compile_time_value(denv)
2099 try:
2100 return base[start:stop]
2101 except Exception, e:
2102 self.compile_time_value_error(e)
2104 def analyse_target_declaration(self, env):
2105 pass
2107 def analyse_target_types(self, env):
2108 self.analyse_types(env)
2109 # when assigning, we must accept any Python type
2110 if self.type.is_pyobject:
2111 self.type = py_object_type
2113 def analyse_types(self, env):
2114 self.base.analyse_types(env)
2115 if self.start:
2116 self.start.analyse_types(env)
2117 if self.stop:
2118 self.stop.analyse_types(env)
2119 base_type = self.base.type
2120 if base_type.is_string:
2121 self.type = bytes_type
2122 elif base_type.is_array or base_type.is_ptr:
2123 # we need a ptr type here instead of an array type, as
2124 # array types can result in invalid type casts in the C
2125 # code
2126 self.type = PyrexTypes.CPtrType(base_type.base_type)
2127 else:
2128 self.base = self.base.coerce_to_pyobject(env)
2129 self.type = py_object_type
2130 if base_type.is_builtin_type:
2131 # slicing builtin types returns something of the same type
2132 self.type = base_type
2133 c_int = PyrexTypes.c_py_ssize_t_type
2134 if self.start:
2135 self.start = self.start.coerce_to(c_int, env)
2136 if self.stop:
2137 self.stop = self.stop.coerce_to(c_int, env)
2138 self.is_temp = 1
2140 nogil_check = Node.gil_error
2141 gil_message = "Slicing Python object"
2143 def generate_result_code(self, code):
2144 if not self.type.is_pyobject:
2145 error(self.pos,
2146 "Slicing is not currently supported for '%s'." % self.type)
2147 return
2148 if self.base.type.is_string:
2149 if self.stop is None:
2150 code.putln(
2151 "%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
2152 self.result(),
2153 self.base.result(),
2154 self.start_code(),
2155 code.error_goto_if_null(self.result(), self.pos)))
2156 else:
2157 code.putln(
2158 "%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
2159 self.result(),
2160 self.base.result(),
2161 self.start_code(),
2162 self.stop_code(),
2163 self.start_code(),
2164 code.error_goto_if_null(self.result(), self.pos)))
2165 else:
2166 code.putln(
2167 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
2168 self.result(),
2169 self.base.py_result(),
2170 self.start_code(),
2171 self.stop_code(),
2172 code.error_goto_if_null(self.result(), self.pos)))
2173 code.put_gotref(self.py_result())
2175 def generate_assignment_code(self, rhs, code):
2176 self.generate_subexpr_evaluation_code(code)
2177 if self.type.is_pyobject:
2178 code.put_error_if_neg(self.pos,
2179 "PySequence_SetSlice(%s, %s, %s, %s)" % (
2180 self.base.py_result(),
2181 self.start_code(),
2182 self.stop_code(),
2183 rhs.result()))
2184 else:
2185 start_offset = ''
2186 if self.start:
2187 start_offset = self.start_code()
2188 if start_offset == '0':
2189 start_offset = ''
2190 else:
2191 start_offset += '+'
2192 if rhs.type.is_array:
2193 array_length = rhs.type.size
2194 self.generate_slice_guard_code(code, array_length)
2195 else:
2196 error(self.pos,
2197 "Slice assignments from pointers are not yet supported.")
2198 # FIXME: fix the array size according to start/stop
2199 array_length = self.base.type.size
2200 for i in range(array_length):
2201 code.putln("%s[%s%s] = %s[%d];" % (
2202 self.base.result(), start_offset, i,
2203 rhs.result(), i))
2204 self.generate_subexpr_disposal_code(code)
2205 self.free_subexpr_temps(code)
2206 rhs.generate_disposal_code(code)
2207 rhs.free_temps(code)
2209 def generate_deletion_code(self, code):
2210 if not self.base.type.is_pyobject:
2211 error(self.pos,
2212 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2213 return
2214 self.generate_subexpr_evaluation_code(code)
2215 code.put_error_if_neg(self.pos,
2216 "PySequence_DelSlice(%s, %s, %s)" % (
2217 self.base.py_result(),
2218 self.start_code(),
2219 self.stop_code()))
2220 self.generate_subexpr_disposal_code(code)
2222 def generate_slice_guard_code(self, code, target_size):
2223 if not self.base.type.is_array:
2224 return
2225 slice_size = self.base.type.size
2226 start = stop = None
2227 if self.stop:
2228 stop = self.stop.result()
2229 try:
2230 stop = int(stop)
2231 if stop < 0:
2232 slice_size = self.base.type.size + stop
2233 else:
2234 slice_size = stop
2235 stop = None
2236 except ValueError:
2237 pass
2238 if self.start:
2239 start = self.start.result()
2240 try:
2241 start = int(start)
2242 if start < 0:
2243 start = self.base.type.size + start
2244 slice_size -= start
2245 start = None
2246 except ValueError:
2247 pass
2248 check = None
2249 if slice_size < 0:
2250 if target_size > 0:
2251 error(self.pos, "Assignment to empty slice.")
2252 elif start is None and stop is None:
2253 # we know the exact slice length
2254 if target_size != slice_size:
2255 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2256 slice_size, target_size))
2257 elif start is not None:
2258 if stop is None:
2259 stop = slice_size
2260 check = "(%s)-(%s)" % (stop, start)
2261 else: # stop is not None:
2262 check = stop
2263 if check:
2264 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2265 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));' % (
2266 target_size, check))
2267 code.putln(code.error_goto(self.pos))
2268 code.putln("}")
2270 def start_code(self):
2271 if self.start:
2272 return self.start.result()
2273 else:
2274 return "0"
2276 def stop_code(self):
2277 if self.stop:
2278 return self.stop.result()
2279 elif self.base.type.is_array:
2280 return self.base.type.size
2281 else:
2282 return "PY_SSIZE_T_MAX"
2284 def calculate_result_code(self):
2285 # self.result() is not used, but this method must exist
2286 return "<unused>"
2289 class SliceNode(ExprNode):
2290 # start:stop:step in subscript list
2292 # start ExprNode
2293 # stop ExprNode
2294 # step ExprNode
2296 type = py_object_type
2297 is_temp = 1
2299 def calculate_constant_result(self):
2300 self.constant_result = self.base.constant_result[
2301 self.start.constant_result : \
2302 self.stop.constant_result : \
2303 self.step.constant_result]
2305 def compile_time_value(self, denv):
2306 start = self.start.compile_time_value(denv)
2307 if self.stop is None:
2308 stop = None
2309 else:
2310 stop = self.stop.compile_time_value(denv)
2311 if self.step is None:
2312 step = None
2313 else:
2314 step = self.step.compile_time_value(denv)
2315 try:
2316 return slice(start, stop, step)
2317 except Exception, e:
2318 self.compile_time_value_error(e)
2320 subexprs = ['start', 'stop', 'step']
2322 def analyse_types(self, env):
2323 self.start.analyse_types(env)
2324 self.stop.analyse_types(env)
2325 self.step.analyse_types(env)
2326 self.start = self.start.coerce_to_pyobject(env)
2327 self.stop = self.stop.coerce_to_pyobject(env)
2328 self.step = self.step.coerce_to_pyobject(env)
2330 gil_message = "Constructing Python slice object"
2332 def generate_result_code(self, code):
2333 code.putln(
2334 "%s = PySlice_New(%s, %s, %s); %s" % (
2335 self.result(),
2336 self.start.py_result(),
2337 self.stop.py_result(),
2338 self.step.py_result(),
2339 code.error_goto_if_null(self.result(), self.pos)))
2340 code.put_gotref(self.py_result())
2343 class CallNode(ExprNode):
2345 def analyse_as_type_constructor(self, env):
2346 type = self.function.analyse_as_type(env)
2347 if type and type.is_struct_or_union:
2348 args, kwds = self.explicit_args_kwds()
2349 items = []
2350 for arg, member in zip(args, type.scope.var_entries):
2351 items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg))
2352 if kwds:
2353 items += kwds.key_value_pairs
2354 self.key_value_pairs = items
2355 self.__class__ = DictNode
2356 self.analyse_types(env)
2357 self.coerce_to(type, env)
2358 return True
2360 def nogil_check(self, env):
2361 func_type = self.function_type()
2362 if func_type.is_pyobject:
2363 self.gil_error()
2364 elif not getattr(func_type, 'nogil', False):
2365 self.gil_error()
2367 gil_message = "Calling gil-requiring function"
2370 class SimpleCallNode(CallNode):
2371 # Function call without keyword, * or ** args.
2373 # function ExprNode
2374 # args [ExprNode]
2375 # arg_tuple ExprNode or None used internally
2376 # self ExprNode or None used internally
2377 # coerced_self ExprNode or None used internally
2378 # wrapper_call bool used internally
2379 # has_optional_args bool used internally
2381 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2383 self = None
2384 coerced_self = None
2385 arg_tuple = None
2386 wrapper_call = False
2387 has_optional_args = False
2389 def compile_time_value(self, denv):
2390 function = self.function.compile_time_value(denv)
2391 args = [arg.compile_time_value(denv) for arg in self.args]
2392 try:
2393 return function(*args)
2394 except Exception, e:
2395 self.compile_time_value_error(e)
2397 def type_dependencies(self, env):
2398 # TODO: Update when Danilo's C++ code merged in to handle the
2399 # the case of function overloading.
2400 return self.function.type_dependencies(env)
2402 def infer_type(self, env):
2403 function = self.function
2404 func_type = function.infer_type(env)
2405 if func_type.is_ptr:
2406 func_type = func_type.base_type
2407 if func_type.is_cfunction:
2408 return func_type.return_type
2409 elif func_type is type_type:
2410 if function.is_name and function.entry and function.entry.type:
2411 result_type = function.entry.type
2412 if result_type.is_extension_type:
2413 return result_type
2414 elif result_type.is_builtin_type:
2415 if function.entry.name in Builtin.types_that_construct_their_instance:
2416 return result_type
2417 return py_object_type
2419 def analyse_as_type(self, env):
2420 attr = self.function.as_cython_attribute()
2421 if attr == 'pointer':
2422 if len(self.args) != 1:
2423 error(self.args.pos, "only one type allowed.")
2424 else:
2425 type = self.args[0].analyse_as_type(env)
2426 if not type:
2427 error(self.args[0].pos, "Unknown type")
2428 else:
2429 return PyrexTypes.CPtrType(type)
2431 def explicit_args_kwds(self):
2432 return self.args, None
2434 def analyse_types(self, env):
2435 if self.analyse_as_type_constructor(env):
2436 return
2437 function = self.function
2438 function.is_called = 1
2439 self.function.analyse_types(env)
2440 if function.is_attribute and function.entry and function.entry.is_cmethod:
2441 # Take ownership of the object from which the attribute
2442 # was obtained, because we need to pass it as 'self'.
2443 self.self = function.obj
2444 function.obj = CloneNode(self.self)
2445 func_type = self.function_type()
2446 if func_type.is_pyobject:
2447 self.arg_tuple = TupleNode(self.pos, args = self.args)
2448 self.arg_tuple.analyse_types(env)
2449 self.args = None
2450 if function.is_name and function.type_entry:
2451 # We are calling an extension type constructor. As
2452 # long as we do not support __new__(), the result type
2453 # is clear
2454 self.type = function.type_entry.type
2455 self.result_ctype = py_object_type
2456 else:
2457 self.type = py_object_type
2458 self.is_temp = 1
2459 else:
2460 for arg in self.args:
2461 arg.analyse_types(env)
2462 if self.self and func_type.args:
2463 # Coerce 'self' to the type expected by the method.
2464 expected_type = func_type.args[0].type
2465 self.coerced_self = CloneNode(self.self).coerce_to(
2466 expected_type, env)
2467 # Insert coerced 'self' argument into argument list.
2468 self.args.insert(0, self.coerced_self)
2469 self.analyse_c_function_call(env)
2471 def function_type(self):
2472 # Return the type of the function being called, coercing a function
2473 # pointer to a function if necessary.
2474 func_type = self.function.type
2475 if func_type.is_ptr:
2476 func_type = func_type.base_type
2477 return func_type
2479 def analyse_c_function_call(self, env):
2480 func_type = self.function_type()
2481 # Check function type
2482 if not func_type.is_cfunction:
2483 if not func_type.is_error:
2484 error(self.pos, "Calling non-function type '%s'" %
2485 func_type)
2486 self.type = PyrexTypes.error_type
2487 self.result_code = "<error>"
2488 return
2489 # Check no. of args
2490 max_nargs = len(func_type.args)
2491 expected_nargs = max_nargs - func_type.optional_arg_count
2492 actual_nargs = len(self.args)
2493 if actual_nargs < expected_nargs \
2494 or (not func_type.has_varargs and actual_nargs > max_nargs):
2495 expected_str = str(expected_nargs)
2496 if func_type.has_varargs:
2497 expected_str = "at least " + expected_str
2498 elif func_type.optional_arg_count:
2499 if actual_nargs < max_nargs:
2500 expected_str = "at least " + expected_str
2501 else:
2502 expected_str = "at most " + str(max_nargs)
2503 error(self.pos,
2504 "Call with wrong number of arguments (expected %s, got %s)"
2505 % (expected_str, actual_nargs))
2506 self.args = None
2507 self.type = PyrexTypes.error_type
2508 self.result_code = "<error>"
2509 return
2510 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2511 self.has_optional_args = 1
2512 self.is_temp = 1
2513 # Coerce arguments
2514 for i in range(min(max_nargs, actual_nargs)):
2515 formal_type = func_type.args[i].type
2516 self.args[i] = self.args[i].coerce_to(formal_type, env)
2517 for i in range(max_nargs, actual_nargs):
2518 if self.args[i].type.is_pyobject:
2519 error(self.args[i].pos,
2520 "Python object cannot be passed as a varargs parameter")
2521 # Calc result type and code fragment
2522 self.type = func_type.return_type
2523 if self.type.is_pyobject:
2524 self.result_ctype = py_object_type
2525 self.is_temp = 1
2526 elif func_type.exception_value is not None \
2527 or func_type.exception_check:
2528 self.is_temp = 1
2529 # C++ exception handler
2530 if func_type.exception_check == '+':
2531 if func_type.exception_value is None:
2532 env.use_utility_code(cpp_exception_utility_code)
2534 def calculate_result_code(self):
2535 return self.c_call_code()
2537 def c_call_code(self):
2538 func_type = self.function_type()
2539 if self.args is None or not func_type.is_cfunction:
2540 return "<error>"
2541 formal_args = func_type.args
2542 arg_list_code = []
2543 args = zip(formal_args, self.args)
2544 max_nargs = len(func_type.args)
2545 expected_nargs = max_nargs - func_type.optional_arg_count
2546 actual_nargs = len(self.args)
2547 for formal_arg, actual_arg in args[:expected_nargs]:
2548 arg_code = actual_arg.result_as(formal_arg.type)
2549 arg_list_code.append(arg_code)
2551 if func_type.is_overridable:
2552 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2554 if func_type.optional_arg_count:
2555 if expected_nargs == actual_nargs:
2556 optional_args = 'NULL'
2557 else:
2558 optional_args = "&%s" % self.opt_arg_struct
2559 arg_list_code.append(optional_args)
2561 for actual_arg in self.args[len(formal_args):]:
2562 arg_list_code.append(actual_arg.result())
2563 result = "%s(%s)" % (self.function.result(),
2564 ', '.join(arg_list_code))
2565 return result
2567 def generate_result_code(self, code):
2568 func_type = self.function_type()
2569 if func_type.is_pyobject:
2570 arg_code = self.arg_tuple.py_result()
2571 code.putln(
2572 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2573 self.result(),
2574 self.function.py_result(),
2575 arg_code,
2576 code.error_goto_if_null(self.result(), self.pos)))
2577 code.put_gotref(self.py_result())
2578 elif func_type.is_cfunction:
2579 if self.has_optional_args:
2580 actual_nargs = len(self.args)
2581 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2582 self.opt_arg_struct = code.funcstate.allocate_temp(
2583 func_type.op_arg_struct.base_type, manage_ref=True)
2584 code.putln("%s.%s = %s;" % (
2585 self.opt_arg_struct,
2586 Naming.pyrex_prefix + "n",
2587 len(self.args) - expected_nargs))
2588 args = zip(func_type.args, self.args)
2589 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2590 code.putln("%s.%s = %s;" % (
2591 self.opt_arg_struct,
2592 func_type.opt_arg_cname(formal_arg.name),
2593 actual_arg.result_as(formal_arg.type)))
2594 exc_checks = []
2595 if self.type.is_pyobject:
2596 exc_checks.append("!%s" % self.result())
2597 else:
2598 exc_val = func_type.exception_value
2599 exc_check = func_type.exception_check
2600 if exc_val is not None:
2601 exc_checks.append("%s == %s" % (self.result(), exc_val))
2602 if exc_check:
2603 exc_checks.append("PyErr_Occurred()")
2604 if self.is_temp or exc_checks:
2605 rhs = self.c_call_code()
2606 if self.result():
2607 lhs = "%s = " % self.result()
2608 if self.is_temp and self.type.is_pyobject:
2609 #return_type = self.type # func_type.return_type
2610 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2611 # "from", return_type, "to pyobject" ###
2612 rhs = typecast(py_object_type, self.type, rhs)
2613 else:
2614 lhs = ""
2615 if func_type.exception_check == '+':
2616 if func_type.exception_value is None:
2617 raise_py_exception = "__Pyx_CppExn2PyErr()"
2618 elif func_type.exception_value.type.is_pyobject:
2619 raise_py_exception = ' try { throw; } catch(const std::exception& exn) { PyErr_SetString(%s, exn.what()); } catch(...) { PyErr_SetNone(%s); }' % (
2620 func_type.exception_value.entry.cname,
2621 func_type.exception_value.entry.cname)
2622 else:
2623 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2624 code.putln(
2625 "try {%s%s;} catch(...) {%s; %s}" % (
2626 lhs,
2627 rhs,
2628 raise_py_exception,
2629 code.error_goto(self.pos)))
2630 else:
2631 if exc_checks:
2632 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2633 else:
2634 goto_error = ""
2635 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2636 if self.type.is_pyobject and self.result():
2637 code.put_gotref(self.py_result())
2638 if self.has_optional_args:
2639 code.funcstate.release_temp(self.opt_arg_struct)
2642 class PythonCapiFunctionNode(ExprNode):
2643 subexprs = []
2644 def __init__(self, pos, name, func_type, utility_code = None):
2645 self.pos = pos
2646 self.name = name
2647 self.type = func_type
2648 self.utility_code = utility_code
2650 def generate_result_code(self, code):
2651 if self.utility_code:
2652 code.globalstate.use_utility_code(self.utility_code)
2654 def calculate_result_code(self):
2655 return self.name
2657 class PythonCapiCallNode(SimpleCallNode):
2658 # Python C-API Function call (only created in transforms)
2660 def __init__(self, pos, function_name, func_type,
2661 utility_code = None, **kwargs):
2662 self.type = func_type.return_type
2663 self.result_ctype = self.type
2664 self.function = PythonCapiFunctionNode(
2665 pos, function_name, func_type,
2666 utility_code = utility_code)
2667 # call this last so that we can override the constructed
2668 # attributes above with explicit keyword arguments if required
2669 SimpleCallNode.__init__(self, pos, **kwargs)
2672 class GeneralCallNode(CallNode):
2673 # General Python function call, including keyword,
2674 # * and ** arguments.
2676 # function ExprNode
2677 # positional_args ExprNode Tuple of positional arguments
2678 # keyword_args ExprNode or None Dict of keyword arguments
2679 # starstar_arg ExprNode or None Dict of extra keyword args
2681 type = py_object_type
2683 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2685 nogil_check = Node.gil_error
2687 def compile_time_value(self, denv):
2688 function = self.function.compile_time_value(denv)
2689 positional_args = self.positional_args.compile_time_value(denv)
2690 keyword_args = self.keyword_args.compile_time_value(denv)
2691 starstar_arg = self.starstar_arg.compile_time_value(denv)
2692 try:
2693 keyword_args.update(starstar_arg)
2694 return function(*positional_args, **keyword_args)
2695 except Exception, e:
2696 self.compile_time_value_error(e)
2698 def explicit_args_kwds(self):
2699 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2700 raise PostParseError(self.pos,
2701 'Compile-time keyword arguments must be explicit.')
2702 return self.positional_args.args, self.keyword_args
2704 def analyse_types(self, env):
2705 if self.analyse_as_type_constructor(env):
2706 return
2707 self.function.analyse_types(env)
2708 self.positional_args.analyse_types(env)
2709 if self.keyword_args:
2710 self.keyword_args.analyse_types(env)
2711 if self.starstar_arg:
2712 self.starstar_arg.analyse_types(env)
2713 if not self.function.type.is_pyobject:
2714 if self.function.type.is_error:
2715 self.type = error_type
2716 return
2717 if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
2718 error(self.pos, "Keyword and starred arguments not allowed in cdef functions.")
2719 else:
2720 self.function = self.function.coerce_to_pyobject(env)
2721 self.positional_args = \
2722 self.positional_args.coerce_to_pyobject(env)
2723 if self.starstar_arg:
2724 self.starstar_arg = \
2725 self.starstar_arg.coerce_to_pyobject(env)
2726 function = self.function
2727 if function.is_name and function.type_entry:
2728 # We are calling an extension type constructor. As long
2729 # as we do not support __new__(), the result type is clear
2730 self.type = function.type_entry.type
2731 self.result_ctype = py_object_type
2732 else:
2733 self.type = py_object_type
2734 self.is_temp = 1
2736 def generate_result_code(self, code):
2737 if self.type.is_error: return
2738 if self.keyword_args and self.starstar_arg:
2739 code.put_error_if_neg(self.pos,
2740 "PyDict_Update(%s, %s)" % (
2741 self.keyword_args.py_result(),
2742 self.starstar_arg.py_result()))
2743 keyword_code = self.keyword_args.py_result()
2744 elif self.keyword_args:
2745 keyword_code = self.keyword_args.py_result()
2746 elif self.starstar_arg:
2747 keyword_code = self.starstar_arg.py_result()
2748 else:
2749 keyword_code = None
2750 if not keyword_code:
2751 call_code = "PyObject_Call(%s, %s, NULL)" % (
2752 self.function.py_result(),
2753 self.positional_args.py_result())
2754 else:
2755 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2756 self.function.py_result(),
2757 self.positional_args.py_result(),
2758 keyword_code)
2759 code.putln(
2760 "%s = %s; %s" % (
2761 self.result(),
2762 call_code,
2763 code.error_goto_if_null(self.result(), self.pos)))
2764 code.put_gotref(self.py_result())
2767 class AsTupleNode(ExprNode):
2768 # Convert argument to tuple. Used for normalising
2769 # the * argument of a function call.
2771 # arg ExprNode
2773 subexprs = ['arg']
2775 def calculate_constant_result(self):
2776 self.constant_result = tuple(self.base.constant_result)
2778 def compile_time_value(self, denv):
2779 arg = self.arg.compile_time_value(denv)
2780 try:
2781 return tuple(arg)
2782 except Exception, e:
2783 self.compile_time_value_error(e)
2785 def analyse_types(self, env):
2786 self.arg.analyse_types(env)
2787 self.arg = self.arg.coerce_to_pyobject(env)
2788 self.type = tuple_type
2789 self.is_temp = 1
2791 nogil_check = Node.gil_error
2792 gil_message = "Constructing Python tuple"
2794 def generate_result_code(self, code):
2795 code.putln(
2796 "%s = PySequence_Tuple(%s); %s" % (
2797 self.result(),
2798 self.arg.py_result(),
2799 code.error_goto_if_null(self.result(), self.pos)))
2800 code.put_gotref(self.py_result())
2803 class AttributeNode(ExprNode):
2804 # obj.attribute
2806 # obj ExprNode
2807 # attribute string
2808 # needs_none_check boolean Used if obj is an extension type.
2809 # If set to True, it is known that the type is not None.
2811 # Used internally:
2813 # is_py_attr boolean Is a Python getattr operation
2814 # member string C name of struct member
2815 # is_called boolean Function call is being done on result
2816 # entry Entry Symbol table entry of attribute
2818 is_attribute = 1
2819 subexprs = ['obj']
2821 type = PyrexTypes.error_type
2822 entry = None
2823 is_called = 0
2824 needs_none_check = True
2826 def as_cython_attribute(self):
2827 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2828 return self.attribute
2830 def coerce_to(self, dst_type, env):
2831 # If coercing to a generic pyobject and this is a cpdef function
2832 # we can create the corresponding attribute
2833 if dst_type is py_object_type:
2834 entry = self.entry
2835 if entry and entry.is_cfunction and entry.as_variable:
2836 # must be a cpdef function
2837 self.is_temp = 1
2838 self.entry = entry.as_variable
2839 self.analyse_as_python_attribute(env)
2840 return self
2841 return ExprNode.coerce_to(self, dst_type, env)
2843 def calculate_constant_result(self):
2844 attr = self.attribute
2845 if attr.startswith("__") and attr.endswith("__"):
2846 return
2847 self.constant_result = getattr(self.obj.constant_result, attr)
2849 def compile_time_value(self, denv):
2850 attr = self.attribute
2851 if attr.startswith("__") and attr.endswith("__"):
2852 error(self.pos,
2853 "Invalid attribute name '%s' in compile-time expression" % attr)
2854 return None
2855 obj = self.obj.compile_time_value(denv)
2856 try:
2857 return getattr(obj, attr)
2858 except Exception, e:
2859 self.compile_time_value_error(e)
2861 def type_dependencies(self, env):
2862 return self.obj.type_dependencies(env)
2864 def infer_type(self, env):
2865 if self.analyse_as_cimported_attribute(env, 0):
2866 return self.entry.type
2867 elif self.analyse_as_unbound_cmethod(env):
2868 return self.entry.type
2869 else:
2870 self.analyse_attribute(env, obj_type = self.obj.infer_type(env))
2871 return self.type
2873 def analyse_target_declaration(self, env):
2874 pass
2876 def analyse_target_types(self, env):
2877 self.analyse_types(env, target = 1)
2879 def analyse_types(self, env, target = 0):
2880 if self.analyse_as_cimported_attribute(env, target):
2881 return
2882 if not target and self.analyse_as_unbound_cmethod(env):
2883 return
2884 self.analyse_as_ordinary_attribute(env, target)
2886 def analyse_as_cimported_attribute(self, env, target):
2887 # Try to interpret this as a reference to an imported
2888 # C const, type, var or function. If successful, mutates
2889 # this node into a NameNode and returns 1, otherwise
2890 # returns 0.
2891 module_scope = self.obj.analyse_as_module(env)
2892 if module_scope:
2893 entry = module_scope.lookup_here(self.attribute)
2894 if entry and (
2895 entry.is_cglobal or entry.is_cfunction
2896 or entry.is_type or entry.is_const):
2897 self.mutate_into_name_node(env, entry, target)
2898 return 1
2899 return 0
2901 def analyse_as_unbound_cmethod(self, env):
2902 # Try to interpret this as a reference to an unbound
2903 # C method of an extension type. If successful, mutates
2904 # this node into a NameNode and returns 1, otherwise
2905 # returns 0.
2906 type = self.obj.analyse_as_extension_type(env)
2907 if type:
2908 entry = type.scope.lookup_here(self.attribute)
2909 if entry and entry.is_cmethod:
2910 # Create a temporary entry describing the C method
2911 # as an ordinary function.
2912 ubcm_entry = Symtab.Entry(entry.name,
2913 "%s->%s" % (type.vtabptr_cname, entry.cname),
2914 entry.type)
2915 ubcm_entry.is_cfunction = 1
2916 ubcm_entry.func_cname = entry.func_cname
2917 ubcm_entry.is_unbound_cmethod = 1
2918 self.mutate_into_name_node(env, ubcm_entry, None)
2919 return 1
2920 return 0
2922 def analyse_as_type(self, env):
2923 module_scope = self.obj.analyse_as_module(env)
2924 if module_scope:
2925 return module_scope.lookup_type(self.attribute)
2926 return None
2928 def analyse_as_extension_type(self, env):
2929 # Try to interpret this as a reference to an extension type
2930 # in a cimported module. Returns the extension type, or None.
2931 module_scope = self.obj.analyse_as_module(env)
2932 if module_scope:
2933 entry = module_scope.lookup_here(self.attribute)
2934 if entry and entry.is_type and entry.type.is_extension_type:
2935 return entry.type
2936 return None
2938 def analyse_as_module(self, env):
2939 # Try to interpret this as a reference to a cimported module
2940 # in another cimported module. Returns the module scope, or None.
2941 module_scope = self.obj.analyse_as_module(env)
2942 if module_scope:
2943 entry = module_scope.lookup_here(self.attribute)
2944 if entry and entry.as_module:
2945 return entry.as_module
2946 return None
2948 def mutate_into_name_node(self, env, entry, target):
2949 # Mutate this node into a NameNode and complete the
2950 # analyse_types phase.
2951 self.__class__ = NameNode
2952 self.name = self.attribute
2953 self.entry = entry
2954 del self.obj
2955 del self.attribute
2956 if target:
2957 NameNode.analyse_target_types(self, env)
2958 else:
2959 NameNode.analyse_rvalue_entry(self, env)
2961 def analyse_as_ordinary_attribute(self, env, target):
2962 self.obj.analyse_types(env)
2963 self.analyse_attribute(env)
2964 if self.entry and self.entry.is_cmethod and not self.is_called:
2965 # error(self.pos, "C method can only be called")
2966 pass
2967 ## Reference to C array turns into pointer to first element.
2968 #while self.type.is_array:
2969 # self.type = self.type.element_ptr_type()
2970 if self.is_py_attr:
2971 if not target:
2972 self.is_temp = 1
2973 self.result_ctype = py_object_type
2975 def analyse_attribute(self, env, obj_type = None):
2976 # Look up attribute and set self.type and self.member.
2977 self.is_py_attr = 0
2978 self.member = self.attribute
2979 if obj_type is None:
2980 if self.obj.type.is_string:
2981 self.obj = self.obj.coerce_to_pyobject(env)
2982 obj_type = self.obj.type
2983 else:
2984 if obj_type.is_string:
2985 obj_type = py_object_type
2986 if obj_type.is_ptr or obj_type.is_array:
2987 obj_type = obj_type.base_type
2988 self.op = "->"
2989 elif obj_type.is_extension_type:
2990 self.op = "->"
2991 else:
2992 self.op = "."
2993 if obj_type.has_attributes:
2994 entry = None
2995 if obj_type.attributes_known():
2996 entry = obj_type.scope.lookup_here(self.attribute)
2997 if entry and entry.is_member:
2998 entry = None
2999 else:
3000 error(self.pos,
3001 "Cannot select attribute of incomplete type '%s'"
3002 % obj_type)
3003 self.type = PyrexTypes.error_type
3004 return
3005 self.entry = entry
3006 if entry:
3007 if obj_type.is_extension_type and entry.name == "__weakref__":
3008 error(self.pos, "Illegal use of special attribute __weakref__")
3009 # methods need the normal attribute lookup
3010 # because they do not have struct entries
3011 if entry.is_variable or entry.is_cmethod:
3012 self.type = entry.type
3013 self.member = entry.cname
3014 return
3015 else:
3016 # If it's not a variable or C method, it must be a Python
3017 # method of an extension type, so we treat it like a Python
3018 # attribute.
3019 pass
3020 # If we get here, the base object is not a struct/union/extension
3021 # type, or it is an extension type and the attribute is either not
3022 # declared or is declared as a Python method. Treat it as a Python
3023 # attribute reference.
3024 self.analyse_as_python_attribute(env, obj_type)
3026 def analyse_as_python_attribute(self, env, obj_type = None):
3027 if obj_type is None:
3028 obj_type = self.obj.type
3029 self.member = self.attribute
3030 self.type = py_object_type
3031 self.is_py_attr = 1
3032 if not obj_type.is_pyobject and not obj_type.is_error:
3033 if obj_type.can_coerce_to_pyobject(env):
3034 self.obj = self.obj.coerce_to_pyobject(env)
3035 else:
3036 error(self.pos,
3037 "Object of type '%s' has no attribute '%s'" %
3038 (obj_type, self.attribute))
3040 def nogil_check(self, env):
3041 if self.is_py_attr:
3042 self.gil_error()
3044 gil_message = "Accessing Python attribute"
3046 def is_simple(self):
3047 if self.obj:
3048 return self.result_in_temp() or self.obj.is_simple()
3049 else:
3050 return NameNode.is_simple(self)
3052 def is_lvalue(self):
3053 if self.obj:
3054 return 1
3055 else:
3056 return NameNode.is_lvalue(self)
3058 def is_ephemeral(self):
3059 if self.obj:
3060 return self.obj.is_ephemeral()
3061 else:
3062 return NameNode.is_ephemeral(self)
3064 def calculate_result_code(self):
3065 #print "AttributeNode.calculate_result_code:", self.member ###
3066 #print "...obj node =", self.obj, "code", self.obj.result() ###
3067 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
3068 obj = self.obj
3069 obj_code = obj.result_as(obj.type)
3070 #print "...obj_code =", obj_code ###
3071 if self.entry and self.entry.is_cmethod:
3072 if obj.type.is_extension_type:
3073 return "((struct %s *)%s%s%s)->%s" % (
3074 obj.type.vtabstruct_cname, obj_code, self.op,
3075 obj.type.vtabslot_cname, self.member)
3076 else:
3077 return self.member
3078 elif obj.type.is_complex:
3079 return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code)
3080 else:
3081 return "%s%s%s" % (obj_code, self.op, self.member)
3083 def generate_result_code(self, code):
3084 interned_attr_cname = code.intern_identifier(self.attribute)
3085 if self.is_py_attr:
3086 code.putln(
3087 '%s = PyObject_GetAttr(%s, %s); %s' % (
3088 self.result(),
3089 self.obj.py_result(),
3090 interned_attr_cname,
3091 code.error_goto_if_null(self.result(), self.pos)))
3092 code.put_gotref(self.py_result())
3093 else:
3094 # result_code contains what is needed, but we may need to insert
3095 # a check and raise an exception
3096 if (self.obj.type.is_extension_type
3097 and self.needs_none_check
3098 and code.globalstate.directives['nonecheck']):
3099 self.put_nonecheck(code)
3101 def generate_assignment_code(self, rhs, code):
3102 interned_attr_cname = code.intern_identifier(self.attribute)
3103 self.obj.generate_evaluation_code(code)
3104 if self.is_py_attr:
3105 code.put_error_if_neg(self.pos,
3106 'PyObject_SetAttr(%s, %s, %s)' % (
3107 self.obj.py_result(),
3108 interned_attr_cname,
3109 rhs.py_result()))
3110 rhs.generate_disposal_code(code)
3111 rhs.free_temps(code)
3112 elif self.obj.type.is_complex:
3113 code.putln("__Pyx_SET_C%s(%s, %s);" % (
3114 self.member.upper(),
3115 self.obj.result_as(self.obj.type),
3116 rhs.result_as(self.ctype())))
3117 else:
3118 if (self.obj.type.is_extension_type
3119 and self.needs_none_check
3120 and code.globalstate.directives['nonecheck']):
3121 self.put_nonecheck(code)
3123 select_code = self.result()
3124 if self.type.is_pyobject and self.use_managed_ref:
3125 rhs.make_owned_reference(code)
3126 code.put_giveref(rhs.py_result())
3127 code.put_gotref(select_code)
3128 code.put_decref(select_code, self.ctype())
3129 code.putln(
3130 "%s = %s;" % (
3131 select_code,
3132 rhs.result_as(self.ctype())))
3133 #rhs.result()))
3134 rhs.generate_post_assignment_code(code)
3135 rhs.free_temps(code)
3136 self.obj.generate_disposal_code(code)
3137 self.obj.free_temps(code)
3139 def generate_deletion_code(self, code):
3140 interned_attr_cname = code.intern_identifier(self.attribute)
3141 self.obj.generate_evaluation_code(code)
3142 if self.is_py_attr:
3143 code.put_error_if_neg(self.pos,
3144 'PyObject_DelAttr(%s, %s)' % (
3145 self.obj.py_result(),
3146 interned_attr_cname))
3147 else:
3148 error(self.pos, "Cannot delete C attribute of extension type")
3149 self.obj.generate_disposal_code(code)
3150 self.obj.free_temps(code)
3152 def annotate(self, code):
3153 if self.is_py_attr:
3154 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
3155 else:
3156 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
3158 def put_nonecheck(self, code):
3159 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
3160 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
3161 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute)
3162 code.putln(code.error_goto(self.pos))
3163 code.putln("}")
3166 #-------------------------------------------------------------------
3168 # Constructor nodes
3170 #-------------------------------------------------------------------
3172 class StarredTargetNode(ExprNode):
3173 # A starred expression like "*a"
3175 # This is only allowed in sequence assignment targets such as
3177 # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4]
3179 # and will be removed during type analysis (or generate an error
3180 # if it's found at unexpected places).
3182 # target ExprNode
3184 subexprs = ['target']
3185 is_starred = 1
3186 type = py_object_type
3187 is_temp = 1
3189 def __init__(self, pos, target):
3190 self.pos = pos
3191 self.target = target
3193 def analyse_declarations(self, env):
3194 error(self.pos, "can use starred expression only as assignment target")
3195 self.target.analyse_declarations(env)
3197 def analyse_types(self, env):
3198 error(self.pos, "can use starred expression only as assignment target")
3199 self.target.analyse_types(env)
3200 self.type = self.target.type
3202 def analyse_target_declaration(self, env):
3203 self.target.analyse_target_declaration(env)
3205 def analyse_target_types(self, env):
3206 self.target.analyse_target_types(env)
3207 self.type = self.target.type
3209 def calculate_result_code(self):
3210 return ""
3212 def generate_result_code(self, code):
3213 pass
3216 class SequenceNode(ExprNode):
3217 # Base class for list and tuple constructor nodes.
3218 # Contains common code for performing sequence unpacking.
3220 # args [ExprNode]
3221 # iterator ExprNode
3222 # unpacked_items [ExprNode] or None
3223 # coerced_unpacked_items [ExprNode] or None
3225 subexprs = ['args']
3227 is_sequence_constructor = 1
3228 unpacked_items = None
3230 def compile_time_value_list(self, denv):
3231 return [arg.compile_time_value(denv) for arg in self.args]
3233 def replace_starred_target_node(self):
3234 # replace a starred node in the targets by the contained expression
3235 self.starred_assignment = False
3236 args = []
3237 for arg in self.args:
3238 if arg.is_starred:
3239 if self.starred_assignment:
3240 error(arg.pos, "more than 1 starred expression in assignment")
3241 self.starred_assignment = True
3242 arg = arg.target
3243 arg.is_starred = True
3244 args.append(arg)
3245 self.args = args
3247 def analyse_target_declaration(self, env):
3248 self.replace_starred_target_node()
3249 for arg in self.args:
3250 arg.analyse_target_declaration(env)
3252 def analyse_types(self, env, skip_children=False):
3253 for i in range(len(self.args)):
3254 arg = self.args[i]
3255 if not skip_children: arg.analyse_types(env)
3256 self.args[i] = arg.coerce_to_pyobject(env)
3257 self.type = py_object_type
3258 self.is_temp = 1
3260 def analyse_target_types(self, env):
3261 self.iterator = PyTempNode(self.pos, env)
3262 self.unpacked_items = []
3263 self.coerced_unpacked_items = []
3264 for arg in self.args:
3265 arg.analyse_target_types(env)
3266 if arg.is_starred:
3267 if not arg.type.assignable_from(Builtin.list_type):
3268 error(arg.pos,
3269 "starred target must have Python object (list) type")
3270 if arg.type is py_object_type:
3271 arg.type = Builtin.list_type
3272 unpacked_item = PyTempNode(self.pos, env)
3273 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
3274 self.unpacked_items.append(unpacked_item)
3275 self.coerced_unpacked_items.append(coerced_unpacked_item)
3276 self.type = py_object_type
3278 def generate_result_code(self, code):
3279 self.generate_operation_code(code)
3281 def generate_assignment_code(self, rhs, code):
3282 if self.starred_assignment:
3283 self.generate_starred_assignment_code(rhs, code)
3284 else:
3285 self.generate_parallel_assignment_code(rhs, code)
3287 for item in self.unpacked_items:
3288 item.release(code)
3289 rhs.free_temps(code)
3291 def generate_parallel_assignment_code(self, rhs, code):
3292 # Need to work around the fact that generate_evaluation_code
3293 # allocates the temps in a rather hacky way -- the assignment
3294 # is evaluated twice, within each if-block.
3296 code.globalstate.use_utility_code(unpacking_utility_code)
3298 if rhs.type is tuple_type:
3299 tuple_check = "likely(%s != Py_None)"
3300 else:
3301 tuple_check = "PyTuple_CheckExact(%s)"
3302 code.putln(
3303 "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
3304 tuple_check % rhs.py_result(),
3305 rhs.py_result(),
3306 len(self.args)))
3307 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3308 for item in self.unpacked_items:
3309 item.allocate(code)
3310 for i in range(len(self.args)):
3311 item = self.unpacked_items[i]
3312 code.put(
3313 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3314 item.result(),
3315 i))
3316 code.put_incref(item.result(), item.ctype())
3317 value_node = self.coerced_unpacked_items[i]
3318 value_node.generate_evaluation_code(code)
3319 rhs.generate_disposal_code(code)
3321 for i in range(len(self.args)):
3322 self.args[i].generate_assignment_code(
3323 self.coerced_unpacked_items[i], code)
3325 code.putln("} else {")
3327 if rhs.type is tuple_type:
3328 code.globalstate.use_utility_code(tuple_unpacking_error_code)
3329 code.putln("__Pyx_UnpackTupleError(%s, %s);" % (
3330 rhs.py_result(), len(self.args)))
3331 code.putln(code.error_goto(self.pos))
3332 else:
3333 self.iterator.allocate(code)
3334 code.putln(
3335 "%s = PyObject_GetIter(%s); %s" % (
3336 self.iterator.result(),
3337 rhs.py_result(),
3338 code.error_goto_if_null(self.iterator.result(), self.pos)))
3339 code.put_gotref(self.iterator.py_result())
3340 rhs.generate_disposal_code(code)
3341 for i in range(len(self.args)):
3342 item = self.unpacked_items[i]
3343 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3344 self.iterator.py_result(), i)
3345 code.putln(
3346 "%s = %s; %s" % (
3347 item.result(),
3348 typecast(item.ctype(), py_object_type, unpack_code),
3349 code.error_goto_if_null(item.result(), self.pos)))
3350 code.put_gotref(item.py_result())
3351 value_node = self.coerced_unpacked_items[i]
3352 value_node.generate_evaluation_code(code)
3353 code.put_error_if_neg(self.pos,
3354 "__Pyx_EndUnpack(%s)" % (
3355 self.iterator.py_result()))
3356 if debug_disposal_code:
3357 print("UnpackNode.generate_assignment_code:")
3358 print("...generating disposal code for %s" % self.iterator)
3359 self.iterator.generate_disposal_code(code)
3360 self.iterator.free_temps(code)
3361 self.iterator.release(code)
3363 for i in range(len(self.args)):
3364 self.args[i].generate_assignment_code(
3365 self.coerced_unpacked_items[i], code)
3367 code.putln("}")
3369 def generate_starred_assignment_code(self, rhs, code):
3370 code.globalstate.use_utility_code(unpacking_utility_code)
3372 for i, arg in enumerate(self.args):
3373 if arg.is_starred:
3374 starred_target = self.unpacked_items[i]
3375 fixed_args_left = self.args[:i]
3376 fixed_args_right = self.args[i+1:]
3377 break
3379 self.iterator.allocate(code)
3380 code.putln(
3381 "%s = PyObject_GetIter(%s); %s" % (
3382 self.iterator.result(),
3383 rhs.py_result(),
3384 code.error_goto_if_null(self.iterator.result(), self.pos)))
3385 code.put_gotref(self.iterator.py_result())
3386 rhs.generate_disposal_code(code)
3388 for item in self.unpacked_items:
3389 item.allocate(code)
3390 for i in range(len(fixed_args_left)):
3391 item = self.unpacked_items[i]
3392 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3393 self.iterator.py_result(), i)
3394 code.putln(
3395 "%s = %s; %s" % (
3396 item.result(),
3397 typecast(item.ctype(), py_object_type, unpack_code),
3398 code.error_goto_if_null(item.result(), self.pos)))
3399 code.put_gotref(item.py_result())
3400 value_node = self.coerced_unpacked_items[i]
3401 value_node.generate_evaluation_code(code)
3403 target_list = starred_target.result()
3404 code.putln("%s = PySequence_List(%s); %s" % (
3405 target_list, self.iterator.py_result(),
3406 code.error_goto_if_null(target_list, self.pos)))
3407 code.put_gotref(target_list)
3408 if fixed_args_right:
3409 code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
3410 unpacked_right_args = self.unpacked_items[-len(fixed_args_right):]
3411 code.putln("if (unlikely(PyList_GET_SIZE(%s) < %d)) {" % (
3412 (target_list, len(unpacked_right_args))))
3413 code.put("__Pyx_RaiseNeedMoreValuesError(%d+PyList_GET_SIZE(%s)); %s" % (
3414 len(fixed_args_left), target_list,
3415 code.error_goto(self.pos)))
3416 code.putln('}')
3417 for i, (arg, coerced_arg) in enumerate(zip(unpacked_right_args[::-1],
3418 self.coerced_unpacked_items[::-1])):
3419 code.putln(
3420 "%s = PyList_GET_ITEM(%s, PyList_GET_SIZE(%s)-1); " % (
3421 arg.py_result(),
3422 target_list, target_list))
3423 # resize the list the hard way
3424 code.putln("((PyVarObject*)%s)->ob_size--;" % target_list)
3425 code.put_gotref(arg.py_result())
3426 coerced_arg.generate_evaluation_code(code)
3428 self.iterator.generate_disposal_code(code)
3429 self.iterator.free_temps(code)
3430 self.iterator.release(code)
3432 for i in range(len(self.args)):
3433 self.args[i].generate_assignment_code(
3434 self.coerced_unpacked_items[i], code)
3436 def annotate(self, code):
3437 for arg in self.args:
3438 arg.annotate(code)
3439 if self.unpacked_items:
3440 for arg in self.unpacked_items:
3441 arg.annotate(code)
3442 for arg in self.coerced_unpacked_items:
3443 arg.annotate(code)
3446 class TupleNode(SequenceNode):
3447 # Tuple constructor.
3449 type = tuple_type
3451 gil_message = "Constructing Python tuple"
3453 def analyse_types(self, env, skip_children=False):
3454 if len(self.args) == 0:
3455 self.is_temp = 0
3456 self.is_literal = 1
3457 else:
3458 SequenceNode.analyse_types(self, env, skip_children)
3460 def calculate_result_code(self):
3461 if len(self.args) > 0:
3462 error(self.pos, "Positive length tuples must be constructed.")
3463 else:
3464 return Naming.empty_tuple
3466 def calculate_constant_result(self):
3467 self.constant_result = tuple([
3468 arg.constant_result for arg in self.args])
3470 def compile_time_value(self, denv):
3471 values = self.compile_time_value_list(denv)
3472 try:
3473 return tuple(values)
3474 except Exception, e:
3475 self.compile_time_value_error(e)
3477 def generate_operation_code(self, code):
3478 if len(self.args) == 0:
3479 # result_code is Naming.empty_tuple
3480 return
3481 code.putln(
3482 "%s = PyTuple_New(%s); %s" % (
3483 self.result(),
3484 len(self.args),
3485 code.error_goto_if_null(self.result(), self.pos)))
3486 code.put_gotref(self.py_result())
3487 for i in range(len(self.args)):
3488 arg = self.args[i]
3489 if not arg.result_in_temp():
3490 code.put_incref(arg.result(), arg.ctype())
3491 code.putln(
3492 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3493 self.result(),
3494 i,
3495 arg.py_result()))
3496 code.put_giveref(arg.py_result())
3498 def generate_subexpr_disposal_code(self, code):
3499 # We call generate_post_assignment_code here instead
3500 # of generate_disposal_code, because values were stored
3501 # in the tuple using a reference-stealing operation.
3502 for arg in self.args:
3503 arg.generate_post_assignment_code(code)
3504 # Should NOT call free_temps -- this is invoked by the default
3505 # generate_evaluation_code which will do that.
3508 class ListNode(SequenceNode):
3509 # List constructor.
3511 # obj_conversion_errors [PyrexError] used internally
3512 # orignial_args [ExprNode] used internally
3514 obj_conversion_errors = []
3516 gil_message = "Constructing Python list"
3518 def type_dependencies(self, env):
3519 return ()
3521 def infer_type(self, env):
3522 # TOOD: Infer non-object list arrays.
3523 return list_type
3525 def analyse_expressions(self, env):
3526 SequenceNode.analyse_expressions(self, env)
3527 self.coerce_to_pyobject(env)
3529 def analyse_types(self, env):
3530 hold_errors()
3531 self.original_args = list(self.args)
3532 SequenceNode.analyse_types(self, env)
3533 self.type = list_type
3534 self.obj_conversion_errors = held_errors()
3535 release_errors(ignore=True)
3537 def coerce_to(self, dst_type, env):
3538 if dst_type.is_pyobject:
3539 for err in self.obj_conversion_errors:
3540 report_error(err)
3541 self.obj_conversion_errors = []
3542 if not self.type.subtype_of(dst_type):
3543 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3544 elif dst_type.is_ptr:
3545 base_type = dst_type.base_type
3546 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3547 for i in range(len(self.original_args)):
3548 arg = self.args[i]
3549 if isinstance(arg, CoerceToPyTypeNode):
3550 arg = arg.arg
3551 self.args[i] = arg.coerce_to(base_type, env)
3552 elif dst_type.is_struct:
3553 if len(self.args) > len(dst_type.scope.var_entries):
3554 error(self.pos, "Too may members for '%s'" % dst_type)
3555 else:
3556 if len(self.args) < len(dst_type.scope.var_entries):
3557 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3558 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3559 if isinstance(arg, CoerceToPyTypeNode):
3560 arg = arg.arg
3561 self.args[i] = arg.coerce_to(member.type, env)
3562 self.type = dst_type
3563 else:
3564 self.type = error_type
3565 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3566 return self
3568 def release_temp(self, env):
3569 if self.type.is_array:
3570 # To be valid C++, we must allocate the memory on the stack
3571 # manually and be sure not to reuse it for something else.
3572 pass
3573 else:
3574 SequenceNode.release_temp(self, env)
3576 def calculate_constant_result(self):
3577 self.constant_result = [
3578 arg.constant_result for arg in self.args]
3580 def compile_time_value(self, denv):
3581 return self.compile_time_value_list(denv)
3583 def generate_operation_code(self, code):
3584 if self.type.is_pyobject:
3585 for err in self.obj_conversion_errors:
3586 report_error(err)
3587 code.putln("%s = PyList_New(%s); %s" %
3588 (self.result(),
3589 len(self.args),
3590 code.error_goto_if_null(self.result(), self.pos)))
3591 code.put_gotref(self.py_result())
3592 for i in range(len(self.args)):
3593 arg = self.args[i]
3594 #if not arg.is_temp:
3595 if not arg.result_in_temp():
3596 code.put_incref(arg.result(), arg.ctype())
3597 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3598 (self.result(),
3599 i,
3600 arg.py_result()))
3601 code.put_giveref(arg.py_result())
3602 elif self.type.is_array:
3603 for i, arg in enumerate(self.args):
3604 code.putln("%s[%s] = %s;" % (
3605 self.result(),
3606 i,
3607 arg.result()))
3608 elif self.type.is_struct:
3609 for arg, member in zip(self.args, self.type.scope.var_entries):
3610 code.putln("%s.%s = %s;" % (
3611 self.result(),
3612 member.cname,
3613 arg.result()))
3614 else:
3615 raise InternalError("List type never specified")
3617 def generate_subexpr_disposal_code(self, code):
3618 # We call generate_post_assignment_code here instead
3619 # of generate_disposal_code, because values were stored
3620 # in the list using a reference-stealing operation.
3621 for arg in self.args:
3622 arg.generate_post_assignment_code(code)
3623 # Should NOT call free_temps -- this is invoked by the default
3624 # generate_evaluation_code which will do that.
3627 class ComprehensionNode(ExprNode):
3628 subexprs = ["target"]
3629 child_attrs = ["loop", "append"]
3631 def infer_type(self, env):
3632 return self.target.infer_type(env)
3634 def analyse_types(self, env):
3635 self.target.analyse_expressions(env)
3636 self.type = self.target.type
3637 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3638 # We are analysing declarations to late.
3639 self.loop.target.analyse_target_declaration(env)
3640 env.infer_types()
3641 self.loop.analyse_declarations(env)
3642 self.loop.analyse_expressions(env)
3644 def calculate_result_code(self):
3645 return self.target.result()
3647 def generate_result_code(self, code):
3648 self.generate_operation_code(code)
3650 def generate_operation_code(self, code):
3651 self.loop.generate_execution_code(code)
3653 def annotate(self, code):
3654 self.loop.annotate(code)
3657 class ComprehensionAppendNode(ExprNode):
3658 # Need to be careful to avoid infinite recursion:
3659 # target must not be in child_attrs/subexprs
3660 subexprs = ['expr']
3662 type = PyrexTypes.c_int_type
3664 def analyse_types(self, env):
3665 self.expr.analyse_types(env)
3666 if not self.expr.type.is_pyobject:
3667 self.expr = self.expr.coerce_to_pyobject(env)
3668 self.is_temp = 1
3670 def generate_result_code(self, code):
3671 if self.target.type is list_type:
3672 function = "PyList_Append"
3673 elif self.target.type is set_type:
3674 function = "PySet_Add"
3675 else:
3676 raise InternalError(
3677 "Invalid type for comprehension node: %s" % self.target.type)
3679 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3680 (self.result(),
3681 function,
3682 self.target.result(),
3683 self.expr.result(),
3684 code.error_goto_if(self.result(), self.pos)))
3686 class DictComprehensionAppendNode(ComprehensionAppendNode):
3687 subexprs = ['key_expr', 'value_expr']
3689 def analyse_types(self, env):
3690 self.key_expr.analyse_types(env)
3691 if not self.key_expr.type.is_pyobject:
3692 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3693 self.value_expr.analyse_types(env)
3694 if not self.value_expr.type.is_pyobject:
3695 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3696 self.is_temp = 1
3698 def generate_result_code(self, code):
3699 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3700 (self.result(),
3701 self.target.result(),
3702 self.key_expr.result(),
3703 self.value_expr.result(),
3704 code.error_goto_if(self.result(), self.pos)))
3707 class SetNode(ExprNode):
3708 # Set constructor.
3710 type = set_type
3712 subexprs = ['args']
3714 gil_message = "Constructing Python set"
3716 def analyse_types(self, env):
3717 for i in range(len(self.args)):
3718 arg = self.args[i]
3719 arg.analyse_types(env)
3720 self.args[i] = arg.coerce_to_pyobject(env)
3721 self.type = set_type
3722 self.is_temp = 1
3724 def calculate_constant_result(self):
3725 self.constant_result = set([
3726 arg.constant_result for arg in self.args])
3728 def compile_time_value(self, denv):
3729 values = [arg.compile_time_value(denv) for arg in self.args]
3730 try:
3731 return set(values)
3732 except Exception, e:
3733 self.compile_time_value_error(e)
3735 def generate_evaluation_code(self, code):
3736 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3737 self.allocate_temp_result(code)
3738 code.putln(
3739 "%s = PySet_New(0); %s" % (
3740 self.result(),
3741 code.error_goto_if_null(self.result(), self.pos)))
3742 code.put_gotref(self.py_result())
3743 for arg in self.args:
3744 arg.generate_evaluation_code(code)
3745 code.putln(
3746 code.error_goto_if_neg(
3747 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3748 self.pos))
3749 arg.generate_disposal_code(code)
3750 arg.free_temps(code)
3753 class DictNode(ExprNode):
3754 # Dictionary constructor.
3756 # key_value_pairs [DictItemNode]
3758 # obj_conversion_errors [PyrexError] used internally
3760 subexprs = ['key_value_pairs']
3761 is_temp = 1
3762 type = dict_type
3764 obj_conversion_errors = []
3766 def calculate_constant_result(self):
3767 self.constant_result = dict([
3768 item.constant_result for item in self.key_value_pairs])
3770 def compile_time_value(self, denv):
3771 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3772 for item in self.key_value_pairs]
3773 try:
3774 return dict(pairs)
3775 except Exception, e:
3776 self.compile_time_value_error(e)
3778 def type_dependencies(self, env):
3779 return ()
3781 def infer_type(self, env):
3782 # TOOD: Infer struct constructors.
3783 return dict_type
3785 def analyse_types(self, env):
3786 hold_errors()
3787 for item in self.key_value_pairs:
3788 item.analyse_types(env)
3789 self.obj_conversion_errors = held_errors()
3790 release_errors(ignore=True)
3792 def coerce_to(self, dst_type, env):
3793 if dst_type.is_pyobject:
3794 self.release_errors()
3795 if not self.type.subtype_of(dst_type):
3796 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3797 elif dst_type.is_struct_or_union:
3798 self.type = dst_type
3799 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3800 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3801 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3802 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3803 for item in self.key_value_pairs:
3804 if isinstance(item.key, CoerceToPyTypeNode):
3805 item.key = item.key.arg
3806 if not isinstance(item.key, (UnicodeNode, StringNode, BytesNode)):
3807 error(item.key.pos, "Invalid struct field identifier")
3808 item.key = StringNode(item.key.pos, value="<error>")
3809 else:
3810 key = str(item.key.value) # converts string literals to unicode in Py3
3811 member = dst_type.scope.lookup_here(key)
3812 if not member:
3813 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key))
3814 else:
3815 value = item.value
3816 if isinstance(value, CoerceToPyTypeNode):
3817 value = value.arg
3818 item.value = value.coerce_to(member.type, env)
3819 else:
3820 self.type = error_type
3821 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3822 return self
3824 def release_errors(self):
3825 for err in self.obj_conversion_errors:
3826 report_error(err)
3827 self.obj_conversion_errors = []
3829 gil_message = "Constructing Python dict"
3831 def generate_evaluation_code(self, code):
3832 # Custom method used here because key-value
3833 # pairs are evaluated and used one at a time.
3834 code.mark_pos(self.pos)
3835 self.allocate_temp_result(code)
3836 if self.type.is_pyobject:
3837 self.release_errors()
3838 code.putln(
3839 "%s = PyDict_New(); %s" % (
3840 self.result(),
3841 code.error_goto_if_null(self.result(), self.pos)))
3842 code.put_gotref(self.py_result())
3843 for item in self.key_value_pairs:
3844 item.generate_evaluation_code(code)
3845 if self.type.is_pyobject:
3846 code.put_error_if_neg(self.pos,
3847 "PyDict_SetItem(%s, %s, %s)" % (
3848 self.result(),
3849 item.key.py_result(),
3850 item.value.py_result()))
3851 else:
3852 code.putln("%s.%s = %s;" % (
3853 self.result(),
3854 item.key.value,
3855 item.value.result()))
3856 item.generate_disposal_code(code)
3857 item.free_temps(code)
3859 def annotate(self, code):
3860 for item in self.key_value_pairs:
3861 item.annotate(code)
3863 class DictItemNode(ExprNode):
3864 # Represents a single item in a DictNode
3866 # key ExprNode
3867 # value ExprNode
3868 subexprs = ['key', 'value']
3870 nogil_check = None # Parent DictNode takes care of it
3872 def calculate_constant_result(self):
3873 self.constant_result = (
3874 self.key.constant_result, self.value.constant_result)
3876 def analyse_types(self, env):
3877 self.key.analyse_types(env)
3878 self.value.analyse_types(env)
3879 self.key = self.key.coerce_to_pyobject(env)
3880 self.value = self.value.coerce_to_pyobject(env)
3882 def generate_evaluation_code(self, code):
3883 self.key.generate_evaluation_code(code)
3884 self.value.generate_evaluation_code(code)
3886 def generate_disposal_code(self, code):
3887 self.key.generate_disposal_code(code)
3888 self.value.generate_disposal_code(code)
3890 def free_temps(self, code):
3891 self.key.free_temps(code)
3892 self.value.free_temps(code)
3894 def __iter__(self):
3895 return iter([self.key, self.value])
3898 class ClassNode(ExprNode):
3899 # Helper class used in the implementation of Python
3900 # class definitions. Constructs a class object given
3901 # a name, tuple of bases and class dictionary.
3903 # name EncodedString Name of the class
3904 # bases ExprNode Base class tuple
3905 # dict ExprNode Class dict (not owned by this node)
3906 # doc ExprNode or None Doc string
3907 # module_name string Name of defining module
3909 subexprs = ['bases', 'doc']
3911 def analyse_types(self, env):
3912 self.bases.analyse_types(env)
3913 if self.doc:
3914 self.doc.analyse_types(env)
3915 self.doc = self.doc.coerce_to_pyobject(env)
3916 self.module_name = env.global_scope().qualified_name
3917 self.type = py_object_type
3918 self.is_temp = 1
3919 env.use_utility_code(create_class_utility_code);
3921 gil_message = "Constructing Python class"
3923 def generate_result_code(self, code):
3924 cname = code.intern_identifier(self.name)
3925 if self.doc:
3926 code.put_error_if_neg(self.pos,
3927 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3928 self.dict.py_result(),
3929 self.doc.py_result()))
3930 code.putln(
3931 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3932 self.result(),
3933 self.bases.py_result(),
3934 self.dict.py_result(),
3935 cname,
3936 self.module_name,
3937 code.error_goto_if_null(self.result(), self.pos)))
3938 code.put_gotref(self.py_result())
3941 class UnboundMethodNode(ExprNode):
3942 # Helper class used in the implementation of Python
3943 # class definitions. Constructs an unbound method
3944 # object from a class and a function.
3946 # function ExprNode Function object
3948 type = py_object_type
3949 is_temp = 1
3951 subexprs = ['function']
3953 def analyse_types(self, env):
3954 self.function.analyse_types(env)
3956 gil_message = "Constructing an unbound method"
3958 def generate_result_code(self, code):
3959 class_cname = code.pyclass_stack[-1].classobj.result()
3960 code.putln(
3961 "%s = PyMethod_New(%s, 0, %s); %s" % (
3962 self.result(),
3963 self.function.py_result(),
3964 class_cname,
3965 code.error_goto_if_null(self.result(), self.pos)))
3966 code.put_gotref(self.py_result())
3968 class PyCFunctionNode(AtomicExprNode):
3969 # Helper class used in the implementation of Python
3970 # class definitions. Constructs a PyCFunction object
3971 # from a PyMethodDef struct.
3973 # pymethdef_cname string PyMethodDef structure
3975 type = py_object_type
3976 is_temp = 1
3978 def analyse_types(self, env):
3979 pass
3981 gil_message = "Constructing Python function"
3983 def generate_result_code(self, code):
3984 code.putln(
3985 "%s = PyCFunction_New(&%s, 0); %s" % (
3986 self.result(),
3987 self.pymethdef_cname,
3988 code.error_goto_if_null(self.result(), self.pos)))
3989 code.put_gotref(self.py_result())
3991 #-------------------------------------------------------------------
3993 # Unary operator nodes
3995 #-------------------------------------------------------------------
3997 compile_time_unary_operators = {
3998 'not': operator.not_,
3999 '~': operator.inv,
4000 '-': operator.neg,
4001 '+': operator.pos,
4004 class UnopNode(ExprNode):
4005 # operator string
4006 # operand ExprNode
4008 # Processing during analyse_expressions phase:
4010 # analyse_c_operation
4011 # Called when the operand is not a pyobject.
4012 # - Check operand type and coerce if needed.
4013 # - Determine result type and result code fragment.
4014 # - Allocate temporary for result if needed.
4016 subexprs = ['operand']
4017 infix = True
4019 def calculate_constant_result(self):
4020 func = compile_time_unary_operators[self.operator]
4021 self.constant_result = func(self.operand.constant_result)
4023 def compile_time_value(self, denv):
4024 func = compile_time_unary_operators.get(self.operator)
4025 if not func:
4026 error(self.pos,
4027 "Unary '%s' not supported in compile-time expression"
4028 % self.operator)
4029 operand = self.operand.compile_time_value(denv)
4030 try:
4031 return func(operand)
4032 except Exception, e:
4033 self.compile_time_value_error(e)
4035 def infer_type(self, env):
4036 return self.operand.infer_type(env)
4038 def analyse_types(self, env):
4039 self.operand.analyse_types(env)
4040 if self.is_py_operation():
4041 self.coerce_operand_to_pyobject(env)
4042 self.type = py_object_type
4043 self.is_temp = 1
4044 else:
4045 self.analyse_c_operation(env)
4047 def check_const(self):
4048 return self.operand.check_const()
4050 def is_py_operation(self):
4051 return self.operand.type.is_pyobject
4053 def nogil_check(self, env):
4054 if self.is_py_operation():
4055 self.gil_error()
4057 def coerce_operand_to_pyobject(self, env):
4058 self.operand = self.operand.coerce_to_pyobject(env)
4060 def generate_result_code(self, code):
4061 if self.operand.type.is_pyobject:
4062 self.generate_py_operation_code(code)
4064 def generate_py_operation_code(self, code):
4065 function = self.py_operation_function()
4066 code.putln(
4067 "%s = %s(%s); %s" % (
4068 self.result(),
4069 function,
4070 self.operand.py_result(),
4071 code.error_goto_if_null(self.result(), self.pos)))
4072 code.put_gotref(self.py_result())
4074 def type_error(self):
4075 if not self.operand.type.is_error:
4076 error(self.pos, "Invalid operand type for '%s' (%s)" %
4077 (self.operator, self.operand.type))
4078 self.type = PyrexTypes.error_type
4081 class NotNode(ExprNode):
4082 # 'not' operator
4084 # operand ExprNode
4086 type = PyrexTypes.c_bint_type
4088 subexprs = ['operand']
4090 def calculate_constant_result(self):
4091 self.constant_result = not self.operand.constant_result
4093 def compile_time_value(self, denv):
4094 operand = self.operand.compile_time_value(denv)
4095 try:
4096 return not operand
4097 except Exception, e:
4098 self.compile_time_value_error(e)
4100 def infer_type(self, env):
4101 return PyrexTypes.c_bint_type
4103 def analyse_types(self, env):
4104 self.operand.analyse_types(env)
4105 self.operand = self.operand.coerce_to_boolean(env)
4107 def calculate_result_code(self):
4108 return "(!%s)" % self.operand.result()
4110 def generate_result_code(self, code):
4111 pass
4114 class UnaryPlusNode(UnopNode):
4115 # unary '+' operator
4117 operator = '+'
4119 def analyse_c_operation(self, env):
4120 self.type = self.operand.type
4122 def py_operation_function(self):
4123 return "PyNumber_Positive"
4125 def calculate_result_code(self):
4126 return self.operand.result()
4129 class UnaryMinusNode(UnopNode):
4130 # unary '-' operator
4132 operator = '-'
4134 def analyse_c_operation(self, env):
4135 if self.operand.type.is_numeric:
4136 self.type = self.operand.type
4137 else:
4138 self.type_error()
4139 if self.type.is_complex:
4140 self.infix = False
4142 def py_operation_function(self):
4143 return "PyNumber_Negative"
4145 def calculate_result_code(self):
4146 if self.infix:
4147 return "(-%s)" % self.operand.result()
4148 else:
4149 return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result())
4151 def get_constant_c_result_code(self):
4152 value = self.operand.get_constant_c_result_code()
4153 if value:
4154 return "(-%s)" % (value)
4156 class TildeNode(UnopNode):
4157 # unary '~' operator
4159 def analyse_c_operation(self, env):
4160 if self.operand.type.is_int:
4161 self.type = self.operand.type
4162 else:
4163 self.type_error()
4165 def py_operation_function(self):
4166 return "PyNumber_Invert"
4168 def calculate_result_code(self):
4169 return "(~%s)" % self.operand.result()
4172 class AmpersandNode(ExprNode):
4173 # The C address-of operator.
4175 # operand ExprNode
4177 subexprs = ['operand']
4179 def infer_type(self, env):
4180 return PyrexTypes.c_ptr_type(self.operand.infer_type(env))
4182 def analyse_types(self, env):
4183 self.operand.analyse_types(env)
4184 argtype = self.operand.type
4185 if not (argtype.is_cfunction or self.operand.is_lvalue()):
4186 self.error("Taking address of non-lvalue")
4187 return
4188 if argtype.is_pyobject:
4189 self.error("Cannot take address of Python variable")
4190 return
4191 self.type = PyrexTypes.c_ptr_type(argtype)
4193 def check_const(self):
4194 return self.operand.check_const_addr()
4196 def error(self, mess):
4197 error(self.pos, mess)
4198 self.type = PyrexTypes.error_type
4199 self.result_code = "<error>"
4201 def calculate_result_code(self):
4202 return "(&%s)" % self.operand.result()
4204 def generate_result_code(self, code):
4205 pass
4208 unop_node_classes = {
4209 "+": UnaryPlusNode,
4210 "-": UnaryMinusNode,
4211 "~": TildeNode,
4214 def unop_node(pos, operator, operand):
4215 # Construct unnop node of appropriate class for
4216 # given operator.
4217 if isinstance(operand, IntNode) and operator == '-':
4218 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
4219 elif isinstance(operand, UnopNode) and operand.operator == operator:
4220 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
4221 return unop_node_classes[operator](pos,
4222 operator = operator,
4223 operand = operand)
4226 class TypecastNode(ExprNode):
4227 # C type cast
4229 # operand ExprNode
4230 # base_type CBaseTypeNode
4231 # declarator CDeclaratorNode
4233 # If used from a transform, one can if wanted specify the attribute
4234 # "type" directly and leave base_type and declarator to None
4236 subexprs = ['operand']
4237 base_type = declarator = type = None
4239 def type_dependencies(self, env):
4240 return ()
4242 def infer_type(self, env):
4243 if self.type is None:
4244 base_type = self.base_type.analyse(env)
4245 _, self.type = self.declarator.analyse(base_type, env)
4246 return self.type
4248 def analyse_types(self, env):
4249 if self.type is None:
4250 base_type = self.base_type.analyse(env)
4251 _, self.type = self.declarator.analyse(base_type, env)
4252 if self.type.is_cfunction:
4253 error(self.pos,
4254 "Cannot cast to a function type")
4255 self.type = PyrexTypes.error_type
4256 self.operand.analyse_types(env)
4257 to_py = self.type.is_pyobject
4258 from_py = self.operand.type.is_pyobject
4259 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
4260 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
4261 if to_py and not from_py:
4262 if self.operand.type.can_coerce_to_pyobject(env):
4263 self.result_ctype = py_object_type
4264 self.operand = self.operand.coerce_to_pyobject(env)
4265 else:
4266 if self.operand.type.is_ptr:
4267 if not (self.operand.type.base_type.is_void or self.operand.type.base_type.is_struct):
4268 error(self.pos, "Python objects cannot be cast from pointers of primitive types")
4269 else:
4270 # Should this be an error?
4271 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
4272 self.operand = self.operand.coerce_to_simple(env)
4273 elif from_py and not to_py:
4274 if self.type.create_from_py_utility_code(env):
4275 self.operand = self.operand.coerce_to(self.type, env)
4276 elif self.type.is_ptr:
4277 if not (self.type.base_type.is_void or self.type.base_type.is_struct):
4278 error(self.pos, "Python objects cannot be cast to pointers of primitive types")
4279 else:
4280 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
4281 elif from_py and to_py:
4282 if self.typecheck and self.type.is_extension_type:
4283 self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True)
4285 def nogil_check(self, env):
4286 if self.type and self.type.is_pyobject and self.is_temp:
4287 self.gil_error()
4289 def check_const(self):
4290 return self.operand.check_const()
4292 def calculate_constant_result(self):
4293 # we usually do not know the result of a type cast at code
4294 # generation time
4295 pass
4297 def calculate_result_code(self):
4298 opnd = self.operand
4299 return self.type.cast_code(opnd.result())
4301 def get_constant_c_result_code(self):
4302 operand_result = self.operand.get_constant_c_result_code()
4303 if operand_result:
4304 return self.type.cast_code(operand_result)
4306 def result_as(self, type):
4307 if self.type.is_pyobject and not self.is_temp:
4308 # Optimise away some unnecessary casting
4309 return self.operand.result_as(type)
4310 else:
4311 return ExprNode.result_as(self, type)
4313 def generate_result_code(self, code):
4314 if self.is_temp:
4315 code.putln(
4316 "%s = (PyObject *)%s;" % (
4317 self.result(),
4318 self.operand.result()))
4319 code.put_incref(self.result(), self.ctype())
4322 class SizeofNode(ExprNode):
4323 # Abstract base class for sizeof(x) expression nodes.
4325 type = PyrexTypes.c_size_t_type
4327 def check_const(self):
4328 return True
4330 def generate_result_code(self, code):
4331 pass
4334 class SizeofTypeNode(SizeofNode):
4335 # C sizeof function applied to a type
4337 # base_type CBaseTypeNode
4338 # declarator CDeclaratorNode
4340 subexprs = []
4341 arg_type = None
4343 def analyse_types(self, env):
4344 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
4345 # this could be better handled by more uniformly treating types as runtime-available objects
4346 if 0 and self.base_type.module_path:
4347 path = self.base_type.module_path
4348 obj = env.lookup(path[0])
4349 if obj.as_module is None:
4350 operand = NameNode(pos=self.pos, name=path[0])
4351 for attr in path[1:]:
4352 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
4353 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
4354 self.operand = operand
4355 self.__class__ = SizeofVarNode
4356 self.analyse_types(env)
4357 return
4358 if self.arg_type is None:
4359 base_type = self.base_type.analyse(env)
4360 _, arg_type = self.declarator.analyse(base_type, env)
4361 self.arg_type = arg_type
4362 self.check_type()
4364 def check_type(self):
4365 arg_type = self.arg_type
4366 if arg_type.is_pyobject and not arg_type.is_extension_type:
4367 error(self.pos, "Cannot take sizeof Python object")
4368 elif arg_type.is_void:
4369 error(self.pos, "Cannot take sizeof void")
4370 elif not arg_type.is_complete():
4371 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
4373 def calculate_result_code(self):
4374 if self.arg_type.is_extension_type:
4375 # the size of the pointer is boring
4376 # we want the size of the actual struct
4377 arg_code = self.arg_type.declaration_code("", deref=1)
4378 else:
4379 arg_code = self.arg_type.declaration_code("")
4380 return "(sizeof(%s))" % arg_code
4383 class SizeofVarNode(SizeofNode):
4384 # C sizeof function applied to a variable
4386 # operand ExprNode
4388 subexprs = ['operand']
4390 def analyse_types(self, env):
4391 # We may actually be looking at a type rather than a variable...
4392 # If we are, traditional analysis would fail...
4393 operand_as_type = self.operand.analyse_as_type(env)
4394 if operand_as_type:
4395 self.arg_type = operand_as_type
4396 self.__class__ = SizeofTypeNode
4397 self.check_type()
4398 else:
4399 self.operand.analyse_types(env)
4401 def calculate_result_code(self):
4402 return "(sizeof(%s))" % self.operand.result()
4404 def generate_result_code(self, code):
4405 pass
4407 class TypeofNode(ExprNode):
4408 # Compile-time type of an expression, as a string.
4410 # operand ExprNode
4411 # literal StringNode # internal
4413 literal = None
4414 type = py_object_type
4416 subexprs = ['literal']
4418 def analyse_types(self, env):
4419 self.operand.analyse_types(env)
4420 self.literal = StringNode(
4421 self.pos, value=StringEncoding.EncodedString(str(self.operand.type)))
4422 self.literal.analyse_types(env)
4423 self.literal = self.literal.coerce_to_pyobject(env)
4425 def generate_evaluation_code(self, code):
4426 self.literal.generate_evaluation_code(code)
4428 def calculate_result_code(self):
4429 return self.literal.calculate_result_code()
4431 #-------------------------------------------------------------------
4433 # Binary operator nodes
4435 #-------------------------------------------------------------------
4437 def _not_in(x, seq):
4438 return x not in seq
4440 compile_time_binary_operators = {
4441 '<': operator.lt,
4442 '<=': operator.le,
4443 '==': operator.eq,
4444 '!=': operator.ne,
4445 '>=': operator.ge,
4446 '>': operator.gt,
4447 'is': operator.is_,
4448 'is_not': operator.is_not,
4449 '+': operator.add,
4450 '&': operator.and_,
4451 '/': operator.truediv,
4452 '//': operator.floordiv,
4453 '<<': operator.lshift,
4454 '%': operator.mod,
4455 '*': operator.mul,
4456 '|': operator.or_,
4457 '**': operator.pow,
4458 '>>': operator.rshift,
4459 '-': operator.sub,
4460 '^': operator.xor,
4461 'in': operator.contains,
4462 'not_in': _not_in,
4465 def get_compile_time_binop(node):
4466 func = compile_time_binary_operators.get(node.operator)
4467 if not func:
4468 error(node.pos,
4469 "Binary '%s' not supported in compile-time expression"
4470 % node.operator)
4471 return func
4473 class BinopNode(ExprNode):
4474 # operator string
4475 # operand1 ExprNode
4476 # operand2 ExprNode
4478 # Processing during analyse_expressions phase:
4480 # analyse_c_operation
4481 # Called when neither operand is a pyobject.
4482 # - Check operand types and coerce if needed.
4483 # - Determine result type and result code fragment.
4484 # - Allocate temporary for result if needed.
4486 subexprs = ['operand1', 'operand2']
4488 def calculate_constant_result(self):
4489 func = compile_time_binary_operators[self.operator]
4490 self.constant_result = func(
4491 self.operand1.constant_result,
4492 self.operand2.constant_result)
4494 def compile_time_value(self, denv):
4495 func = get_compile_time_binop(self)
4496 operand1 = self.operand1.compile_time_value(denv)
4497 operand2 = self.operand2.compile_time_value(denv)
4498 try:
4499 return func(operand1, operand2)
4500 except Exception, e:
4501 self.compile_time_value_error(e)
4503 def infer_type(self, env):
4504 return self.result_type(self.operand1.infer_type(env),
4505 self.operand2.infer_type(env))
4507 def analyse_types(self, env):
4508 self.operand1.analyse_types(env)
4509 self.operand2.analyse_types(env)
4510 if self.is_py_operation():
4511 self.coerce_operands_to_pyobjects(env)
4512 self.type = py_object_type
4513 self.is_temp = 1
4514 else:
4515 self.analyse_c_operation(env)
4517 def is_py_operation(self):
4518 return self.is_py_operation_types(self.operand1.type, self.operand2.type)
4520 def is_py_operation_types(self, type1, type2):
4521 return type1.is_pyobject or type2.is_pyobject
4523 def result_type(self, type1, type2):
4524 if self.is_py_operation_types(type1, type2):
4525 return py_object_type
4526 else:
4527 return self.compute_c_result_type(type1, type2)
4529 def nogil_check(self, env):
4530 if self.is_py_operation():
4531 self.gil_error()
4533 def coerce_operands_to_pyobjects(self, env):
4534 self.operand1 = self.operand1.coerce_to_pyobject(env)
4535 self.operand2 = self.operand2.coerce_to_pyobject(env)
4537 def check_const(self):
4538 return self.operand1.check_const() and self.operand2.check_const()
4540 def generate_result_code(self, code):
4541 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4542 if self.operand1.type.is_pyobject:
4543 function = self.py_operation_function()
4544 if function == "PyNumber_Power":
4545 extra_args = ", Py_None"
4546 else:
4547 extra_args = ""
4548 code.putln(
4549 "%s = %s(%s, %s%s); %s" % (
4550 self.result(),
4551 function,
4552 self.operand1.py_result(),
4553 self.operand2.py_result(),
4554 extra_args,
4555 code.error_goto_if_null(self.result(), self.pos)))
4556 code.put_gotref(self.py_result())
4558 def type_error(self):
4559 if not (self.operand1.type.is_error
4560 or self.operand2.type.is_error):
4561 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4562 (self.operator, self.operand1.type,
4563 self.operand2.type))
4564 self.type = PyrexTypes.error_type
4567 class NumBinopNode(BinopNode):
4568 # Binary operation taking numeric arguments.
4570 infix = True
4572 def analyse_c_operation(self, env):
4573 type1 = self.operand1.type
4574 type2 = self.operand2.type
4575 self.type = self.compute_c_result_type(type1, type2)
4576 if not self.type:
4577 self.type_error()
4578 return
4579 if self.type.is_complex:
4580 self.infix = False
4581 if not self.infix:
4582 self.operand1 = self.operand1.coerce_to(self.type, env)
4583 self.operand2 = self.operand2.coerce_to(self.type, env)
4585 def compute_c_result_type(self, type1, type2):
4586 if self.c_types_okay(type1, type2):
4587 return PyrexTypes.widest_numeric_type(type1, type2)
4588 else:
4589 return None
4591 def get_constant_c_result_code(self):
4592 value1 = self.operand1.get_constant_c_result_code()
4593 value2 = self.operand2.get_constant_c_result_code()
4594 if value1 and value2:
4595 return "(%s %s %s)" % (value1, self.operator, value2)
4596 else:
4597 return None
4599 def c_types_okay(self, type1, type2):
4600 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4601 return (type1.is_numeric or type1.is_enum) \
4602 and (type2.is_numeric or type2.is_enum)
4604 def calculate_result_code(self):
4605 if self.infix:
4606 return "(%s %s %s)" % (
4607 self.operand1.result(),
4608 self.operator,
4609 self.operand2.result())
4610 else:
4611 func = self.type.binary_op(self.operator)
4612 if func is None:
4613 error(self.pos, "binary operator %s not supported for %s" % (self.operator, self.type))
4614 return "%s(%s, %s)" % (
4615 func,
4616 self.operand1.result(),
4617 self.operand2.result())
4619 def py_operation_function(self):
4620 return self.py_functions[self.operator]
4622 py_functions = {
4623 "|": "PyNumber_Or",
4624 "^": "PyNumber_Xor",
4625 "&": "PyNumber_And",
4626 "<<": "PyNumber_Lshift",
4627 ">>": "PyNumber_Rshift",
4628 "+": "PyNumber_Add",
4629 "-": "PyNumber_Subtract",
4630 "*": "PyNumber_Multiply",
4631 "/": "__Pyx_PyNumber_Divide",
4632 "//": "PyNumber_FloorDivide",
4633 "%": "PyNumber_Remainder",
4634 "**": "PyNumber_Power"
4638 class IntBinopNode(NumBinopNode):
4639 # Binary operation taking integer arguments.
4641 def c_types_okay(self, type1, type2):
4642 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4643 return (type1.is_int or type1.is_enum) \
4644 and (type2.is_int or type2.is_enum)
4647 class AddNode(NumBinopNode):
4648 # '+' operator.
4650 def is_py_operation_types(self, type1, type2):
4651 if type1.is_string and type2.is_string:
4652 return 1
4653 else:
4654 return NumBinopNode.is_py_operation_types(self, type1, type2)
4656 def compute_c_result_type(self, type1, type2):
4657 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4658 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4659 return type1
4660 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4661 return type2
4662 else:
4663 return NumBinopNode.compute_c_result_type(
4664 self, type1, type2)
4667 class SubNode(NumBinopNode):
4668 # '-' operator.
4670 def compute_c_result_type(self, type1, type2):
4671 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4672 return type1
4673 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4674 return PyrexTypes.c_int_type
4675 else:
4676 return NumBinopNode.compute_c_result_type(
4677 self, type1, type2)
4680 class MulNode(NumBinopNode):
4681 # '*' operator.
4683 def is_py_operation_types(self, type1, type2):
4684 if (type1.is_string and type2.is_int) \
4685 or (type2.is_string and type1.is_int):
4686 return 1
4687 else:
4688 return NumBinopNode.is_py_operation_types(self, type1, type2)
4691 class DivNode(NumBinopNode):
4692 # '/' or '//' operator.
4694 cdivision = None
4695 truedivision = None # == "unknown" if operator == '/'
4696 ctruedivision = False
4697 cdivision_warnings = False
4698 zerodivision_check = None
4700 def find_compile_time_binary_operator(self, op1, op2):
4701 func = compile_time_binary_operators[self.operator]
4702 if self.operator == '/' and self.truedivision is None:
4703 # => true div for floats, floor div for integers
4704 if isinstance(op1, (int,long)) and isinstance(op2, (int,long)):
4705 func = compile_time_binary_operators['//']
4706 return func
4708 def calculate_constant_result(self):
4709 op1 = self.operand1.constant_result
4710 op2 = self.operand2.constant_result
4711 func = self.find_compile_time_binary_operator(op1, op2)
4712 self.constant_result = func(
4713 self.operand1.constant_result,
4714 self.operand2.constant_result)
4716 def compile_time_value(self, denv):
4717 operand1 = self.operand1.compile_time_value(denv)
4718 operand2 = self.operand2.compile_time_value(denv)
4719 try:
4720 func = self.find_compile_time_binary_operator(
4721 self, operand1, operand2)
4722 return func(operand1, operand2)
4723 except Exception, e:
4724 self.compile_time_value_error(e)
4726 def analyse_types(self, env):
4727 if self.cdivision or env.directives['cdivision']:
4728 self.ctruedivision = False
4729 else:
4730 self.ctruedivision = self.truedivision
4731 NumBinopNode.analyse_types(self, env)
4732 if not self.type.is_pyobject:
4733 self.zerodivision_check = (
4734 self.cdivision is None and not env.directives['cdivision']
4735 and (self.operand2.constant_result is not_a_constant or
4736 self.operand2.constant_result == 0))
4737 if self.zerodivision_check or env.directives['cdivision_warnings']:
4738 # Need to check ahead of time to warn or raise zero division error
4739 self.operand1 = self.operand1.coerce_to_simple(env)
4740 self.operand2 = self.operand2.coerce_to_simple(env)
4741 if env.nogil:
4742 error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
4744 def compute_c_result_type(self, type1, type2):
4745 if self.operator == '/' and self.ctruedivision:
4746 if not type1.is_float and not type2.is_float:
4747 widest_type = PyrexTypes.widest_numeric_type(type1, PyrexTypes.c_double_type)
4748 widest_type = PyrexTypes.widest_numeric_type(type2, widest_type)
4749 return widest_type
4750 return NumBinopNode.compute_c_result_type(self, type1, type2)
4752 def zero_division_message(self):
4753 if self.type.is_int:
4754 return "integer division or modulo by zero"
4755 else:
4756 return "float division"
4758 def generate_evaluation_code(self, code):
4759 if not self.type.is_pyobject and not self.type.is_complex:
4760 if self.cdivision is None:
4761 self.cdivision = (code.globalstate.directives['cdivision']
4762 or not self.type.signed
4763 or self.type.is_float)
4764 if not self.cdivision:
4765 code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
4766 NumBinopNode.generate_evaluation_code(self, code)
4767 self.generate_div_warning_code(code)
4769 def generate_div_warning_code(self, code):
4770 if not self.type.is_pyobject:
4771 if self.zerodivision_check:
4772 if not self.infix:
4773 zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.operand2.result())
4774 else:
4775 zero_test = "%s == 0" % self.operand2.result()
4776 code.putln("if (unlikely(%s)) {" % zero_test)
4777 code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
4778 code.putln(code.error_goto(self.pos))
4779 code.putln("}")
4780 if self.type.is_int and self.type.signed and self.operator != '%':
4781 code.globalstate.use_utility_code(division_overflow_test_code)
4782 code.putln("else if (sizeof(%s) == sizeof(long) && unlikely(%s == -1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % (
4783 self.type.declaration_code(''),
4784 self.operand2.result(),
4785 self.operand1.result()))
4786 code.putln('PyErr_Format(PyExc_OverflowError, "value too large to perform division");')
4787 code.putln(code.error_goto(self.pos))
4788 code.putln("}")
4789 if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
4790 code.globalstate.use_utility_code(cdivision_warning_utility_code)
4791 code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
4792 self.operand1.result(),
4793 self.operand2.result()))
4794 code.putln(code.set_error_info(self.pos));
4795 code.put("if (__Pyx_cdivision_warning()) ")
4796 code.put_goto(code.error_label)
4797 code.putln("}")
4799 def calculate_result_code(self):
4800 if self.type.is_complex:
4801 return NumBinopNode.calculate_result_code(self)
4802 elif self.type.is_float and self.operator == '//':
4803 return "floor(%s / %s)" % (
4804 self.operand1.result(),
4805 self.operand2.result())
4806 elif self.truedivision or self.cdivision:
4807 op1 = self.operand1.result()
4808 op2 = self.operand2.result()
4809 if self.truedivision:
4810 if self.type != self.operand1.type:
4811 op1 = self.type.cast_code(op1)
4812 if self.type != self.operand2.type:
4813 op2 = self.type.cast_code(op2)
4814 return "(%s / %s)" % (op1, op2)
4815 else:
4816 return "__Pyx_div_%s(%s, %s)" % (
4817 self.type.specalization_name(),
4818 self.operand1.result(),
4819 self.operand2.result())
4822 class ModNode(DivNode):
4823 # '%' operator.
4825 def is_py_operation_types(self, type1, type2):
4826 return (type1.is_string
4827 or type2.is_string
4828 or NumBinopNode.is_py_operation_types(self, type1, type2))
4830 def zero_division_message(self):
4831 if self.type.is_int:
4832 return "integer division or modulo by zero"
4833 else:
4834 return "float divmod()"
4836 def generate_evaluation_code(self, code):
4837 if not self.type.is_pyobject:
4838 if self.cdivision is None:
4839 self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
4840 if not self.cdivision:
4841 if self.type.is_int:
4842 code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
4843 else:
4844 code.globalstate.use_utility_code(
4845 mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
4846 NumBinopNode.generate_evaluation_code(self, code)
4847 self.generate_div_warning_code(code)
4849 def calculate_result_code(self):
4850 if self.cdivision:
4851 if self.type.is_float:
4852 return "fmod%s(%s, %s)" % (
4853 self.type.math_h_modifier,
4854 self.operand1.result(),
4855 self.operand2.result())
4856 else:
4857 return "(%s %% %s)" % (
4858 self.operand1.result(),
4859 self.operand2.result())
4860 else:
4861 return "__Pyx_mod_%s(%s, %s)" % (
4862 self.type.specalization_name(),
4863 self.operand1.result(),
4864 self.operand2.result())
4866 class PowNode(NumBinopNode):
4867 # '**' operator.
4869 def analyse_c_operation(self, env):
4870 NumBinopNode.analyse_c_operation(self, env)
4871 if self.type.is_complex:
4872 error(self.pos, "complex powers not yet supported")
4873 self.pow_func = "<error>"
4874 elif self.type.is_float:
4875 self.pow_func = "pow"
4876 else:
4877 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
4878 env.use_utility_code(
4879 int_pow_utility_code.specialize(func_name=self.pow_func,
4880 type=self.type.declaration_code('')))
4882 def calculate_result_code(self):
4883 return "%s(%s, %s)" % (
4884 self.pow_func,
4885 self.operand1.result(),
4886 self.operand2.result())
4889 # Note: This class is temporary "shut down" into an ineffective mode temp
4890 # allocation mode.
4892 # More sophisticated temp reuse was going on before,
4893 # one could have a look at adding this again after /all/ classes
4894 # are converted to the new temp scheme. (The temp juggling cannot work
4895 # otherwise).
4896 class BoolBinopNode(ExprNode):
4897 # Short-circuiting boolean operation.
4899 # operator string
4900 # operand1 ExprNode
4901 # operand2 ExprNode
4903 subexprs = ['operand1', 'operand2']
4905 def infer_type(self, env):
4906 type1 = self.operand1.infer_type(env)
4907 type2 = self.operand2.infer_type(env)
4908 return PyrexTypes.spanning_type(type1, type2)
4910 def calculate_constant_result(self):
4911 if self.operator == 'and':
4912 self.constant_result = \
4913 self.operand1.constant_result and \
4914 self.operand2.constant_result
4915 else:
4916 self.constant_result = \
4917 self.operand1.constant_result or \
4918 self.operand2.constant_result
4920 def compile_time_value(self, denv):
4921 if self.operator == 'and':
4922 return self.operand1.compile_time_value(denv) \
4923 and self.operand2.compile_time_value(denv)
4924 else:
4925 return self.operand1.compile_time_value(denv) \
4926 or self.operand2.compile_time_value(denv)
4928 def coerce_to_boolean(self, env):
4929 self.operand1 = self.operand1.coerce_to_boolean(env)
4930 self.operand2 = self.operand2.coerce_to_boolean(env)
4931 self.type = PyrexTypes.c_bint_type
4932 return self
4934 def analyse_types(self, env):
4935 self.operand1.analyse_types(env)
4936 self.operand2.analyse_types(env)
4937 self.type = PyrexTypes.spanning_type(self.operand1.type, self.operand2.type)
4938 self.operand1 = self.operand1.coerce_to(self.type, env)
4939 self.operand2 = self.operand2.coerce_to(self.type, env)
4941 # For what we're about to do, it's vital that
4942 # both operands be temp nodes.
4943 self.operand1 = self.operand1.coerce_to_simple(env)
4944 self.operand2 = self.operand2.coerce_to_simple(env)
4945 self.is_temp = 1
4947 gil_message = "Truth-testing Python object"
4949 def check_const(self):
4950 return self.operand1.check_const() and self.operand2.check_const()
4952 def generate_evaluation_code(self, code):
4953 code.mark_pos(self.pos)
4954 self.operand1.generate_evaluation_code(code)
4955 test_result, uses_temp = self.generate_operand1_test(code)
4956 if self.operator == 'and':
4957 sense = ""
4958 else:
4959 sense = "!"
4960 code.putln(
4961 "if (%s%s) {" % (
4962 sense,
4963 test_result))
4964 if uses_temp:
4965 code.funcstate.release_temp(test_result)
4966 self.operand1.generate_disposal_code(code)
4967 self.operand2.generate_evaluation_code(code)
4968 self.allocate_temp_result(code)
4969 self.operand2.make_owned_reference(code)
4970 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
4971 self.operand2.generate_post_assignment_code(code)
4972 self.operand2.free_temps(code)
4973 code.putln("} else {")
4974 self.operand1.make_owned_reference(code)
4975 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
4976 self.operand1.generate_post_assignment_code(code)
4977 self.operand1.free_temps(code)
4978 code.putln("}")
4980 def generate_operand1_test(self, code):
4981 # Generate code to test the truth of the first operand.
4982 if self.type.is_pyobject:
4983 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
4984 manage_ref=False)
4985 code.putln(
4986 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4987 test_result,
4988 self.operand1.py_result(),
4989 code.error_goto_if_neg(test_result, self.pos)))
4990 else:
4991 test_result = self.operand1.result()
4992 return (test_result, self.type.is_pyobject)
4995 class CondExprNode(ExprNode):
4996 # Short-circuiting conditional expression.
4998 # test ExprNode
4999 # true_val ExprNode
5000 # false_val ExprNode
5002 true_val = None
5003 false_val = None
5005 subexprs = ['test', 'true_val', 'false_val']
5007 def type_dependencies(self, env):
5008 return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
5010 def infer_type(self, env):
5011 return self.compute_result_type(self.true_val.infer_type(env),
5012 self.false_val.infer_type(env))
5014 def calculate_constant_result(self):
5015 if self.test.constant_result:
5016 self.constant_result = self.true_val.constant_result
5017 else:
5018 self.constant_result = self.false_val.constant_result
5020 def analyse_types(self, env):
5021 self.test.analyse_types(env)
5022 self.test = self.test.coerce_to_boolean(env)
5023 self.true_val.analyse_types(env)
5024 self.false_val.analyse_types(env)
5025 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
5026 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
5027 self.true_val = self.true_val.coerce_to(self.type, env)
5028 self.false_val = self.false_val.coerce_to(self.type, env)
5029 self.is_temp = 1
5030 if self.type == PyrexTypes.error_type:
5031 self.type_error()
5033 def compute_result_type(self, type1, type2):
5034 if type1 == type2:
5035 return type1
5036 elif type1.is_numeric and type2.is_numeric:
5037 return PyrexTypes.widest_numeric_type(type1, type2)
5038 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
5039 return type2
5040 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
5041 return type1
5042 elif type1.is_pyobject or type2.is_pyobject:
5043 return py_object_type
5044 elif type1.assignable_from(type2):
5045 return type1
5046 elif type2.assignable_from(type1):
5047 return type2
5048 else:
5049 return PyrexTypes.error_type
5051 def type_error(self):
5052 if not (self.true_val.type.is_error or self.false_val.type.is_error):
5053 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
5054 (self.true_val.type, self.false_val.type))
5055 self.type = PyrexTypes.error_type
5057 def check_const(self):
5058 return (self.test.check_const()
5059 and self.true_val.check_const()
5060 and self.false_val.check_const())
5062 def generate_evaluation_code(self, code):
5063 # Because subexprs may not be evaluated we can use a more optimal
5064 # subexpr allocation strategy than the default, so override evaluation_code.
5066 code.mark_pos(self.pos)
5067 self.allocate_temp_result(code)
5068 self.test.generate_evaluation_code(code)
5069 code.putln("if (%s) {" % self.test.result() )
5070 self.eval_and_get(code, self.true_val)
5071 code.putln("} else {")
5072 self.eval_and_get(code, self.false_val)
5073 code.putln("}")
5074 self.test.generate_disposal_code(code)
5075 self.test.free_temps(code)
5077 def eval_and_get(self, code, expr):
5078 expr.generate_evaluation_code(code)
5079 expr.make_owned_reference(code)
5080 code.putln("%s = %s;" % (self.result(), expr.result()))
5081 expr.generate_post_assignment_code(code)
5082 expr.free_temps(code)
5084 richcmp_constants = {
5085 "<" : "Py_LT",
5086 "<=": "Py_LE",
5087 "==": "Py_EQ",
5088 "!=": "Py_NE",
5089 "<>": "Py_NE",
5090 ">" : "Py_GT",
5091 ">=": "Py_GE",
5094 class CmpNode(object):
5095 # Mixin class containing code common to PrimaryCmpNodes
5096 # and CascadedCmpNodes.
5098 def infer_types(self, env):
5099 # TODO: Actually implement this (after merging with -unstable).
5100 return py_object_type
5102 def calculate_cascaded_constant_result(self, operand1_result):
5103 func = compile_time_binary_operators[self.operator]
5104 operand2_result = self.operand2.constant_result
5105 result = func(operand1_result, operand2_result)
5106 if result and self.cascade:
5107 result = result and \
5108 self.cascade.cascaded_compile_time_value(operand2_result)
5109 self.constant_result = result
5111 def cascaded_compile_time_value(self, operand1, denv):
5112 func = get_compile_time_binop(self)
5113 operand2 = self.operand2.compile_time_value(denv)
5114 try:
5115 result = func(operand1, operand2)
5116 except Exception, e:
5117 self.compile_time_value_error(e)
5118 result = None
5119 if result:
5120 cascade = self.cascade
5121 if cascade:
5122 # FIXME: I bet this must call cascaded_compile_time_value()
5123 result = result and cascade.compile_time_value(operand2, denv)
5124 return result
5126 def find_common_int_type(self, env, op, operand1, operand2):
5127 # type1 != type2 and at least one of the types is not a C int
5128 type1 = operand1.type
5129 type2 = operand2.type
5130 type1_can_be_int = False
5131 type2_can_be_int = False
5133 if isinstance(operand1, (StringNode, BytesNode)) \
5134 and operand1.can_coerce_to_char_literal():
5135 type1_can_be_int = True
5136 if isinstance(operand2, (StringNode, BytesNode)) \
5137 and operand2.can_coerce_to_char_literal():
5138 type2_can_be_int = True
5140 if type1.is_int:
5141 if type2_can_be_int:
5142 return type1
5143 elif type2.is_int:
5144 if type1_can_be_int:
5145 return type2
5146 elif type1_can_be_int:
5147 if type2_can_be_int:
5148 return PyrexTypes.c_uchar_type
5150 return None
5152 def find_common_type(self, env, op, operand1, common_type=None):
5153 operand2 = self.operand2
5154 type1 = operand1.type
5155 type2 = operand2.type
5157 new_common_type = None
5159 # catch general errors
5160 if type1 == str_type and (type2.is_string or type2 in (bytes_type, unicode_type)) or \
5161 type2 == str_type and (type1.is_string or type1 in (bytes_type, unicode_type)):
5162 error(self.pos, "Comparisons between bytes/unicode and str are not portable to Python 3")
5163 new_common_type = error_type
5165 # try to use numeric comparisons where possible
5166 elif type1.is_complex or type2.is_complex:
5167 if op not in ('==', '!='):
5168 error(self.pos, "complex types are unordered")
5169 new_common_type = error_type
5170 if type1.is_pyobject:
5171 new_common_type = type1
5172 elif type2.is_pyobject:
5173 new_common_type = type2
5174 else:
5175 new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
5176 elif type1.is_numeric and type2.is_numeric:
5177 new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
5178 elif common_type is None or not common_type.is_pyobject:
5179 new_common_type = self.find_common_int_type(env, op, operand1, operand2)
5181 if new_common_type is None:
5182 # fall back to generic type compatibility tests
5183 if type1 == type2:
5184 new_common_type = type1
5185 elif type1.is_pyobject or type2.is_pyobject:
5186 if type2.is_numeric or type2.is_string:
5187 if operand2.check_for_coercion_error(type1):
5188 new_common_type = error_type
5189 else:
5190 new_common_type = py_object_type
5191 elif type1.is_numeric or type1.is_string:
5192 if operand1.check_for_coercion_error(type2):
5193 new_common_type = error_type
5194 else:
5195 new_common_type = py_object_type
5196 elif py_object_type.assignable_from(type1) and py_object_type.assignable_from(type2):
5197 new_common_type = py_object_type
5198 else:
5199 # one Python type and one non-Python type, not assignable
5200 self.invalid_types_error(operand1, op, operand2)
5201 new_common_type = error_type
5202 elif type1.assignable_from(type2):
5203 new_common_type = type1
5204 elif type2.assignable_from(type1):
5205 new_common_type = type2
5206 else:
5207 # C types that we couldn't handle up to here are an error
5208 self.invalid_types_error(operand1, op, operand2)
5209 new_common_type = error_type
5211 # recursively merge types
5212 if common_type is None or new_common_type.is_error:
5213 common_type = new_common_type
5214 else:
5215 # we could do a lot better by splitting the comparison
5216 # into a non-Python part and a Python part, but this is
5217 # safer for now
5218 common_type = PyrexTypes.spanning_type(common_type, new_common_type)
5220 if self.cascade:
5221 common_type = self.cascade.find_common_type(env, self.operator, operand2, common_type)
5223 return common_type
5225 def invalid_types_error(self, operand1, op, operand2):
5226 error(self.pos, "Invalid types for '%s' (%s, %s)" %
5227 (op, operand1.type, operand2.type))
5229 def is_python_comparison(self):
5230 return (self.has_python_operands()
5231 or (self.cascade and self.cascade.is_python_comparison())
5232 or self.operator in ('in', 'not_in'))
5234 def coerce_operands_to(self, dst_type, env):
5235 operand2 = self.operand2
5236 if operand2.type != dst_type:
5237 self.operand2 = operand2.coerce_to(dst_type, env)
5238 if self.cascade:
5239 self.cascade.coerce_operands_to(dst_type, env)
5241 def is_python_result(self):
5242 return ((self.has_python_operands() and
5243 self.operator not in ('is', 'is_not', 'in', 'not_in'))
5244 or (self.cascade and self.cascade.is_python_result()))
5246 def generate_operation_code(self, code, result_code,
5247 operand1, op , operand2):
5248 if self.type is PyrexTypes.py_object_type:
5249 coerce_result = "__Pyx_PyBool_FromLong"
5250 else:
5251 coerce_result = ""
5252 if 'not' in op:
5253 negation = "!"
5254 else:
5255 negation = ""
5256 if op == 'in' or op == 'not_in':
5257 code.globalstate.use_utility_code(contians_utility_code)
5258 if self.type is PyrexTypes.py_object_type:
5259 coerce_result = "__Pyx_PyBoolOrNull_FromLong"
5260 if op == 'not_in':
5261 negation = "__Pyx_NegateNonNeg"
5262 if operand2.type is dict_type:
5263 code.globalstate.use_utility_code(
5264 raise_none_iter_error_utility_code)
5265 code.putln("if (unlikely(%s == Py_None)) {" % operand2.py_result())
5266 code.putln("__Pyx_RaiseNoneNotIterableError(); %s" %
5267 code.error_goto(self.pos))
5268 code.putln("} else {")
5269 method = "PyDict_Contains"
5270 else:
5271 method = "PySequence_Contains"
5272 if self.type is PyrexTypes.py_object_type:
5273 error_clause = code.error_goto_if_null
5274 got_ref = "__Pyx_XGOTREF(%s); " % result_code
5275 else:
5276 error_clause = code.error_goto_if_neg
5277 got_ref = ""
5278 code.putln(
5279 "%s = %s(%s(%s(%s, %s))); %s%s" % (
5280 result_code,
5281 coerce_result,
5282 negation,
5283 method,
5284 operand2.py_result(),
5285 operand1.py_result(),
5286 got_ref,
5287 error_clause(result_code, self.pos)))
5288 if operand2.type is dict_type:
5289 code.putln("}")
5291 elif (operand1.type.is_pyobject
5292 and op not in ('is', 'is_not')):
5293 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
5294 result_code,
5295 operand1.py_result(),
5296 operand2.py_result(),
5297 richcmp_constants[op],
5298 code.error_goto_if_null(result_code, self.pos)))
5299 code.put_gotref(result_code)
5300 elif operand1.type.is_complex:
5301 if op == "!=":
5302 negation = "!"
5303 else:
5304 negation = ""
5305 code.putln("%s = %s(%s%s(%s, %s));" % (
5306 result_code,
5307 coerce_result,
5308 negation,
5309 operand1.type.unary_op('eq'),
5310 operand1.result(),
5311 operand2.result()))
5312 else:
5313 type1 = operand1.type
5314 type2 = operand2.type
5315 if (type1.is_extension_type or type2.is_extension_type) \
5316 and not type1.same_as(type2):
5317 common_type = py_object_type
5318 elif type1.is_numeric:
5319 common_type = PyrexTypes.widest_numeric_type(type1, type2)
5320 else:
5321 common_type = type1
5322 code1 = operand1.result_as(common_type)
5323 code2 = operand2.result_as(common_type)
5324 code.putln("%s = %s(%s %s %s);" % (
5325 result_code,
5326 coerce_result,
5327 code1,
5328 self.c_operator(op),
5329 code2))
5331 def c_operator(self, op):
5332 if op == 'is':
5333 return "=="
5334 elif op == 'is_not':
5335 return "!="
5336 else:
5337 return op
5339 contians_utility_code = UtilityCode(
5340 proto="""
5341 static INLINE long __Pyx_NegateNonNeg(long b) { return unlikely(b < 0) ? b : !b; }
5342 static INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
5343 return unlikely(b < 0) ? NULL : __Pyx_PyBool_FromLong(b);
5345 """)
5348 class PrimaryCmpNode(ExprNode, CmpNode):
5349 # Non-cascaded comparison or first comparison of
5350 # a cascaded sequence.
5352 # operator string
5353 # operand1 ExprNode
5354 # operand2 ExprNode
5355 # cascade CascadedCmpNode
5357 # We don't use the subexprs mechanism, because
5358 # things here are too complicated for it to handle.
5359 # Instead, we override all the framework methods
5360 # which use it.
5362 child_attrs = ['operand1', 'operand2', 'cascade']
5364 cascade = None
5366 def infer_type(self, env):
5367 # TODO: Actually implement this (after merging with -unstable).
5368 return py_object_type
5370 def type_dependencies(self, env):
5371 return ()
5373 def calculate_constant_result(self):
5374 self.constant_result = self.calculate_cascaded_constant_result(
5375 self.operand1.constant_result)
5377 def compile_time_value(self, denv):
5378 operand1 = self.operand1.compile_time_value(denv)
5379 return self.cascaded_compile_time_value(operand1, denv)
5381 def analyse_types(self, env):
5382 self.operand1.analyse_types(env)
5383 self.operand2.analyse_types(env)
5384 if self.cascade:
5385 self.cascade.analyse_types(env)
5387 if self.operator in ('in', 'not_in'):
5388 common_type = py_object_type
5389 self.is_pycmp = True
5390 else:
5391 common_type = self.find_common_type(env, self.operator, self.operand1)
5392 self.is_pycmp = common_type.is_pyobject
5394 if not common_type.is_error:
5395 if self.operand1.type != common_type:
5396 self.operand1 = self.operand1.coerce_to(common_type, env)
5397 self.coerce_operands_to(common_type, env)
5399 if self.cascade:
5400 self.operand2 = self.operand2.coerce_to_simple(env)
5401 self.cascade.coerce_cascaded_operands_to_temp(env)
5402 if self.is_python_result():
5403 self.type = PyrexTypes.py_object_type
5404 else:
5405 self.type = PyrexTypes.c_bint_type
5406 cdr = self.cascade
5407 while cdr:
5408 cdr.type = self.type
5409 cdr = cdr.cascade
5410 if self.is_pycmp or self.cascade:
5411 self.is_temp = 1
5413 def has_python_operands(self):
5414 return (self.operand1.type.is_pyobject
5415 or self.operand2.type.is_pyobject)
5417 def check_const(self):
5418 if self.cascade:
5419 self.not_const()
5420 return False
5421 else:
5422 return self.operand1.check_const() and self.operand2.check_const()
5424 def calculate_result_code(self):
5425 if self.operand1.type.is_complex:
5426 if self.operator == "!=":
5427 negation = "!"
5428 else:
5429 negation = ""
5430 return "(%s%s(%s, %s))" % (
5431 negation,
5432 self.operand1.type.binary_op('=='),
5433 self.operand1.result(),
5434 self.operand2.result())
5435 else:
5436 return "(%s %s %s)" % (
5437 self.operand1.result(),
5438 self.c_operator(self.operator),
5439 self.operand2.result())
5441 def generate_evaluation_code(self, code):
5442 self.operand1.generate_evaluation_code(code)
5443 self.operand2.generate_evaluation_code(code)
5444 if self.is_temp:
5445 self.allocate_temp_result(code)
5446 self.generate_operation_code(code, self.result(),
5447 self.operand1, self.operator, self.operand2)
5448 if self.cascade:
5449 self.cascade.generate_evaluation_code(code,
5450 self.result(), self.operand2)
5451 self.operand1.generate_disposal_code(code)
5452 self.operand1.free_temps(code)
5453 self.operand2.generate_disposal_code(code)
5454 self.operand2.free_temps(code)
5456 def generate_subexpr_disposal_code(self, code):
5457 # If this is called, it is a non-cascaded cmp,
5458 # so only need to dispose of the two main operands.
5459 self.operand1.generate_disposal_code(code)
5460 self.operand2.generate_disposal_code(code)
5462 def free_subexpr_temps(self, code):
5463 # If this is called, it is a non-cascaded cmp,
5464 # so only need to dispose of the two main operands.
5465 self.operand1.free_temps(code)
5466 self.operand2.free_temps(code)
5468 def annotate(self, code):
5469 self.operand1.annotate(code)
5470 self.operand2.annotate(code)
5471 if self.cascade:
5472 self.cascade.annotate(code)
5475 class CascadedCmpNode(Node, CmpNode):
5476 # A CascadedCmpNode is not a complete expression node. It
5477 # hangs off the side of another comparison node, shares
5478 # its left operand with that node, and shares its result
5479 # with the PrimaryCmpNode at the head of the chain.
5481 # operator string
5482 # operand2 ExprNode
5483 # cascade CascadedCmpNode
5485 child_attrs = ['operand2', 'cascade']
5487 cascade = None
5488 constant_result = constant_value_not_set # FIXME: where to calculate this?
5490 def infer_type(self, env):
5491 # TODO: Actually implement this (after merging with -unstable).
5492 return py_object_type
5494 def type_dependencies(self, env):
5495 return ()
5497 def analyse_types(self, env):
5498 self.operand2.analyse_types(env)
5499 if self.cascade:
5500 self.cascade.analyse_types(env)
5502 def has_python_operands(self):
5503 return self.operand2.type.is_pyobject
5505 def coerce_operands_to_pyobjects(self, env):
5506 self.operand2 = self.operand2.coerce_to_pyobject(env)
5507 if self.cascade:
5508 self.cascade.coerce_operands_to_pyobjects(env)
5510 def coerce_cascaded_operands_to_temp(self, env):
5511 if self.cascade:
5512 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
5513 self.operand2 = self.operand2.coerce_to_simple(env)
5514 self.cascade.coerce_cascaded_operands_to_temp(env)
5516 def generate_evaluation_code(self, code, result, operand1):
5517 if self.type.is_pyobject:
5518 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
5519 code.put_decref(result, self.type)
5520 else:
5521 code.putln("if (%s) {" % result)
5522 self.operand2.generate_evaluation_code(code)
5523 self.generate_operation_code(code, result,
5524 operand1, self.operator, self.operand2)
5525 if self.cascade:
5526 self.cascade.generate_evaluation_code(
5527 code, result, self.operand2)
5528 # Cascaded cmp result is always temp
5529 self.operand2.generate_disposal_code(code)
5530 self.operand2.free_temps(code)
5531 code.putln("}")
5533 def annotate(self, code):
5534 self.operand2.annotate(code)
5535 if self.cascade:
5536 self.cascade.annotate(code)
5539 binop_node_classes = {
5540 "or": BoolBinopNode,
5541 "and": BoolBinopNode,
5542 "|": IntBinopNode,
5543 "^": IntBinopNode,
5544 "&": IntBinopNode,
5545 "<<": IntBinopNode,
5546 ">>": IntBinopNode,
5547 "+": AddNode,
5548 "-": SubNode,
5549 "*": MulNode,
5550 "/": DivNode,
5551 "//": DivNode,
5552 "%": ModNode,
5553 "**": PowNode
5556 def binop_node(pos, operator, operand1, operand2):
5557 # Construct binop node of appropriate class for
5558 # given operator.
5559 return binop_node_classes[operator](pos,
5560 operator = operator,
5561 operand1 = operand1,
5562 operand2 = operand2)
5564 #-------------------------------------------------------------------
5566 # Coercion nodes
5568 # Coercion nodes are special in that they are created during
5569 # the analyse_types phase of parse tree processing.
5570 # Their __init__ methods consequently incorporate some aspects
5571 # of that phase.
5573 #-------------------------------------------------------------------
5575 class CoercionNode(ExprNode):
5576 # Abstract base class for coercion nodes.
5578 # arg ExprNode node being coerced
5580 subexprs = ['arg']
5581 constant_result = not_a_constant
5583 def __init__(self, arg):
5584 self.pos = arg.pos
5585 self.arg = arg
5586 if debug_coercion:
5587 print("%s Coercing %s" % (self, self.arg))
5589 def calculate_constant_result(self):
5590 # constant folding can break type coercion, so this is disabled
5591 pass
5593 def annotate(self, code):
5594 self.arg.annotate(code)
5595 if self.arg.type != self.type:
5596 file, line, col = self.pos
5597 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
5600 class CastNode(CoercionNode):
5601 # Wrap a node in a C type cast.
5603 def __init__(self, arg, new_type):
5604 CoercionNode.__init__(self, arg)
5605 self.type = new_type
5607 def calculate_result_code(self):
5608 return self.arg.result_as(self.type)
5610 def generate_result_code(self, code):
5611 self.arg.generate_result_code(code)
5614 class PyTypeTestNode(CoercionNode):
5615 # This node is used to check that a generic Python
5616 # object is an instance of a particular extension type.
5617 # This node borrows the result of its argument node.
5619 def __init__(self, arg, dst_type, env, notnone=False):
5620 # The arg is know to be a Python object, and
5621 # the dst_type is known to be an extension type.
5622 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
5623 CoercionNode.__init__(self, arg)
5624 self.type = dst_type
5625 self.result_ctype = arg.ctype()
5626 self.notnone = notnone
5628 nogil_check = Node.gil_error
5629 gil_message = "Python type test"
5631 def analyse_types(self, env):
5632 pass
5634 def result_in_temp(self):
5635 return self.arg.result_in_temp()
5637 def is_ephemeral(self):
5638 return self.arg.is_ephemeral()
5640 def calculate_constant_result(self):
5641 # FIXME
5642 pass
5644 def calculate_result_code(self):
5645 return self.arg.result()
5647 def generate_result_code(self, code):
5648 if self.type.typeobj_is_available():
5649 if not self.type.is_builtin_type:
5650 code.globalstate.use_utility_code(type_test_utility_code)
5651 code.putln(
5652 "if (!(%s)) %s" % (
5653 self.type.type_test_code(self.arg.py_result(), self.notnone),
5654 code.error_goto(self.pos)))
5655 else:
5656 error(self.pos, "Cannot test type of extern C class "
5657 "without type object name specification")
5659 def generate_post_assignment_code(self, code):
5660 self.arg.generate_post_assignment_code(code)
5662 def free_temps(self, code):
5663 self.arg.free_temps(code)
5666 class NoneCheckNode(CoercionNode):
5667 # This node is used to check that a Python object is not None and
5668 # raises an appropriate exception (as specified by the creating
5669 # transform).
5671 def __init__(self, arg, exception_type_cname, exception_message):
5672 CoercionNode.__init__(self, arg)
5673 self.type = arg.type
5674 self.result_ctype = arg.ctype()
5675 self.exception_type_cname = exception_type_cname
5676 self.exception_message = exception_message
5678 def analyse_types(self, env):
5679 pass
5681 def result_in_temp(self):
5682 return self.arg.result_in_temp()
5684 def calculate_result_code(self):
5685 return self.arg.result()
5687 def generate_result_code(self, code):
5688 code.putln(
5689 "if (unlikely(%s == Py_None)) {" % self.arg.result())
5690 code.putln('PyErr_SetString(%s, "%s"); %s ' % (
5691 self.exception_type_cname,
5692 StringEncoding.escape_byte_string(
5693 self.exception_message.encode('UTF-8')),
5694 code.error_goto(self.pos)))
5695 code.putln("}")
5697 def generate_post_assignment_code(self, code):
5698 self.arg.generate_post_assignment_code(code)
5700 def free_temps(self, code):
5701 self.arg.free_temps(code)
5704 class CoerceToPyTypeNode(CoercionNode):
5705 # This node is used to convert a C data type
5706 # to a Python object.
5708 type = py_object_type
5709 is_temp = 1
5711 def __init__(self, arg, env, type=py_object_type):
5712 CoercionNode.__init__(self, arg)
5713 if not arg.type.create_to_py_utility_code(env):
5714 error(arg.pos,
5715 "Cannot convert '%s' to Python object" % arg.type)
5716 if type is not py_object_type:
5717 self.type = py_object_type
5718 elif arg.type.is_string:
5719 self.type = Builtin.bytes_type
5721 gil_message = "Converting to Python object"
5723 def coerce_to_boolean(self, env):
5724 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
5726 def coerce_to_integer(self, env):
5727 # If not already some C integer type, coerce to longint.
5728 if self.arg.type.is_int:
5729 return self.arg
5730 else:
5731 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
5733 def analyse_types(self, env):
5734 # The arg is always already analysed
5735 pass
5737 def generate_result_code(self, code):
5738 function = self.arg.type.to_py_function
5739 code.putln('%s = %s(%s); %s' % (
5740 self.result(),
5741 function,
5742 self.arg.result(),
5743 code.error_goto_if_null(self.result(), self.pos)))
5744 code.put_gotref(self.py_result())
5747 class CoerceFromPyTypeNode(CoercionNode):
5748 # This node is used to convert a Python object
5749 # to a C data type.
5751 def __init__(self, result_type, arg, env):
5752 CoercionNode.__init__(self, arg)
5753 self.type = result_type
5754 self.is_temp = 1
5755 if not result_type.create_from_py_utility_code(env):
5756 error(arg.pos,
5757 "Cannot convert Python object to '%s'" % result_type)
5758 if self.type.is_string and self.arg.is_ephemeral():
5759 error(arg.pos,
5760 "Obtaining char * from temporary Python value")
5762 def analyse_types(self, env):
5763 # The arg is always already analysed
5764 pass
5766 def generate_result_code(self, code):
5767 function = self.type.from_py_function
5768 operand = self.arg.py_result()
5769 rhs = "%s(%s)" % (function, operand)
5770 if self.type.is_enum:
5771 rhs = typecast(self.type, c_long_type, rhs)
5772 code.putln('%s = %s; %s' % (
5773 self.result(),
5774 rhs,
5775 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
5776 if self.type.is_pyobject:
5777 code.put_gotref(self.py_result())
5780 class CoerceToBooleanNode(CoercionNode):
5781 # This node is used when a result needs to be used
5782 # in a boolean context.
5784 type = PyrexTypes.c_bint_type
5786 def __init__(self, arg, env):
5787 CoercionNode.__init__(self, arg)
5788 if arg.type.is_pyobject:
5789 self.is_temp = 1
5791 def nogil_check(self, env):
5792 if self.arg.type.is_pyobject:
5793 self.gil_error()
5795 gil_message = "Truth-testing Python object"
5797 def check_const(self):
5798 if self.is_temp:
5799 self.not_const()
5800 return False
5801 return self.arg.check_const()
5803 def calculate_result_code(self):
5804 return "(%s != 0)" % self.arg.result()
5806 def generate_result_code(self, code):
5807 if self.arg.type.is_pyobject:
5808 code.putln(
5809 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5810 self.result(),
5811 self.arg.py_result(),
5812 code.error_goto_if_neg(self.result(), self.pos)))
5814 class CoerceToComplexNode(CoercionNode):
5816 def __init__(self, arg, dst_type, env):
5817 if arg.type.is_complex:
5818 arg = arg.coerce_to_simple(env)
5819 self.type = dst_type
5820 CoercionNode.__init__(self, arg)
5821 dst_type.create_declaration_utility_code(env)
5823 def calculate_result_code(self):
5824 if self.arg.type.is_complex:
5825 real_part = "__Pyx_CREAL(%s)" % self.arg.result()
5826 imag_part = "__Pyx_CIMAG(%s)" % self.arg.result()
5827 else:
5828 real_part = self.arg.result()
5829 imag_part = "0"
5830 return "%s(%s, %s)" % (
5831 self.type.from_parts,
5832 real_part,
5833 imag_part)
5835 def generate_result_code(self, code):
5836 pass
5838 class CoerceToTempNode(CoercionNode):
5839 # This node is used to force the result of another node
5840 # to be stored in a temporary. It is only used if the
5841 # argument node's result is not already in a temporary.
5843 def __init__(self, arg, env):
5844 CoercionNode.__init__(self, arg)
5845 self.type = self.arg.type
5846 self.is_temp = 1
5847 if self.type.is_pyobject:
5848 self.result_ctype = py_object_type
5850 gil_message = "Creating temporary Python reference"
5852 def analyse_types(self, env):
5853 # The arg is always already analysed
5854 pass
5856 def coerce_to_boolean(self, env):
5857 self.arg = self.arg.coerce_to_boolean(env)
5858 self.type = self.arg.type
5859 self.result_ctype = self.type
5860 return self
5862 def generate_result_code(self, code):
5863 #self.arg.generate_evaluation_code(code) # Already done
5864 # by generic generate_subexpr_evaluation_code!
5865 code.putln("%s = %s;" % (
5866 self.result(), self.arg.result_as(self.ctype())))
5867 if self.type.is_pyobject and self.use_managed_ref:
5868 code.put_incref(self.result(), self.ctype())
5871 class CloneNode(CoercionNode):
5872 # This node is employed when the result of another node needs
5873 # to be used multiple times. The argument node's result must
5874 # be in a temporary. This node "borrows" the result from the
5875 # argument node, and does not generate any evaluation or
5876 # disposal code for it. The original owner of the argument
5877 # node is responsible for doing those things.
5879 subexprs = [] # Arg is not considered a subexpr
5880 nogil_check = None
5882 def __init__(self, arg):
5883 CoercionNode.__init__(self, arg)
5884 if hasattr(arg, 'type'):
5885 self.type = arg.type
5886 self.result_ctype = arg.result_ctype
5887 if hasattr(arg, 'entry'):
5888 self.entry = arg.entry
5890 def result(self):
5891 return self.arg.result()
5893 def type_dependencies(self, env):
5894 return self.arg.type_dependencies(env)
5896 def infer_type(self, env):
5897 return self.arg.infer_type(env)
5899 def analyse_types(self, env):
5900 self.type = self.arg.type
5901 self.result_ctype = self.arg.result_ctype
5902 self.is_temp = 1
5903 if hasattr(self.arg, 'entry'):
5904 self.entry = self.arg.entry
5906 def generate_evaluation_code(self, code):
5907 pass
5909 def generate_result_code(self, code):
5910 pass
5912 def generate_disposal_code(self, code):
5913 pass
5915 def free_temps(self, code):
5916 pass
5919 class ModuleRefNode(ExprNode):
5920 # Simple returns the module object
5922 type = py_object_type
5923 is_temp = False
5924 subexprs = []
5926 def analyse_types(self, env):
5927 pass
5929 def calculate_result_code(self):
5930 return Naming.module_cname
5932 def generate_result_code(self, code):
5933 pass
5935 class DocstringRefNode(ExprNode):
5936 # Extracts the docstring of the body element
5938 subexprs = ['body']
5939 type = py_object_type
5940 is_temp = True
5942 def __init__(self, pos, body):
5943 ExprNode.__init__(self, pos)
5944 assert body.type.is_pyobject
5945 self.body = body
5947 def analyse_types(self, env):
5948 pass
5950 def generate_result_code(self, code):
5951 code.putln('%s = __Pyx_GetAttrString(%s, "__doc__");' %
5952 (self.result(), self.body.result()))
5953 code.put_gotref(self.result())
5957 #------------------------------------------------------------------------------------
5959 # Runtime support code
5961 #------------------------------------------------------------------------------------
5963 get_name_interned_utility_code = UtilityCode(
5964 proto = """
5965 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
5966 """,
5967 impl = """
5968 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
5969 PyObject *result;
5970 result = PyObject_GetAttr(dict, name);
5971 if (!result)
5972 PyErr_SetObject(PyExc_NameError, name);
5973 return result;
5975 """)
5977 #------------------------------------------------------------------------------------
5979 import_utility_code = UtilityCode(
5980 proto = """
5981 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
5982 """,
5983 impl = """
5984 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
5985 PyObject *__import__ = 0;
5986 PyObject *empty_list = 0;
5987 PyObject *module = 0;
5988 PyObject *global_dict = 0;
5989 PyObject *empty_dict = 0;
5990 PyObject *list;
5991 __import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
5992 if (!__import__)
5993 goto bad;
5994 if (from_list)
5995 list = from_list;
5996 else {
5997 empty_list = PyList_New(0);
5998 if (!empty_list)
5999 goto bad;
6000 list = empty_list;
6002 global_dict = PyModule_GetDict(%(GLOBALS)s);
6003 if (!global_dict)
6004 goto bad;
6005 empty_dict = PyDict_New();
6006 if (!empty_dict)
6007 goto bad;
6008 module = PyObject_CallFunctionObjArgs(__import__,
6009 name, global_dict, empty_dict, list, NULL);
6010 bad:
6011 Py_XDECREF(empty_list);
6012 Py_XDECREF(__import__);
6013 Py_XDECREF(empty_dict);
6014 return module;
6016 """ % {
6017 "BUILTINS": Naming.builtins_cname,
6018 "GLOBALS": Naming.module_cname,
6019 })
6021 #------------------------------------------------------------------------------------
6023 get_exception_utility_code = UtilityCode(
6024 proto = """
6025 static PyObject *__Pyx_GetExcValue(void); /*proto*/
6026 """,
6027 impl = """
6028 static PyObject *__Pyx_GetExcValue(void) {
6029 PyObject *type = 0, *value = 0, *tb = 0;
6030 PyObject *tmp_type, *tmp_value, *tmp_tb;
6031 PyObject *result = 0;
6032 PyThreadState *tstate = PyThreadState_Get();
6033 PyErr_Fetch(&type, &value, &tb);
6034 PyErr_NormalizeException(&type, &value, &tb);
6035 if (PyErr_Occurred())
6036 goto bad;
6037 if (!value) {
6038 value = Py_None;
6039 Py_INCREF(value);
6041 tmp_type = tstate->exc_type;
6042 tmp_value = tstate->exc_value;
6043 tmp_tb = tstate->exc_traceback;
6044 tstate->exc_type = type;
6045 tstate->exc_value = value;
6046 tstate->exc_traceback = tb;
6047 /* Make sure tstate is in a consistent state when we XDECREF
6048 these objects (XDECREF may run arbitrary code). */
6049 Py_XDECREF(tmp_type);
6050 Py_XDECREF(tmp_value);
6051 Py_XDECREF(tmp_tb);
6052 result = value;
6053 Py_XINCREF(result);
6054 type = 0;
6055 value = 0;
6056 tb = 0;
6057 bad:
6058 Py_XDECREF(type);
6059 Py_XDECREF(value);
6060 Py_XDECREF(tb);
6061 return result;
6063 """)
6065 #------------------------------------------------------------------------------------
6067 type_test_utility_code = UtilityCode(
6068 proto = """
6069 static INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
6070 """,
6071 impl = """
6072 static INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
6073 if (unlikely(!type)) {
6074 PyErr_Format(PyExc_SystemError, "Missing type object");
6075 return 0;
6077 if (likely(PyObject_TypeCheck(obj, type)))
6078 return 1;
6079 PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s",
6080 Py_TYPE(obj)->tp_name, type->tp_name);
6081 return 0;
6083 """)
6085 #------------------------------------------------------------------------------------
6087 create_class_utility_code = UtilityCode(
6088 proto = """
6089 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
6090 """,
6091 impl = """
6092 static PyObject *__Pyx_CreateClass(
6093 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
6095 PyObject *py_modname;
6096 PyObject *result = 0;
6098 #if PY_MAJOR_VERSION < 3
6099 py_modname = PyString_FromString(modname);
6100 #else
6101 py_modname = PyUnicode_FromString(modname);
6102 #endif
6103 if (!py_modname)
6104 goto bad;
6105 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
6106 goto bad;
6107 #if PY_MAJOR_VERSION < 3
6108 result = PyClass_New(bases, dict, name);
6109 #else
6110 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
6111 #endif
6112 bad:
6113 Py_XDECREF(py_modname);
6114 return result;
6116 """)
6118 #------------------------------------------------------------------------------------
6120 cpp_exception_utility_code = UtilityCode(
6121 proto = """
6122 #ifndef __Pyx_CppExn2PyErr
6123 static void __Pyx_CppExn2PyErr() {
6124 try {
6125 if (PyErr_Occurred())
6126 ; // let the latest Python exn pass through and ignore the current one
6127 else
6128 throw;
6129 } catch (const std::out_of_range& exn) {
6130 // catch out_of_range explicitly so the proper Python exn may be raised
6131 PyErr_SetString(PyExc_IndexError, exn.what());
6132 } catch (const std::exception& exn) {
6133 PyErr_SetString(PyExc_RuntimeError, exn.what());
6135 catch (...)
6137 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
6140 #endif
6141 """,
6142 impl = ""
6145 #------------------------------------------------------------------------------------
6147 # If the is_unsigned flag is set, we need to do some extra work to make
6148 # sure the index doesn't become negative.
6150 getitem_int_utility_code = UtilityCode(
6151 proto = """
6153 static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
6154 PyObject *r;
6155 if (!j) return NULL;
6156 r = PyObject_GetItem(o, j);
6157 Py_DECREF(j);
6158 return r;
6161 """ + ''.join([
6162 """
6163 #define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6164 __Pyx_GetItemInt_%(type)s_Fast(o, i, size <= sizeof(long)) : \\
6165 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
6167 static INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6168 if (likely(o != Py_None)) {
6169 if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
6170 PyObject *r = Py%(type)s_GET_ITEM(o, i);
6171 Py_INCREF(r);
6172 return r;
6174 else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
6175 PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
6176 Py_INCREF(r);
6177 return r;
6180 return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
6182 """ % {'type' : type_name} for type_name in ('List', 'Tuple')
6183 ]) + """
6185 #define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6186 __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \\
6187 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
6189 static INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6190 PyObject *r;
6191 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
6192 r = PyList_GET_ITEM(o, i);
6193 Py_INCREF(r);
6195 else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
6196 r = PyTuple_GET_ITEM(o, i);
6197 Py_INCREF(r);
6199 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
6200 r = PySequence_GetItem(o, i);
6202 else {
6203 r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
6205 return r;
6207 """,
6208 impl = """
6209 """)
6213 #------------------------------------------------------------------------------------
6215 setitem_int_utility_code = UtilityCode(
6216 proto = """
6217 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6218 __Pyx_SetItemInt_Fast(o, i, v, size <= sizeof(long)) : \\
6219 __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
6221 static INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
6222 int r;
6223 if (!j) return -1;
6224 r = PyObject_SetItem(o, j, v);
6225 Py_DECREF(j);
6226 return r;
6229 static INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int fits_long) {
6230 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
6231 Py_INCREF(v);
6232 Py_DECREF(PyList_GET_ITEM(o, i));
6233 PyList_SET_ITEM(o, i, v);
6234 return 1;
6236 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
6237 return PySequence_SetItem(o, i, v);
6238 else {
6239 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
6240 return __Pyx_SetItemInt_Generic(o, j, v);
6243 """,
6244 impl = """
6245 """)
6247 #------------------------------------------------------------------------------------
6249 delitem_int_utility_code = UtilityCode(
6250 proto = """
6251 #define __Pyx_DelItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6252 __Pyx_DelItemInt_Fast(o, i, size <= sizeof(long)) : \\
6253 __Pyx_DelItem_Generic(o, to_py_func(i)))
6255 static INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
6256 int r;
6257 if (!j) return -1;
6258 r = PyObject_DelItem(o, j);
6259 Py_DECREF(j);
6260 return r;
6263 static INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6264 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
6265 return PySequence_DelItem(o, i);
6266 else {
6267 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
6268 return __Pyx_DelItem_Generic(o, j);
6271 """,
6272 impl = """
6273 """)
6275 #------------------------------------------------------------------------------------
6277 raise_noneattr_error_utility_code = UtilityCode(
6278 proto = """
6279 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
6280 """,
6281 impl = '''
6282 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
6283 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
6285 ''')
6287 raise_noneindex_error_utility_code = UtilityCode(
6288 proto = """
6289 static INLINE void __Pyx_RaiseNoneIndexingError(void);
6290 """,
6291 impl = '''
6292 static INLINE void __Pyx_RaiseNoneIndexingError(void) {
6293 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
6295 ''')
6297 raise_none_iter_error_utility_code = UtilityCode(
6298 proto = """
6299 static INLINE void __Pyx_RaiseNoneNotIterableError(void);
6300 """,
6301 impl = '''
6302 static INLINE void __Pyx_RaiseNoneNotIterableError(void) {
6303 PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
6305 ''')
6307 raise_too_many_values_to_unpack = UtilityCode(
6308 proto = """
6309 static INLINE void __Pyx_RaiseTooManyValuesError(void);
6310 """,
6311 impl = '''
6312 static INLINE void __Pyx_RaiseTooManyValuesError(void) {
6313 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
6315 ''')
6317 raise_need_more_values_to_unpack = UtilityCode(
6318 proto = """
6319 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
6320 """,
6321 impl = '''
6322 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
6323 PyErr_Format(PyExc_ValueError,
6324 #if PY_VERSION_HEX < 0x02050000
6325 "need more than %d value%s to unpack", (int)index,
6326 #else
6327 "need more than %zd value%s to unpack", index,
6328 #endif
6329 (index == 1) ? "" : "s");
6331 ''')
6333 #------------------------------------------------------------------------------------
6335 tuple_unpacking_error_code = UtilityCode(
6336 proto = """
6337 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
6338 """,
6339 impl = """
6340 static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
6341 if (t == Py_None) {
6342 __Pyx_RaiseNoneNotIterableError();
6343 } else if (PyTuple_GET_SIZE(t) < index) {
6344 __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
6345 } else {
6346 __Pyx_RaiseTooManyValuesError();
6349 """,
6350 requires = [raise_none_iter_error_utility_code,
6351 raise_need_more_values_to_unpack,
6352 raise_too_many_values_to_unpack]
6355 unpacking_utility_code = UtilityCode(
6356 proto = """
6357 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
6358 static int __Pyx_EndUnpack(PyObject *); /*proto*/
6359 """,
6360 impl = """
6361 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
6362 PyObject *item;
6363 if (!(item = PyIter_Next(iter))) {
6364 if (!PyErr_Occurred()) {
6365 __Pyx_RaiseNeedMoreValuesError(index);
6368 return item;
6371 static int __Pyx_EndUnpack(PyObject *iter) {
6372 PyObject *item;
6373 if ((item = PyIter_Next(iter))) {
6374 Py_DECREF(item);
6375 __Pyx_RaiseTooManyValuesError();
6376 return -1;
6378 else if (!PyErr_Occurred())
6379 return 0;
6380 else
6381 return -1;
6383 """,
6384 requires = [raise_need_more_values_to_unpack,
6385 raise_too_many_values_to_unpack]
6389 #------------------------------------------------------------------------------------
6391 int_pow_utility_code = UtilityCode(
6392 proto="""
6393 static INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
6394 """,
6395 impl="""
6396 static INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
6397 %(type)s t = b;
6398 switch (e) {
6399 case 3:
6400 t *= b;
6401 case 2:
6402 t *= b;
6403 case 1:
6404 return t;
6405 case 0:
6406 return 1;
6408 if (unlikely(e<0)) return 0;
6409 t = 1;
6410 while (likely(e)) {
6411 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
6412 b *= b;
6413 e >>= 1;
6415 return t;
6417 """)
6419 # ------------------------------ Division ------------------------------------
6421 div_int_utility_code = UtilityCode(
6422 proto="""
6423 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
6424 """,
6425 impl="""
6426 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
6427 %(type)s q = a / b;
6428 %(type)s r = a - q*b;
6429 q -= ((r != 0) & ((r ^ b) < 0));
6430 return q;
6432 """)
6434 mod_int_utility_code = UtilityCode(
6435 proto="""
6436 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6437 """,
6438 impl="""
6439 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6440 %(type)s r = a %% b;
6441 r += ((r != 0) & ((r ^ b) < 0)) * b;
6442 return r;
6444 """)
6446 mod_float_utility_code = UtilityCode(
6447 proto="""
6448 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6449 """,
6450 impl="""
6451 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6452 %(type)s r = fmod%(math_h_modifier)s(a, b);
6453 r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
6454 return r;
6456 """)
6458 cdivision_warning_utility_code = UtilityCode(
6459 proto="""
6460 static int __Pyx_cdivision_warning(void); /* proto */
6461 """,
6462 impl="""
6463 static int __Pyx_cdivision_warning(void) {
6464 return PyErr_WarnExplicit(PyExc_RuntimeWarning,
6465 "division with oppositely signed operands, C and Python semantics differ",
6466 %(FILENAME)s,
6467 %(LINENO)s,
6468 __Pyx_MODULE_NAME,
6469 NULL);
6471 """ % {
6472 'FILENAME': Naming.filename_cname,
6473 'LINENO': Naming.lineno_cname,
6474 })
6476 # from intobject.c
6477 division_overflow_test_code = UtilityCode(
6478 proto="""
6479 #define UNARY_NEG_WOULD_OVERFLOW(x) \
6480 (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
6481 """)