Cython has moved to github.
cython-devel
view Cython/Compiler/ExprNodes.py @ 2715:56bc793d18e0
enable Python methods on C types through coercion to Python objects
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Thu Dec 03 13:17:39 2009 +0100 (2 years ago) |
| parents | 42da0e99a94b |
| children | e00a09e6561a |
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.
1036 #
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 the 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']:
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.
1350 #
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`
1427 #
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)
1458 #
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.
1493 #
1494 # allocate_counter_temp/release_counter_temp needs to be called
1495 # by parent (ForInStatNode)
1496 #
1497 # Implements result = iter(sequence)
1498 #
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.
1559 #
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.
1643 #
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 #-------------------------------------------------------------------
1712 #
1713 # Trailer nodes
1714 #
1715 #-------------------------------------------------------------------
1717 class IndexNode(ExprNode):
1718 # Sequence indexing.
1719 #
1720 # base ExprNode
1721 # index ExprNode
1722 # indices [ExprNode]
1723 # is_buffer_access boolean Whether this is a buffer access.
1724 #
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
2069 #
2070 # base ExprNode
2071 # start ExprNode or None
2072 # stop ExprNode or None
2074 subexprs = ['base', 'start', 'stop']
2076 def calculate_constant_result(self):
2077 self.constant_result = self.base.constant_result[
2078 self.start.constant_result : self.stop.constant_result]
2080 def compile_time_value(self, denv):
2081 base = self.base.compile_time_value(denv)
2082 if self.start is None:
2083 start = 0
2084 else:
2085 start = self.start.compile_time_value(denv)
2086 if self.stop is None:
2087 stop = None
2088 else:
2089 stop = self.stop.compile_time_value(denv)
2090 try:
2091 return base[start:stop]
2092 except Exception, e:
2093 self.compile_time_value_error(e)
2095 def analyse_target_declaration(self, env):
2096 pass
2098 def analyse_target_types(self, env):
2099 self.analyse_types(env)
2100 # when assigning, we must accept any Python type
2101 if self.type.is_pyobject:
2102 self.type = py_object_type
2104 def analyse_types(self, env):
2105 self.base.analyse_types(env)
2106 if self.start:
2107 self.start.analyse_types(env)
2108 if self.stop:
2109 self.stop.analyse_types(env)
2110 base_type = self.base.type
2111 if base_type.is_string:
2112 self.type = bytes_type
2113 elif base_type.is_array or base_type.is_ptr:
2114 # we need a ptr type here instead of an array type, as
2115 # array types can result in invalid type casts in the C
2116 # code
2117 self.type = PyrexTypes.CPtrType(base_type.base_type)
2118 else:
2119 self.base = self.base.coerce_to_pyobject(env)
2120 self.type = py_object_type
2121 if base_type.is_builtin_type:
2122 # slicing builtin types returns something of the same type
2123 self.type = base_type
2124 c_int = PyrexTypes.c_py_ssize_t_type
2125 if self.start:
2126 self.start = self.start.coerce_to(c_int, env)
2127 if self.stop:
2128 self.stop = self.stop.coerce_to(c_int, env)
2129 self.is_temp = 1
2131 nogil_check = Node.gil_error
2132 gil_message = "Slicing Python object"
2134 def generate_result_code(self, code):
2135 if not self.type.is_pyobject:
2136 error(self.pos,
2137 "Slicing is not currently supported for '%s'." % self.type)
2138 return
2139 if self.base.type.is_string:
2140 if self.stop is None:
2141 code.putln(
2142 "%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
2143 self.result(),
2144 self.base.result(),
2145 self.start_code(),
2146 code.error_goto_if_null(self.result(), self.pos)))
2147 else:
2148 code.putln(
2149 "%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
2150 self.result(),
2151 self.base.result(),
2152 self.start_code(),
2153 self.stop_code(),
2154 self.start_code(),
2155 code.error_goto_if_null(self.result(), self.pos)))
2156 else:
2157 code.putln(
2158 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
2159 self.result(),
2160 self.base.py_result(),
2161 self.start_code(),
2162 self.stop_code(),
2163 code.error_goto_if_null(self.result(), self.pos)))
2164 code.put_gotref(self.py_result())
2166 def generate_assignment_code(self, rhs, code):
2167 self.generate_subexpr_evaluation_code(code)
2168 if self.type.is_pyobject:
2169 code.put_error_if_neg(self.pos,
2170 "PySequence_SetSlice(%s, %s, %s, %s)" % (
2171 self.base.py_result(),
2172 self.start_code(),
2173 self.stop_code(),
2174 rhs.result()))
2175 else:
2176 start_offset = ''
2177 if self.start:
2178 start_offset = self.start_code()
2179 if start_offset == '0':
2180 start_offset = ''
2181 else:
2182 start_offset += '+'
2183 if rhs.type.is_array:
2184 array_length = rhs.type.size
2185 self.generate_slice_guard_code(code, array_length)
2186 else:
2187 error(self.pos,
2188 "Slice assignments from pointers are not yet supported.")
2189 # FIXME: fix the array size according to start/stop
2190 array_length = self.base.type.size
2191 for i in range(array_length):
2192 code.putln("%s[%s%s] = %s[%d];" % (
2193 self.base.result(), start_offset, i,
2194 rhs.result(), i))
2195 self.generate_subexpr_disposal_code(code)
2196 self.free_subexpr_temps(code)
2197 rhs.generate_disposal_code(code)
2198 rhs.free_temps(code)
2200 def generate_deletion_code(self, code):
2201 if not self.base.type.is_pyobject:
2202 error(self.pos,
2203 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2204 return
2205 self.generate_subexpr_evaluation_code(code)
2206 code.put_error_if_neg(self.pos,
2207 "PySequence_DelSlice(%s, %s, %s)" % (
2208 self.base.py_result(),
2209 self.start_code(),
2210 self.stop_code()))
2211 self.generate_subexpr_disposal_code(code)
2213 def generate_slice_guard_code(self, code, target_size):
2214 if not self.base.type.is_array:
2215 return
2216 slice_size = self.base.type.size
2217 start = stop = None
2218 if self.stop:
2219 stop = self.stop.result()
2220 try:
2221 stop = int(stop)
2222 if stop < 0:
2223 slice_size = self.base.type.size + stop
2224 else:
2225 slice_size = stop
2226 stop = None
2227 except ValueError:
2228 pass
2229 if self.start:
2230 start = self.start.result()
2231 try:
2232 start = int(start)
2233 if start < 0:
2234 start = self.base.type.size + start
2235 slice_size -= start
2236 start = None
2237 except ValueError:
2238 pass
2239 check = None
2240 if slice_size < 0:
2241 if target_size > 0:
2242 error(self.pos, "Assignment to empty slice.")
2243 elif start is None and stop is None:
2244 # we know the exact slice length
2245 if target_size != slice_size:
2246 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2247 slice_size, target_size))
2248 elif start is not None:
2249 if stop is None:
2250 stop = slice_size
2251 check = "(%s)-(%s)" % (stop, start)
2252 else: # stop is not None:
2253 check = stop
2254 if check:
2255 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2256 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));' % (
2257 target_size, check))
2258 code.putln(code.error_goto(self.pos))
2259 code.putln("}")
2261 def start_code(self):
2262 if self.start:
2263 return self.start.result()
2264 else:
2265 return "0"
2267 def stop_code(self):
2268 if self.stop:
2269 return self.stop.result()
2270 elif self.base.type.is_array:
2271 return self.base.type.size
2272 else:
2273 return "PY_SSIZE_T_MAX"
2275 def calculate_result_code(self):
2276 # self.result() is not used, but this method must exist
2277 return "<unused>"
2280 class SliceNode(ExprNode):
2281 # start:stop:step in subscript list
2282 #
2283 # start ExprNode
2284 # stop ExprNode
2285 # step ExprNode
2287 type = py_object_type
2288 is_temp = 1
2290 def calculate_constant_result(self):
2291 self.constant_result = self.base.constant_result[
2292 self.start.constant_result : \
2293 self.stop.constant_result : \
2294 self.step.constant_result]
2296 def compile_time_value(self, denv):
2297 start = self.start.compile_time_value(denv)
2298 if self.stop is None:
2299 stop = None
2300 else:
2301 stop = self.stop.compile_time_value(denv)
2302 if self.step is None:
2303 step = None
2304 else:
2305 step = self.step.compile_time_value(denv)
2306 try:
2307 return slice(start, stop, step)
2308 except Exception, e:
2309 self.compile_time_value_error(e)
2311 subexprs = ['start', 'stop', 'step']
2313 def analyse_types(self, env):
2314 self.start.analyse_types(env)
2315 self.stop.analyse_types(env)
2316 self.step.analyse_types(env)
2317 self.start = self.start.coerce_to_pyobject(env)
2318 self.stop = self.stop.coerce_to_pyobject(env)
2319 self.step = self.step.coerce_to_pyobject(env)
2321 gil_message = "Constructing Python slice object"
2323 def generate_result_code(self, code):
2324 code.putln(
2325 "%s = PySlice_New(%s, %s, %s); %s" % (
2326 self.result(),
2327 self.start.py_result(),
2328 self.stop.py_result(),
2329 self.step.py_result(),
2330 code.error_goto_if_null(self.result(), self.pos)))
2331 code.put_gotref(self.py_result())
2334 class CallNode(ExprNode):
2336 def analyse_as_type_constructor(self, env):
2337 type = self.function.analyse_as_type(env)
2338 if type and type.is_struct_or_union:
2339 args, kwds = self.explicit_args_kwds()
2340 items = []
2341 for arg, member in zip(args, type.scope.var_entries):
2342 items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg))
2343 if kwds:
2344 items += kwds.key_value_pairs
2345 self.key_value_pairs = items
2346 self.__class__ = DictNode
2347 self.analyse_types(env)
2348 self.coerce_to(type, env)
2349 return True
2351 def nogil_check(self, env):
2352 func_type = self.function_type()
2353 if func_type.is_pyobject:
2354 self.gil_error()
2355 elif not getattr(func_type, 'nogil', False):
2356 self.gil_error()
2358 gil_message = "Calling gil-requiring function"
2361 class SimpleCallNode(CallNode):
2362 # Function call without keyword, * or ** args.
2363 #
2364 # function ExprNode
2365 # args [ExprNode]
2366 # arg_tuple ExprNode or None used internally
2367 # self ExprNode or None used internally
2368 # coerced_self ExprNode or None used internally
2369 # wrapper_call bool used internally
2370 # has_optional_args bool used internally
2372 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2374 self = None
2375 coerced_self = None
2376 arg_tuple = None
2377 wrapper_call = False
2378 has_optional_args = False
2380 def compile_time_value(self, denv):
2381 function = self.function.compile_time_value(denv)
2382 args = [arg.compile_time_value(denv) for arg in self.args]
2383 try:
2384 return function(*args)
2385 except Exception, e:
2386 self.compile_time_value_error(e)
2388 def type_dependencies(self, env):
2389 # TODO: Update when Danilo's C++ code merged in to handle the
2390 # the case of function overloading.
2391 return self.function.type_dependencies(env)
2393 def infer_type(self, env):
2394 func_type = self.function.infer_type(env)
2395 if func_type.is_ptr:
2396 func_type = func_type.base_type
2397 if func_type.is_cfunction:
2398 return func_type.return_type
2399 else:
2400 return py_object_type
2402 def analyse_as_type(self, env):
2403 attr = self.function.as_cython_attribute()
2404 if attr == 'pointer':
2405 if len(self.args) != 1:
2406 error(self.args.pos, "only one type allowed.")
2407 else:
2408 type = self.args[0].analyse_as_type(env)
2409 if not type:
2410 error(self.args[0].pos, "Unknown type")
2411 else:
2412 return PyrexTypes.CPtrType(type)
2414 def explicit_args_kwds(self):
2415 return self.args, None
2417 def analyse_types(self, env):
2418 if self.analyse_as_type_constructor(env):
2419 return
2420 function = self.function
2421 function.is_called = 1
2422 self.function.analyse_types(env)
2423 if function.is_attribute and function.entry and function.entry.is_cmethod:
2424 # Take ownership of the object from which the attribute
2425 # was obtained, because we need to pass it as 'self'.
2426 self.self = function.obj
2427 function.obj = CloneNode(self.self)
2428 func_type = self.function_type()
2429 if func_type.is_pyobject:
2430 self.arg_tuple = TupleNode(self.pos, args = self.args)
2431 self.arg_tuple.analyse_types(env)
2432 self.args = None
2433 if function.is_name and function.type_entry:
2434 # We are calling an extension type constructor. As
2435 # long as we do not support __new__(), the result type
2436 # is clear
2437 self.type = function.type_entry.type
2438 self.result_ctype = py_object_type
2439 else:
2440 self.type = py_object_type
2441 self.is_temp = 1
2442 else:
2443 for arg in self.args:
2444 arg.analyse_types(env)
2445 if self.self and func_type.args:
2446 # Coerce 'self' to the type expected by the method.
2447 expected_type = func_type.args[0].type
2448 self.coerced_self = CloneNode(self.self).coerce_to(
2449 expected_type, env)
2450 # Insert coerced 'self' argument into argument list.
2451 self.args.insert(0, self.coerced_self)
2452 self.analyse_c_function_call(env)
2454 def function_type(self):
2455 # Return the type of the function being called, coercing a function
2456 # pointer to a function if necessary.
2457 func_type = self.function.type
2458 if func_type.is_ptr:
2459 func_type = func_type.base_type
2460 return func_type
2462 def analyse_c_function_call(self, env):
2463 func_type = self.function_type()
2464 # Check function type
2465 if not func_type.is_cfunction:
2466 if not func_type.is_error:
2467 error(self.pos, "Calling non-function type '%s'" %
2468 func_type)
2469 self.type = PyrexTypes.error_type
2470 self.result_code = "<error>"
2471 return
2472 # Check no. of args
2473 max_nargs = len(func_type.args)
2474 expected_nargs = max_nargs - func_type.optional_arg_count
2475 actual_nargs = len(self.args)
2476 if actual_nargs < expected_nargs \
2477 or (not func_type.has_varargs and actual_nargs > max_nargs):
2478 expected_str = str(expected_nargs)
2479 if func_type.has_varargs:
2480 expected_str = "at least " + expected_str
2481 elif func_type.optional_arg_count:
2482 if actual_nargs < max_nargs:
2483 expected_str = "at least " + expected_str
2484 else:
2485 expected_str = "at most " + str(max_nargs)
2486 error(self.pos,
2487 "Call with wrong number of arguments (expected %s, got %s)"
2488 % (expected_str, actual_nargs))
2489 self.args = None
2490 self.type = PyrexTypes.error_type
2491 self.result_code = "<error>"
2492 return
2493 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2494 self.has_optional_args = 1
2495 self.is_temp = 1
2496 # Coerce arguments
2497 for i in range(min(max_nargs, actual_nargs)):
2498 formal_type = func_type.args[i].type
2499 self.args[i] = self.args[i].coerce_to(formal_type, env)
2500 for i in range(max_nargs, actual_nargs):
2501 if self.args[i].type.is_pyobject:
2502 error(self.args[i].pos,
2503 "Python object cannot be passed as a varargs parameter")
2504 # Calc result type and code fragment
2505 self.type = func_type.return_type
2506 if self.type.is_pyobject:
2507 self.result_ctype = py_object_type
2508 self.is_temp = 1
2509 elif func_type.exception_value is not None \
2510 or func_type.exception_check:
2511 self.is_temp = 1
2512 # C++ exception handler
2513 if func_type.exception_check == '+':
2514 if func_type.exception_value is None:
2515 env.use_utility_code(cpp_exception_utility_code)
2517 def calculate_result_code(self):
2518 return self.c_call_code()
2520 def c_call_code(self):
2521 func_type = self.function_type()
2522 if self.args is None or not func_type.is_cfunction:
2523 return "<error>"
2524 formal_args = func_type.args
2525 arg_list_code = []
2526 args = zip(formal_args, self.args)
2527 max_nargs = len(func_type.args)
2528 expected_nargs = max_nargs - func_type.optional_arg_count
2529 actual_nargs = len(self.args)
2530 for formal_arg, actual_arg in args[:expected_nargs]:
2531 arg_code = actual_arg.result_as(formal_arg.type)
2532 arg_list_code.append(arg_code)
2534 if func_type.is_overridable:
2535 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2537 if func_type.optional_arg_count:
2538 if expected_nargs == actual_nargs:
2539 optional_args = 'NULL'
2540 else:
2541 optional_args = "&%s" % self.opt_arg_struct
2542 arg_list_code.append(optional_args)
2544 for actual_arg in self.args[len(formal_args):]:
2545 arg_list_code.append(actual_arg.result())
2546 result = "%s(%s)" % (self.function.result(),
2547 ', '.join(arg_list_code))
2548 return result
2550 def generate_result_code(self, code):
2551 func_type = self.function_type()
2552 if func_type.is_pyobject:
2553 arg_code = self.arg_tuple.py_result()
2554 code.putln(
2555 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2556 self.result(),
2557 self.function.py_result(),
2558 arg_code,
2559 code.error_goto_if_null(self.result(), self.pos)))
2560 code.put_gotref(self.py_result())
2561 elif func_type.is_cfunction:
2562 if self.has_optional_args:
2563 actual_nargs = len(self.args)
2564 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2565 self.opt_arg_struct = code.funcstate.allocate_temp(
2566 func_type.op_arg_struct.base_type, manage_ref=True)
2567 code.putln("%s.%s = %s;" % (
2568 self.opt_arg_struct,
2569 Naming.pyrex_prefix + "n",
2570 len(self.args) - expected_nargs))
2571 args = zip(func_type.args, self.args)
2572 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2573 code.putln("%s.%s = %s;" % (
2574 self.opt_arg_struct,
2575 func_type.opt_arg_cname(formal_arg.name),
2576 actual_arg.result_as(formal_arg.type)))
2577 exc_checks = []
2578 if self.type.is_pyobject:
2579 exc_checks.append("!%s" % self.result())
2580 else:
2581 exc_val = func_type.exception_value
2582 exc_check = func_type.exception_check
2583 if exc_val is not None:
2584 exc_checks.append("%s == %s" % (self.result(), exc_val))
2585 if exc_check:
2586 exc_checks.append("PyErr_Occurred()")
2587 if self.is_temp or exc_checks:
2588 rhs = self.c_call_code()
2589 if self.result():
2590 lhs = "%s = " % self.result()
2591 if self.is_temp and self.type.is_pyobject:
2592 #return_type = self.type # func_type.return_type
2593 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2594 # "from", return_type, "to pyobject" ###
2595 rhs = typecast(py_object_type, self.type, rhs)
2596 else:
2597 lhs = ""
2598 if func_type.exception_check == '+':
2599 if func_type.exception_value is None:
2600 raise_py_exception = "__Pyx_CppExn2PyErr()"
2601 elif func_type.exception_value.type.is_pyobject:
2602 raise_py_exception = ' try { throw; } catch(const std::exception& exn) { PyErr_SetString(%s, exn.what()); } catch(...) { PyErr_SetNone(%s); }' % (
2603 func_type.exception_value.entry.cname,
2604 func_type.exception_value.entry.cname)
2605 else:
2606 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2607 code.putln(
2608 "try {%s%s;} catch(...) {%s; %s}" % (
2609 lhs,
2610 rhs,
2611 raise_py_exception,
2612 code.error_goto(self.pos)))
2613 else:
2614 if exc_checks:
2615 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2616 else:
2617 goto_error = ""
2618 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2619 if self.type.is_pyobject and self.result():
2620 code.put_gotref(self.py_result())
2621 if self.has_optional_args:
2622 code.funcstate.release_temp(self.opt_arg_struct)
2625 class PythonCapiFunctionNode(ExprNode):
2626 subexprs = []
2627 def __init__(self, pos, name, func_type, utility_code = None):
2628 self.pos = pos
2629 self.name = name
2630 self.type = func_type
2631 self.utility_code = utility_code
2633 def generate_result_code(self, code):
2634 if self.utility_code:
2635 code.globalstate.use_utility_code(self.utility_code)
2637 def calculate_result_code(self):
2638 return self.name
2640 class PythonCapiCallNode(SimpleCallNode):
2641 # Python C-API Function call (only created in transforms)
2643 def __init__(self, pos, function_name, func_type,
2644 utility_code = None, **kwargs):
2645 self.type = func_type.return_type
2646 self.result_ctype = self.type
2647 self.function = PythonCapiFunctionNode(
2648 pos, function_name, func_type,
2649 utility_code = utility_code)
2650 # call this last so that we can override the constructed
2651 # attributes above with explicit keyword arguments if required
2652 SimpleCallNode.__init__(self, pos, **kwargs)
2655 class GeneralCallNode(CallNode):
2656 # General Python function call, including keyword,
2657 # * and ** arguments.
2658 #
2659 # function ExprNode
2660 # positional_args ExprNode Tuple of positional arguments
2661 # keyword_args ExprNode or None Dict of keyword arguments
2662 # starstar_arg ExprNode or None Dict of extra keyword args
2664 type = py_object_type
2666 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2668 nogil_check = Node.gil_error
2670 def compile_time_value(self, denv):
2671 function = self.function.compile_time_value(denv)
2672 positional_args = self.positional_args.compile_time_value(denv)
2673 keyword_args = self.keyword_args.compile_time_value(denv)
2674 starstar_arg = self.starstar_arg.compile_time_value(denv)
2675 try:
2676 keyword_args.update(starstar_arg)
2677 return function(*positional_args, **keyword_args)
2678 except Exception, e:
2679 self.compile_time_value_error(e)
2681 def explicit_args_kwds(self):
2682 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2683 raise PostParseError(self.pos,
2684 'Compile-time keyword arguments must be explicit.')
2685 return self.positional_args.args, self.keyword_args
2687 def analyse_types(self, env):
2688 if self.analyse_as_type_constructor(env):
2689 return
2690 self.function.analyse_types(env)
2691 self.positional_args.analyse_types(env)
2692 if self.keyword_args:
2693 self.keyword_args.analyse_types(env)
2694 if self.starstar_arg:
2695 self.starstar_arg.analyse_types(env)
2696 if not self.function.type.is_pyobject:
2697 if self.function.type.is_error:
2698 self.type = error_type
2699 return
2700 if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
2701 error(self.pos, "Keyword and starred arguments not allowed in cdef functions.")
2702 else:
2703 self.function = self.function.coerce_to_pyobject(env)
2704 self.positional_args = \
2705 self.positional_args.coerce_to_pyobject(env)
2706 if self.starstar_arg:
2707 self.starstar_arg = \
2708 self.starstar_arg.coerce_to_pyobject(env)
2709 function = self.function
2710 if function.is_name and function.type_entry:
2711 # We are calling an extension type constructor. As long
2712 # as we do not support __new__(), the result type is clear
2713 self.type = function.type_entry.type
2714 self.result_ctype = py_object_type
2715 else:
2716 self.type = py_object_type
2717 self.is_temp = 1
2719 def generate_result_code(self, code):
2720 if self.type.is_error: return
2721 if self.keyword_args and self.starstar_arg:
2722 code.put_error_if_neg(self.pos,
2723 "PyDict_Update(%s, %s)" % (
2724 self.keyword_args.py_result(),
2725 self.starstar_arg.py_result()))
2726 keyword_code = self.keyword_args.py_result()
2727 elif self.keyword_args:
2728 keyword_code = self.keyword_args.py_result()
2729 elif self.starstar_arg:
2730 keyword_code = self.starstar_arg.py_result()
2731 else:
2732 keyword_code = None
2733 if not keyword_code:
2734 call_code = "PyObject_Call(%s, %s, NULL)" % (
2735 self.function.py_result(),
2736 self.positional_args.py_result())
2737 else:
2738 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2739 self.function.py_result(),
2740 self.positional_args.py_result(),
2741 keyword_code)
2742 code.putln(
2743 "%s = %s; %s" % (
2744 self.result(),
2745 call_code,
2746 code.error_goto_if_null(self.result(), self.pos)))
2747 code.put_gotref(self.py_result())
2750 class AsTupleNode(ExprNode):
2751 # Convert argument to tuple. Used for normalising
2752 # the * argument of a function call.
2753 #
2754 # arg ExprNode
2756 subexprs = ['arg']
2758 def calculate_constant_result(self):
2759 self.constant_result = tuple(self.base.constant_result)
2761 def compile_time_value(self, denv):
2762 arg = self.arg.compile_time_value(denv)
2763 try:
2764 return tuple(arg)
2765 except Exception, e:
2766 self.compile_time_value_error(e)
2768 def analyse_types(self, env):
2769 self.arg.analyse_types(env)
2770 self.arg = self.arg.coerce_to_pyobject(env)
2771 self.type = tuple_type
2772 self.is_temp = 1
2774 nogil_check = Node.gil_error
2775 gil_message = "Constructing Python tuple"
2777 def generate_result_code(self, code):
2778 code.putln(
2779 "%s = PySequence_Tuple(%s); %s" % (
2780 self.result(),
2781 self.arg.py_result(),
2782 code.error_goto_if_null(self.result(), self.pos)))
2783 code.put_gotref(self.py_result())
2786 class AttributeNode(ExprNode):
2787 # obj.attribute
2788 #
2789 # obj ExprNode
2790 # attribute string
2791 # needs_none_check boolean Used if obj is an extension type.
2792 # If set to True, it is known that the type is not None.
2793 #
2794 # Used internally:
2795 #
2796 # is_py_attr boolean Is a Python getattr operation
2797 # member string C name of struct member
2798 # is_called boolean Function call is being done on result
2799 # entry Entry Symbol table entry of attribute
2801 is_attribute = 1
2802 subexprs = ['obj']
2804 type = PyrexTypes.error_type
2805 entry = None
2806 is_called = 0
2807 needs_none_check = True
2809 def as_cython_attribute(self):
2810 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2811 return self.attribute
2813 def coerce_to(self, dst_type, env):
2814 # If coercing to a generic pyobject and this is a cpdef function
2815 # we can create the corresponding attribute
2816 if dst_type is py_object_type:
2817 entry = self.entry
2818 if entry and entry.is_cfunction and entry.as_variable:
2819 # must be a cpdef function
2820 self.is_temp = 1
2821 self.entry = entry.as_variable
2822 self.analyse_as_python_attribute(env)
2823 return self
2824 return ExprNode.coerce_to(self, dst_type, env)
2826 def calculate_constant_result(self):
2827 attr = self.attribute
2828 if attr.startswith("__") and attr.endswith("__"):
2829 return
2830 self.constant_result = getattr(self.obj.constant_result, attr)
2832 def compile_time_value(self, denv):
2833 attr = self.attribute
2834 if attr.startswith("__") and attr.endswith("__"):
2835 error(self.pos,
2836 "Invalid attribute name '%s' in compile-time expression" % attr)
2837 return None
2838 obj = self.obj.compile_time_value(denv)
2839 try:
2840 return getattr(obj, attr)
2841 except Exception, e:
2842 self.compile_time_value_error(e)
2844 def type_dependencies(self, env):
2845 return self.obj.type_dependencies(env)
2847 def infer_type(self, env):
2848 if self.analyse_as_cimported_attribute(env, 0):
2849 return self.entry.type
2850 elif self.analyse_as_unbound_cmethod(env):
2851 return self.entry.type
2852 else:
2853 self.analyse_attribute(env, obj_type = self.obj.infer_type(env))
2854 return self.type
2856 def analyse_target_declaration(self, env):
2857 pass
2859 def analyse_target_types(self, env):
2860 self.analyse_types(env, target = 1)
2862 def analyse_types(self, env, target = 0):
2863 if self.analyse_as_cimported_attribute(env, target):
2864 return
2865 if not target and self.analyse_as_unbound_cmethod(env):
2866 return
2867 self.analyse_as_ordinary_attribute(env, target)
2869 def analyse_as_cimported_attribute(self, env, target):
2870 # Try to interpret this as a reference to an imported
2871 # C const, type, var or function. If successful, mutates
2872 # this node into a NameNode and returns 1, otherwise
2873 # returns 0.
2874 module_scope = self.obj.analyse_as_module(env)
2875 if module_scope:
2876 entry = module_scope.lookup_here(self.attribute)
2877 if entry and (
2878 entry.is_cglobal or entry.is_cfunction
2879 or entry.is_type or entry.is_const):
2880 self.mutate_into_name_node(env, entry, target)
2881 return 1
2882 return 0
2884 def analyse_as_unbound_cmethod(self, env):
2885 # Try to interpret this as a reference to an unbound
2886 # C method of an extension type. If successful, mutates
2887 # this node into a NameNode and returns 1, otherwise
2888 # returns 0.
2889 type = self.obj.analyse_as_extension_type(env)
2890 if type:
2891 entry = type.scope.lookup_here(self.attribute)
2892 if entry and entry.is_cmethod:
2893 # Create a temporary entry describing the C method
2894 # as an ordinary function.
2895 ubcm_entry = Symtab.Entry(entry.name,
2896 "%s->%s" % (type.vtabptr_cname, entry.cname),
2897 entry.type)
2898 ubcm_entry.is_cfunction = 1
2899 ubcm_entry.func_cname = entry.func_cname
2900 ubcm_entry.is_unbound_cmethod = 1
2901 self.mutate_into_name_node(env, ubcm_entry, None)
2902 return 1
2903 return 0
2905 def analyse_as_type(self, env):
2906 module_scope = self.obj.analyse_as_module(env)
2907 if module_scope:
2908 return module_scope.lookup_type(self.attribute)
2909 return None
2911 def analyse_as_extension_type(self, env):
2912 # Try to interpret this as a reference to an extension type
2913 # in a cimported module. Returns the extension type, or None.
2914 module_scope = self.obj.analyse_as_module(env)
2915 if module_scope:
2916 entry = module_scope.lookup_here(self.attribute)
2917 if entry and entry.is_type and entry.type.is_extension_type:
2918 return entry.type
2919 return None
2921 def analyse_as_module(self, env):
2922 # Try to interpret this as a reference to a cimported module
2923 # in another cimported module. Returns the module scope, or None.
2924 module_scope = self.obj.analyse_as_module(env)
2925 if module_scope:
2926 entry = module_scope.lookup_here(self.attribute)
2927 if entry and entry.as_module:
2928 return entry.as_module
2929 return None
2931 def mutate_into_name_node(self, env, entry, target):
2932 # Mutate this node into a NameNode and complete the
2933 # analyse_types phase.
2934 self.__class__ = NameNode
2935 self.name = self.attribute
2936 self.entry = entry
2937 del self.obj
2938 del self.attribute
2939 if target:
2940 NameNode.analyse_target_types(self, env)
2941 else:
2942 NameNode.analyse_rvalue_entry(self, env)
2944 def analyse_as_ordinary_attribute(self, env, target):
2945 self.obj.analyse_types(env)
2946 self.analyse_attribute(env)
2947 if self.entry and self.entry.is_cmethod and not self.is_called:
2948 # error(self.pos, "C method can only be called")
2949 pass
2950 ## Reference to C array turns into pointer to first element.
2951 #while self.type.is_array:
2952 # self.type = self.type.element_ptr_type()
2953 if self.is_py_attr:
2954 if not target:
2955 self.is_temp = 1
2956 self.result_ctype = py_object_type
2958 def analyse_attribute(self, env, obj_type = None):
2959 # Look up attribute and set self.type and self.member.
2960 self.is_py_attr = 0
2961 self.member = self.attribute
2962 if obj_type is None:
2963 if self.obj.type.is_string:
2964 self.obj = self.obj.coerce_to_pyobject(env)
2965 obj_type = self.obj.type
2966 else:
2967 if obj_type.is_string:
2968 obj_type = py_object_type
2969 if obj_type.is_ptr or obj_type.is_array:
2970 obj_type = obj_type.base_type
2971 self.op = "->"
2972 elif obj_type.is_extension_type:
2973 self.op = "->"
2974 else:
2975 self.op = "."
2976 if obj_type.has_attributes:
2977 entry = None
2978 if obj_type.attributes_known():
2979 entry = obj_type.scope.lookup_here(self.attribute)
2980 if entry and entry.is_member:
2981 entry = None
2982 else:
2983 error(self.pos,
2984 "Cannot select attribute of incomplete type '%s'"
2985 % obj_type)
2986 self.type = PyrexTypes.error_type
2987 return
2988 self.entry = entry
2989 if entry:
2990 if obj_type.is_extension_type and entry.name == "__weakref__":
2991 error(self.pos, "Illegal use of special attribute __weakref__")
2992 # methods need the normal attribute lookup
2993 # because they do not have struct entries
2994 if entry.is_variable or entry.is_cmethod:
2995 self.type = entry.type
2996 self.member = entry.cname
2997 return
2998 else:
2999 # If it's not a variable or C method, it must be a Python
3000 # method of an extension type, so we treat it like a Python
3001 # attribute.
3002 pass
3003 # If we get here, the base object is not a struct/union/extension
3004 # type, or it is an extension type and the attribute is either not
3005 # declared or is declared as a Python method. Treat it as a Python
3006 # attribute reference.
3007 self.analyse_as_python_attribute(env, obj_type)
3009 def analyse_as_python_attribute(self, env, obj_type = None):
3010 if obj_type is None:
3011 obj_type = self.obj.type
3012 self.member = self.attribute
3013 self.type = py_object_type
3014 self.is_py_attr = 1
3015 if not obj_type.is_pyobject:
3016 self.obj = self.obj.coerce_to_pyobject(env)
3017 ## if not obj_type.is_error:
3018 ## error(self.pos,
3019 ## "Object of type '%s' has no attribute '%s'" %
3020 ## (obj_type, self.attribute))
3022 def nogil_check(self, env):
3023 if self.is_py_attr:
3024 self.gil_error()
3026 gil_message = "Accessing Python attribute"
3028 def is_simple(self):
3029 if self.obj:
3030 return self.result_in_temp() or self.obj.is_simple()
3031 else:
3032 return NameNode.is_simple(self)
3034 def is_lvalue(self):
3035 if self.obj:
3036 return 1
3037 else:
3038 return NameNode.is_lvalue(self)
3040 def is_ephemeral(self):
3041 if self.obj:
3042 return self.obj.is_ephemeral()
3043 else:
3044 return NameNode.is_ephemeral(self)
3046 def calculate_result_code(self):
3047 #print "AttributeNode.calculate_result_code:", self.member ###
3048 #print "...obj node =", self.obj, "code", self.obj.result() ###
3049 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
3050 obj = self.obj
3051 obj_code = obj.result_as(obj.type)
3052 #print "...obj_code =", obj_code ###
3053 if self.entry and self.entry.is_cmethod:
3054 if obj.type.is_extension_type:
3055 return "((struct %s *)%s%s%s)->%s" % (
3056 obj.type.vtabstruct_cname, obj_code, self.op,
3057 obj.type.vtabslot_cname, self.member)
3058 else:
3059 return self.member
3060 elif obj.type.is_complex:
3061 return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code)
3062 else:
3063 return "%s%s%s" % (obj_code, self.op, self.member)
3065 def generate_result_code(self, code):
3066 interned_attr_cname = code.intern_identifier(self.attribute)
3067 if self.is_py_attr:
3068 code.putln(
3069 '%s = PyObject_GetAttr(%s, %s); %s' % (
3070 self.result(),
3071 self.obj.py_result(),
3072 interned_attr_cname,
3073 code.error_goto_if_null(self.result(), self.pos)))
3074 code.put_gotref(self.py_result())
3075 else:
3076 # result_code contains what is needed, but we may need to insert
3077 # a check and raise an exception
3078 if (self.obj.type.is_extension_type
3079 and self.needs_none_check
3080 and code.globalstate.directives['nonecheck']):
3081 self.put_nonecheck(code)
3083 def generate_assignment_code(self, rhs, code):
3084 interned_attr_cname = code.intern_identifier(self.attribute)
3085 self.obj.generate_evaluation_code(code)
3086 if self.is_py_attr:
3087 code.put_error_if_neg(self.pos,
3088 'PyObject_SetAttr(%s, %s, %s)' % (
3089 self.obj.py_result(),
3090 interned_attr_cname,
3091 rhs.py_result()))
3092 rhs.generate_disposal_code(code)
3093 rhs.free_temps(code)
3094 elif self.obj.type.is_complex:
3095 code.putln("__Pyx_SET_C%s(%s, %s);" % (
3096 self.member.upper(),
3097 self.obj.result_as(self.obj.type),
3098 rhs.result_as(self.ctype())))
3099 else:
3100 if (self.obj.type.is_extension_type
3101 and self.needs_none_check
3102 and code.globalstate.directives['nonecheck']):
3103 self.put_nonecheck(code)
3105 select_code = self.result()
3106 if self.type.is_pyobject and self.use_managed_ref:
3107 rhs.make_owned_reference(code)
3108 code.put_giveref(rhs.py_result())
3109 code.put_gotref(select_code)
3110 code.put_decref(select_code, self.ctype())
3111 code.putln(
3112 "%s = %s;" % (
3113 select_code,
3114 rhs.result_as(self.ctype())))
3115 #rhs.result()))
3116 rhs.generate_post_assignment_code(code)
3117 rhs.free_temps(code)
3118 self.obj.generate_disposal_code(code)
3119 self.obj.free_temps(code)
3121 def generate_deletion_code(self, code):
3122 interned_attr_cname = code.intern_identifier(self.attribute)
3123 self.obj.generate_evaluation_code(code)
3124 if self.is_py_attr:
3125 code.put_error_if_neg(self.pos,
3126 'PyObject_DelAttr(%s, %s)' % (
3127 self.obj.py_result(),
3128 interned_attr_cname))
3129 else:
3130 error(self.pos, "Cannot delete C attribute of extension type")
3131 self.obj.generate_disposal_code(code)
3132 self.obj.free_temps(code)
3134 def annotate(self, code):
3135 if self.is_py_attr:
3136 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
3137 else:
3138 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
3140 def put_nonecheck(self, code):
3141 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
3142 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
3143 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute)
3144 code.putln(code.error_goto(self.pos))
3145 code.putln("}")
3148 #-------------------------------------------------------------------
3149 #
3150 # Constructor nodes
3151 #
3152 #-------------------------------------------------------------------
3154 class StarredTargetNode(ExprNode):
3155 # A starred expression like "*a"
3156 #
3157 # This is only allowed in sequence assignment targets such as
3158 #
3159 # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4]
3160 #
3161 # and will be removed during type analysis (or generate an error
3162 # if it's found at unexpected places).
3163 #
3164 # target ExprNode
3166 subexprs = ['target']
3167 is_starred = 1
3168 type = py_object_type
3169 is_temp = 1
3171 def __init__(self, pos, target):
3172 self.pos = pos
3173 self.target = target
3175 def analyse_declarations(self, env):
3176 error(self.pos, "can use starred expression only as assignment target")
3177 self.target.analyse_declarations(env)
3179 def analyse_types(self, env):
3180 error(self.pos, "can use starred expression only as assignment target")
3181 self.target.analyse_types(env)
3182 self.type = self.target.type
3184 def analyse_target_declaration(self, env):
3185 self.target.analyse_target_declaration(env)
3187 def analyse_target_types(self, env):
3188 self.target.analyse_target_types(env)
3189 self.type = self.target.type
3191 def calculate_result_code(self):
3192 return ""
3194 def generate_result_code(self, code):
3195 pass
3198 class SequenceNode(ExprNode):
3199 # Base class for list and tuple constructor nodes.
3200 # Contains common code for performing sequence unpacking.
3201 #
3202 # args [ExprNode]
3203 # iterator ExprNode
3204 # unpacked_items [ExprNode] or None
3205 # coerced_unpacked_items [ExprNode] or None
3207 subexprs = ['args']
3209 is_sequence_constructor = 1
3210 unpacked_items = None
3212 def compile_time_value_list(self, denv):
3213 return [arg.compile_time_value(denv) for arg in self.args]
3215 def replace_starred_target_node(self):
3216 # replace a starred node in the targets by the contained expression
3217 self.starred_assignment = False
3218 args = []
3219 for arg in self.args:
3220 if arg.is_starred:
3221 if self.starred_assignment:
3222 error(arg.pos, "more than 1 starred expression in assignment")
3223 self.starred_assignment = True
3224 arg = arg.target
3225 arg.is_starred = True
3226 args.append(arg)
3227 self.args = args
3229 def analyse_target_declaration(self, env):
3230 self.replace_starred_target_node()
3231 for arg in self.args:
3232 arg.analyse_target_declaration(env)
3234 def analyse_types(self, env, skip_children=False):
3235 for i in range(len(self.args)):
3236 arg = self.args[i]
3237 if not skip_children: arg.analyse_types(env)
3238 self.args[i] = arg.coerce_to_pyobject(env)
3239 self.type = py_object_type
3240 self.is_temp = 1
3242 def analyse_target_types(self, env):
3243 self.iterator = PyTempNode(self.pos, env)
3244 self.unpacked_items = []
3245 self.coerced_unpacked_items = []
3246 for arg in self.args:
3247 arg.analyse_target_types(env)
3248 if arg.is_starred:
3249 if not arg.type.assignable_from(Builtin.list_type):
3250 error(arg.pos,
3251 "starred target must have Python object (list) type")
3252 if arg.type is py_object_type:
3253 arg.type = Builtin.list_type
3254 unpacked_item = PyTempNode(self.pos, env)
3255 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
3256 self.unpacked_items.append(unpacked_item)
3257 self.coerced_unpacked_items.append(coerced_unpacked_item)
3258 self.type = py_object_type
3260 def generate_result_code(self, code):
3261 self.generate_operation_code(code)
3263 def generate_assignment_code(self, rhs, code):
3264 if self.starred_assignment:
3265 self.generate_starred_assignment_code(rhs, code)
3266 else:
3267 self.generate_parallel_assignment_code(rhs, code)
3269 for item in self.unpacked_items:
3270 item.release(code)
3271 rhs.free_temps(code)
3273 def generate_parallel_assignment_code(self, rhs, code):
3274 # Need to work around the fact that generate_evaluation_code
3275 # allocates the temps in a rather hacky way -- the assignment
3276 # is evaluated twice, within each if-block.
3278 code.globalstate.use_utility_code(unpacking_utility_code)
3280 if rhs.type is tuple_type:
3281 tuple_check = "likely(%s != Py_None)"
3282 else:
3283 tuple_check = "PyTuple_CheckExact(%s)"
3284 code.putln(
3285 "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
3286 tuple_check % rhs.py_result(),
3287 rhs.py_result(),
3288 len(self.args)))
3289 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3290 for item in self.unpacked_items:
3291 item.allocate(code)
3292 for i in range(len(self.args)):
3293 item = self.unpacked_items[i]
3294 code.put(
3295 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3296 item.result(),
3297 i))
3298 code.put_incref(item.result(), item.ctype())
3299 value_node = self.coerced_unpacked_items[i]
3300 value_node.generate_evaluation_code(code)
3301 rhs.generate_disposal_code(code)
3303 for i in range(len(self.args)):
3304 self.args[i].generate_assignment_code(
3305 self.coerced_unpacked_items[i], code)
3307 code.putln("} else {")
3309 if rhs.type is tuple_type:
3310 code.globalstate.use_utility_code(tuple_unpacking_error_code)
3311 code.putln("__Pyx_UnpackTupleError(%s, %s);" % (
3312 rhs.py_result(), len(self.args)))
3313 code.putln(code.error_goto(self.pos))
3314 else:
3315 self.iterator.allocate(code)
3316 code.putln(
3317 "%s = PyObject_GetIter(%s); %s" % (
3318 self.iterator.result(),
3319 rhs.py_result(),
3320 code.error_goto_if_null(self.iterator.result(), self.pos)))
3321 code.put_gotref(self.iterator.py_result())
3322 rhs.generate_disposal_code(code)
3323 for i in range(len(self.args)):
3324 item = self.unpacked_items[i]
3325 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3326 self.iterator.py_result(), i)
3327 code.putln(
3328 "%s = %s; %s" % (
3329 item.result(),
3330 typecast(item.ctype(), py_object_type, unpack_code),
3331 code.error_goto_if_null(item.result(), self.pos)))
3332 code.put_gotref(item.py_result())
3333 value_node = self.coerced_unpacked_items[i]
3334 value_node.generate_evaluation_code(code)
3335 code.put_error_if_neg(self.pos,
3336 "__Pyx_EndUnpack(%s)" % (
3337 self.iterator.py_result()))
3338 if debug_disposal_code:
3339 print("UnpackNode.generate_assignment_code:")
3340 print("...generating disposal code for %s" % self.iterator)
3341 self.iterator.generate_disposal_code(code)
3342 self.iterator.free_temps(code)
3343 self.iterator.release(code)
3345 for i in range(len(self.args)):
3346 self.args[i].generate_assignment_code(
3347 self.coerced_unpacked_items[i], code)
3349 code.putln("}")
3351 def generate_starred_assignment_code(self, rhs, code):
3352 code.globalstate.use_utility_code(unpacking_utility_code)
3354 for i, arg in enumerate(self.args):
3355 if arg.is_starred:
3356 starred_target = self.unpacked_items[i]
3357 fixed_args_left = self.args[:i]
3358 fixed_args_right = self.args[i+1:]
3359 break
3361 self.iterator.allocate(code)
3362 code.putln(
3363 "%s = PyObject_GetIter(%s); %s" % (
3364 self.iterator.result(),
3365 rhs.py_result(),
3366 code.error_goto_if_null(self.iterator.result(), self.pos)))
3367 code.put_gotref(self.iterator.py_result())
3368 rhs.generate_disposal_code(code)
3370 for item in self.unpacked_items:
3371 item.allocate(code)
3372 for i in range(len(fixed_args_left)):
3373 item = self.unpacked_items[i]
3374 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3375 self.iterator.py_result(), i)
3376 code.putln(
3377 "%s = %s; %s" % (
3378 item.result(),
3379 typecast(item.ctype(), py_object_type, unpack_code),
3380 code.error_goto_if_null(item.result(), self.pos)))
3381 code.put_gotref(item.py_result())
3382 value_node = self.coerced_unpacked_items[i]
3383 value_node.generate_evaluation_code(code)
3385 target_list = starred_target.result()
3386 code.putln("%s = PySequence_List(%s); %s" % (
3387 target_list, self.iterator.py_result(),
3388 code.error_goto_if_null(target_list, self.pos)))
3389 code.put_gotref(target_list)
3390 if fixed_args_right:
3391 code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
3392 unpacked_right_args = self.unpacked_items[-len(fixed_args_right):]
3393 code.putln("if (unlikely(PyList_GET_SIZE(%s) < %d)) {" % (
3394 (target_list, len(unpacked_right_args))))
3395 code.put("__Pyx_RaiseNeedMoreValuesError(%d+PyList_GET_SIZE(%s)); %s" % (
3396 len(fixed_args_left), target_list,
3397 code.error_goto(self.pos)))
3398 code.putln('}')
3399 for i, (arg, coerced_arg) in enumerate(zip(unpacked_right_args[::-1],
3400 self.coerced_unpacked_items[::-1])):
3401 code.putln(
3402 "%s = PyList_GET_ITEM(%s, PyList_GET_SIZE(%s)-1); " % (
3403 arg.py_result(),
3404 target_list, target_list))
3405 # resize the list the hard way
3406 code.putln("((PyVarObject*)%s)->ob_size--;" % target_list)
3407 code.put_gotref(arg.py_result())
3408 coerced_arg.generate_evaluation_code(code)
3410 self.iterator.generate_disposal_code(code)
3411 self.iterator.free_temps(code)
3412 self.iterator.release(code)
3414 for i in range(len(self.args)):
3415 self.args[i].generate_assignment_code(
3416 self.coerced_unpacked_items[i], code)
3418 def annotate(self, code):
3419 for arg in self.args:
3420 arg.annotate(code)
3421 if self.unpacked_items:
3422 for arg in self.unpacked_items:
3423 arg.annotate(code)
3424 for arg in self.coerced_unpacked_items:
3425 arg.annotate(code)
3428 class TupleNode(SequenceNode):
3429 # Tuple constructor.
3431 type = tuple_type
3433 gil_message = "Constructing Python tuple"
3435 def analyse_types(self, env, skip_children=False):
3436 if len(self.args) == 0:
3437 self.is_temp = 0
3438 self.is_literal = 1
3439 else:
3440 SequenceNode.analyse_types(self, env, skip_children)
3442 def calculate_result_code(self):
3443 if len(self.args) > 0:
3444 error(self.pos, "Positive length tuples must be constructed.")
3445 else:
3446 return Naming.empty_tuple
3448 def calculate_constant_result(self):
3449 self.constant_result = tuple([
3450 arg.constant_result for arg in self.args])
3452 def compile_time_value(self, denv):
3453 values = self.compile_time_value_list(denv)
3454 try:
3455 return tuple(values)
3456 except Exception, e:
3457 self.compile_time_value_error(e)
3459 def generate_operation_code(self, code):
3460 if len(self.args) == 0:
3461 # result_code is Naming.empty_tuple
3462 return
3463 code.putln(
3464 "%s = PyTuple_New(%s); %s" % (
3465 self.result(),
3466 len(self.args),
3467 code.error_goto_if_null(self.result(), self.pos)))
3468 code.put_gotref(self.py_result())
3469 for i in range(len(self.args)):
3470 arg = self.args[i]
3471 if not arg.result_in_temp():
3472 code.put_incref(arg.result(), arg.ctype())
3473 code.putln(
3474 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3475 self.result(),
3476 i,
3477 arg.py_result()))
3478 code.put_giveref(arg.py_result())
3480 def generate_subexpr_disposal_code(self, code):
3481 # We call generate_post_assignment_code here instead
3482 # of generate_disposal_code, because values were stored
3483 # in the tuple using a reference-stealing operation.
3484 for arg in self.args:
3485 arg.generate_post_assignment_code(code)
3486 # Should NOT call free_temps -- this is invoked by the default
3487 # generate_evaluation_code which will do that.
3490 class ListNode(SequenceNode):
3491 # List constructor.
3493 # obj_conversion_errors [PyrexError] used internally
3494 # orignial_args [ExprNode] used internally
3496 obj_conversion_errors = []
3498 gil_message = "Constructing Python list"
3500 def type_dependencies(self, env):
3501 return ()
3503 def infer_type(self, env):
3504 # TOOD: Infer non-object list arrays.
3505 return list_type
3507 def analyse_expressions(self, env):
3508 SequenceNode.analyse_expressions(self, env)
3509 self.coerce_to_pyobject(env)
3511 def analyse_types(self, env):
3512 hold_errors()
3513 self.original_args = list(self.args)
3514 SequenceNode.analyse_types(self, env)
3515 self.type = list_type
3516 self.obj_conversion_errors = held_errors()
3517 release_errors(ignore=True)
3519 def coerce_to(self, dst_type, env):
3520 if dst_type.is_pyobject:
3521 for err in self.obj_conversion_errors:
3522 report_error(err)
3523 self.obj_conversion_errors = []
3524 if not self.type.subtype_of(dst_type):
3525 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3526 elif dst_type.is_ptr:
3527 base_type = dst_type.base_type
3528 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3529 for i in range(len(self.original_args)):
3530 arg = self.args[i]
3531 if isinstance(arg, CoerceToPyTypeNode):
3532 arg = arg.arg
3533 self.args[i] = arg.coerce_to(base_type, env)
3534 elif dst_type.is_struct:
3535 if len(self.args) > len(dst_type.scope.var_entries):
3536 error(self.pos, "Too may members for '%s'" % dst_type)
3537 else:
3538 if len(self.args) < len(dst_type.scope.var_entries):
3539 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3540 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3541 if isinstance(arg, CoerceToPyTypeNode):
3542 arg = arg.arg
3543 self.args[i] = arg.coerce_to(member.type, env)
3544 self.type = dst_type
3545 else:
3546 self.type = error_type
3547 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3548 return self
3550 def release_temp(self, env):
3551 if self.type.is_array:
3552 # To be valid C++, we must allocate the memory on the stack
3553 # manually and be sure not to reuse it for something else.
3554 pass
3555 else:
3556 SequenceNode.release_temp(self, env)
3558 def calculate_constant_result(self):
3559 self.constant_result = [
3560 arg.constant_result for arg in self.args]
3562 def compile_time_value(self, denv):
3563 return self.compile_time_value_list(denv)
3565 def generate_operation_code(self, code):
3566 if self.type.is_pyobject:
3567 for err in self.obj_conversion_errors:
3568 report_error(err)
3569 code.putln("%s = PyList_New(%s); %s" %
3570 (self.result(),
3571 len(self.args),
3572 code.error_goto_if_null(self.result(), self.pos)))
3573 code.put_gotref(self.py_result())
3574 for i in range(len(self.args)):
3575 arg = self.args[i]
3576 #if not arg.is_temp:
3577 if not arg.result_in_temp():
3578 code.put_incref(arg.result(), arg.ctype())
3579 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3580 (self.result(),
3581 i,
3582 arg.py_result()))
3583 code.put_giveref(arg.py_result())
3584 elif self.type.is_array:
3585 for i, arg in enumerate(self.args):
3586 code.putln("%s[%s] = %s;" % (
3587 self.result(),
3588 i,
3589 arg.result()))
3590 elif self.type.is_struct:
3591 for arg, member in zip(self.args, self.type.scope.var_entries):
3592 code.putln("%s.%s = %s;" % (
3593 self.result(),
3594 member.cname,
3595 arg.result()))
3596 else:
3597 raise InternalError("List type never specified")
3599 def generate_subexpr_disposal_code(self, code):
3600 # We call generate_post_assignment_code here instead
3601 # of generate_disposal_code, because values were stored
3602 # in the list using a reference-stealing operation.
3603 for arg in self.args:
3604 arg.generate_post_assignment_code(code)
3605 # Should NOT call free_temps -- this is invoked by the default
3606 # generate_evaluation_code which will do that.
3609 class ComprehensionNode(ExprNode):
3610 subexprs = ["target"]
3611 child_attrs = ["loop", "append"]
3613 def infer_type(self, env):
3614 return self.target.infer_type(env)
3616 def analyse_types(self, env):
3617 self.target.analyse_expressions(env)
3618 self.type = self.target.type
3619 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3620 # We are analysing declarations to late.
3621 self.loop.target.analyse_target_declaration(env)
3622 env.infer_types()
3623 self.loop.analyse_declarations(env)
3624 self.loop.analyse_expressions(env)
3626 def calculate_result_code(self):
3627 return self.target.result()
3629 def generate_result_code(self, code):
3630 self.generate_operation_code(code)
3632 def generate_operation_code(self, code):
3633 self.loop.generate_execution_code(code)
3635 def annotate(self, code):
3636 self.loop.annotate(code)
3639 class ComprehensionAppendNode(ExprNode):
3640 # Need to be careful to avoid infinite recursion:
3641 # target must not be in child_attrs/subexprs
3642 subexprs = ['expr']
3644 type = PyrexTypes.c_int_type
3646 def analyse_types(self, env):
3647 self.expr.analyse_types(env)
3648 if not self.expr.type.is_pyobject:
3649 self.expr = self.expr.coerce_to_pyobject(env)
3650 self.is_temp = 1
3652 def generate_result_code(self, code):
3653 if self.target.type is list_type:
3654 function = "PyList_Append"
3655 elif self.target.type is set_type:
3656 function = "PySet_Add"
3657 else:
3658 raise InternalError(
3659 "Invalid type for comprehension node: %s" % self.target.type)
3661 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3662 (self.result(),
3663 function,
3664 self.target.result(),
3665 self.expr.result(),
3666 code.error_goto_if(self.result(), self.pos)))
3668 class DictComprehensionAppendNode(ComprehensionAppendNode):
3669 subexprs = ['key_expr', 'value_expr']
3671 def analyse_types(self, env):
3672 self.key_expr.analyse_types(env)
3673 if not self.key_expr.type.is_pyobject:
3674 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3675 self.value_expr.analyse_types(env)
3676 if not self.value_expr.type.is_pyobject:
3677 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3678 self.is_temp = 1
3680 def generate_result_code(self, code):
3681 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3682 (self.result(),
3683 self.target.result(),
3684 self.key_expr.result(),
3685 self.value_expr.result(),
3686 code.error_goto_if(self.result(), self.pos)))
3689 class SetNode(ExprNode):
3690 # Set constructor.
3692 type = set_type
3694 subexprs = ['args']
3696 gil_message = "Constructing Python set"
3698 def analyse_types(self, env):
3699 for i in range(len(self.args)):
3700 arg = self.args[i]
3701 arg.analyse_types(env)
3702 self.args[i] = arg.coerce_to_pyobject(env)
3703 self.type = set_type
3704 self.is_temp = 1
3706 def calculate_constant_result(self):
3707 self.constant_result = set([
3708 arg.constant_result for arg in self.args])
3710 def compile_time_value(self, denv):
3711 values = [arg.compile_time_value(denv) for arg in self.args]
3712 try:
3713 return set(values)
3714 except Exception, e:
3715 self.compile_time_value_error(e)
3717 def generate_evaluation_code(self, code):
3718 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3719 self.allocate_temp_result(code)
3720 code.putln(
3721 "%s = PySet_New(0); %s" % (
3722 self.result(),
3723 code.error_goto_if_null(self.result(), self.pos)))
3724 code.put_gotref(self.py_result())
3725 for arg in self.args:
3726 arg.generate_evaluation_code(code)
3727 code.putln(
3728 code.error_goto_if_neg(
3729 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3730 self.pos))
3731 arg.generate_disposal_code(code)
3732 arg.free_temps(code)
3735 class DictNode(ExprNode):
3736 # Dictionary constructor.
3737 #
3738 # key_value_pairs [DictItemNode]
3739 #
3740 # obj_conversion_errors [PyrexError] used internally
3742 subexprs = ['key_value_pairs']
3743 is_temp = 1
3744 type = dict_type
3746 obj_conversion_errors = []
3748 def calculate_constant_result(self):
3749 self.constant_result = dict([
3750 item.constant_result for item in self.key_value_pairs])
3752 def compile_time_value(self, denv):
3753 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3754 for item in self.key_value_pairs]
3755 try:
3756 return dict(pairs)
3757 except Exception, e:
3758 self.compile_time_value_error(e)
3760 def type_dependencies(self, env):
3761 return ()
3763 def infer_type(self, env):
3764 # TOOD: Infer struct constructors.
3765 return dict_type
3767 def analyse_types(self, env):
3768 hold_errors()
3769 for item in self.key_value_pairs:
3770 item.analyse_types(env)
3771 self.obj_conversion_errors = held_errors()
3772 release_errors(ignore=True)
3774 def coerce_to(self, dst_type, env):
3775 if dst_type.is_pyobject:
3776 self.release_errors()
3777 if not self.type.subtype_of(dst_type):
3778 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3779 elif dst_type.is_struct_or_union:
3780 self.type = dst_type
3781 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3782 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3783 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3784 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3785 for item in self.key_value_pairs:
3786 if isinstance(item.key, CoerceToPyTypeNode):
3787 item.key = item.key.arg
3788 if not isinstance(item.key, (UnicodeNode, StringNode, BytesNode)):
3789 error(item.key.pos, "Invalid struct field identifier")
3790 item.key = StringNode(item.key.pos, value="<error>")
3791 else:
3792 key = str(item.key.value) # converts string literals to unicode in Py3
3793 member = dst_type.scope.lookup_here(key)
3794 if not member:
3795 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key))
3796 else:
3797 value = item.value
3798 if isinstance(value, CoerceToPyTypeNode):
3799 value = value.arg
3800 item.value = value.coerce_to(member.type, env)
3801 else:
3802 self.type = error_type
3803 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3804 return self
3806 def release_errors(self):
3807 for err in self.obj_conversion_errors:
3808 report_error(err)
3809 self.obj_conversion_errors = []
3811 gil_message = "Constructing Python dict"
3813 def generate_evaluation_code(self, code):
3814 # Custom method used here because key-value
3815 # pairs are evaluated and used one at a time.
3816 code.mark_pos(self.pos)
3817 self.allocate_temp_result(code)
3818 if self.type.is_pyobject:
3819 self.release_errors()
3820 code.putln(
3821 "%s = PyDict_New(); %s" % (
3822 self.result(),
3823 code.error_goto_if_null(self.result(), self.pos)))
3824 code.put_gotref(self.py_result())
3825 for item in self.key_value_pairs:
3826 item.generate_evaluation_code(code)
3827 if self.type.is_pyobject:
3828 code.put_error_if_neg(self.pos,
3829 "PyDict_SetItem(%s, %s, %s)" % (
3830 self.result(),
3831 item.key.py_result(),
3832 item.value.py_result()))
3833 else:
3834 code.putln("%s.%s = %s;" % (
3835 self.result(),
3836 item.key.value,
3837 item.value.result()))
3838 item.generate_disposal_code(code)
3839 item.free_temps(code)
3841 def annotate(self, code):
3842 for item in self.key_value_pairs:
3843 item.annotate(code)
3845 class DictItemNode(ExprNode):
3846 # Represents a single item in a DictNode
3847 #
3848 # key ExprNode
3849 # value ExprNode
3850 subexprs = ['key', 'value']
3852 nogil_check = None # Parent DictNode takes care of it
3854 def calculate_constant_result(self):
3855 self.constant_result = (
3856 self.key.constant_result, self.value.constant_result)
3858 def analyse_types(self, env):
3859 self.key.analyse_types(env)
3860 self.value.analyse_types(env)
3861 self.key = self.key.coerce_to_pyobject(env)
3862 self.value = self.value.coerce_to_pyobject(env)
3864 def generate_evaluation_code(self, code):
3865 self.key.generate_evaluation_code(code)
3866 self.value.generate_evaluation_code(code)
3868 def generate_disposal_code(self, code):
3869 self.key.generate_disposal_code(code)
3870 self.value.generate_disposal_code(code)
3872 def free_temps(self, code):
3873 self.key.free_temps(code)
3874 self.value.free_temps(code)
3876 def __iter__(self):
3877 return iter([self.key, self.value])
3880 class ClassNode(ExprNode):
3881 # Helper class used in the implementation of Python
3882 # class definitions. Constructs a class object given
3883 # a name, tuple of bases and class dictionary.
3884 #
3885 # name EncodedString Name of the class
3886 # bases ExprNode Base class tuple
3887 # dict ExprNode Class dict (not owned by this node)
3888 # doc ExprNode or None Doc string
3889 # module_name string Name of defining module
3891 subexprs = ['bases', 'doc']
3893 def analyse_types(self, env):
3894 self.bases.analyse_types(env)
3895 if self.doc:
3896 self.doc.analyse_types(env)
3897 self.doc = self.doc.coerce_to_pyobject(env)
3898 self.module_name = env.global_scope().qualified_name
3899 self.type = py_object_type
3900 self.is_temp = 1
3901 env.use_utility_code(create_class_utility_code);
3903 gil_message = "Constructing Python class"
3905 def generate_result_code(self, code):
3906 cname = code.intern_identifier(self.name)
3907 if self.doc:
3908 code.put_error_if_neg(self.pos,
3909 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3910 self.dict.py_result(),
3911 self.doc.py_result()))
3912 code.putln(
3913 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3914 self.result(),
3915 self.bases.py_result(),
3916 self.dict.py_result(),
3917 cname,
3918 self.module_name,
3919 code.error_goto_if_null(self.result(), self.pos)))
3920 code.put_gotref(self.py_result())
3923 class UnboundMethodNode(ExprNode):
3924 # Helper class used in the implementation of Python
3925 # class definitions. Constructs an unbound method
3926 # object from a class and a function.
3927 #
3928 # function ExprNode Function object
3930 type = py_object_type
3931 is_temp = 1
3933 subexprs = ['function']
3935 def analyse_types(self, env):
3936 self.function.analyse_types(env)
3938 gil_message = "Constructing an unbound method"
3940 def generate_result_code(self, code):
3941 class_cname = code.pyclass_stack[-1].classobj.result()
3942 code.putln(
3943 "%s = PyMethod_New(%s, 0, %s); %s" % (
3944 self.result(),
3945 self.function.py_result(),
3946 class_cname,
3947 code.error_goto_if_null(self.result(), self.pos)))
3948 code.put_gotref(self.py_result())
3950 class PyCFunctionNode(AtomicExprNode):
3951 # Helper class used in the implementation of Python
3952 # class definitions. Constructs a PyCFunction object
3953 # from a PyMethodDef struct.
3954 #
3955 # pymethdef_cname string PyMethodDef structure
3957 type = py_object_type
3958 is_temp = 1
3960 def analyse_types(self, env):
3961 pass
3963 gil_message = "Constructing Python function"
3965 def generate_result_code(self, code):
3966 code.putln(
3967 "%s = PyCFunction_New(&%s, 0); %s" % (
3968 self.result(),
3969 self.pymethdef_cname,
3970 code.error_goto_if_null(self.result(), self.pos)))
3971 code.put_gotref(self.py_result())
3973 #-------------------------------------------------------------------
3974 #
3975 # Unary operator nodes
3976 #
3977 #-------------------------------------------------------------------
3979 compile_time_unary_operators = {
3980 'not': operator.not_,
3981 '~': operator.inv,
3982 '-': operator.neg,
3983 '+': operator.pos,
3984 }
3986 class UnopNode(ExprNode):
3987 # operator string
3988 # operand ExprNode
3989 #
3990 # Processing during analyse_expressions phase:
3991 #
3992 # analyse_c_operation
3993 # Called when the operand is not a pyobject.
3994 # - Check operand type and coerce if needed.
3995 # - Determine result type and result code fragment.
3996 # - Allocate temporary for result if needed.
3998 subexprs = ['operand']
3999 infix = True
4001 def calculate_constant_result(self):
4002 func = compile_time_unary_operators[self.operator]
4003 self.constant_result = func(self.operand.constant_result)
4005 def compile_time_value(self, denv):
4006 func = compile_time_unary_operators.get(self.operator)
4007 if not func:
4008 error(self.pos,
4009 "Unary '%s' not supported in compile-time expression"
4010 % self.operator)
4011 operand = self.operand.compile_time_value(denv)
4012 try:
4013 return func(operand)
4014 except Exception, e:
4015 self.compile_time_value_error(e)
4017 def infer_type(self, env):
4018 return self.operand.infer_type(env)
4020 def analyse_types(self, env):
4021 self.operand.analyse_types(env)
4022 if self.is_py_operation():
4023 self.coerce_operand_to_pyobject(env)
4024 self.type = py_object_type
4025 self.is_temp = 1
4026 else:
4027 self.analyse_c_operation(env)
4029 def check_const(self):
4030 return self.operand.check_const()
4032 def is_py_operation(self):
4033 return self.operand.type.is_pyobject
4035 def nogil_check(self, env):
4036 if self.is_py_operation():
4037 self.gil_error()
4039 def coerce_operand_to_pyobject(self, env):
4040 self.operand = self.operand.coerce_to_pyobject(env)
4042 def generate_result_code(self, code):
4043 if self.operand.type.is_pyobject:
4044 self.generate_py_operation_code(code)
4046 def generate_py_operation_code(self, code):
4047 function = self.py_operation_function()
4048 code.putln(
4049 "%s = %s(%s); %s" % (
4050 self.result(),
4051 function,
4052 self.operand.py_result(),
4053 code.error_goto_if_null(self.result(), self.pos)))
4054 code.put_gotref(self.py_result())
4056 def type_error(self):
4057 if not self.operand.type.is_error:
4058 error(self.pos, "Invalid operand type for '%s' (%s)" %
4059 (self.operator, self.operand.type))
4060 self.type = PyrexTypes.error_type
4063 class NotNode(ExprNode):
4064 # 'not' operator
4065 #
4066 # operand ExprNode
4068 type = PyrexTypes.c_bint_type
4070 subexprs = ['operand']
4072 def calculate_constant_result(self):
4073 self.constant_result = not self.operand.constant_result
4075 def compile_time_value(self, denv):
4076 operand = self.operand.compile_time_value(denv)
4077 try:
4078 return not operand
4079 except Exception, e:
4080 self.compile_time_value_error(e)
4082 def infer_type(self, env):
4083 return PyrexTypes.c_bint_type
4085 def analyse_types(self, env):
4086 self.operand.analyse_types(env)
4087 self.operand = self.operand.coerce_to_boolean(env)
4089 def calculate_result_code(self):
4090 return "(!%s)" % self.operand.result()
4092 def generate_result_code(self, code):
4093 pass
4096 class UnaryPlusNode(UnopNode):
4097 # unary '+' operator
4099 operator = '+'
4101 def analyse_c_operation(self, env):
4102 self.type = self.operand.type
4104 def py_operation_function(self):
4105 return "PyNumber_Positive"
4107 def calculate_result_code(self):
4108 return self.operand.result()
4111 class UnaryMinusNode(UnopNode):
4112 # unary '-' operator
4114 operator = '-'
4116 def analyse_c_operation(self, env):
4117 if self.operand.type.is_numeric:
4118 self.type = self.operand.type
4119 else:
4120 self.type_error()
4121 if self.type.is_complex:
4122 self.infix = False
4124 def py_operation_function(self):
4125 return "PyNumber_Negative"
4127 def calculate_result_code(self):
4128 if self.infix:
4129 return "(-%s)" % self.operand.result()
4130 else:
4131 return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result())
4133 def get_constant_c_result_code(self):
4134 value = self.operand.get_constant_c_result_code()
4135 if value:
4136 return "(-%s)" % (value)
4138 class TildeNode(UnopNode):
4139 # unary '~' operator
4141 def analyse_c_operation(self, env):
4142 if self.operand.type.is_int:
4143 self.type = self.operand.type
4144 else:
4145 self.type_error()
4147 def py_operation_function(self):
4148 return "PyNumber_Invert"
4150 def calculate_result_code(self):
4151 return "(~%s)" % self.operand.result()
4154 class AmpersandNode(ExprNode):
4155 # The C address-of operator.
4156 #
4157 # operand ExprNode
4159 subexprs = ['operand']
4161 def infer_type(self, env):
4162 return PyrexTypes.c_ptr_type(self.operand.infer_type(env))
4164 def analyse_types(self, env):
4165 self.operand.analyse_types(env)
4166 argtype = self.operand.type
4167 if not (argtype.is_cfunction or self.operand.is_lvalue()):
4168 self.error("Taking address of non-lvalue")
4169 return
4170 if argtype.is_pyobject:
4171 self.error("Cannot take address of Python variable")
4172 return
4173 self.type = PyrexTypes.c_ptr_type(argtype)
4175 def check_const(self):
4176 return self.operand.check_const_addr()
4178 def error(self, mess):
4179 error(self.pos, mess)
4180 self.type = PyrexTypes.error_type
4181 self.result_code = "<error>"
4183 def calculate_result_code(self):
4184 return "(&%s)" % self.operand.result()
4186 def generate_result_code(self, code):
4187 pass
4190 unop_node_classes = {
4191 "+": UnaryPlusNode,
4192 "-": UnaryMinusNode,
4193 "~": TildeNode,
4194 }
4196 def unop_node(pos, operator, operand):
4197 # Construct unnop node of appropriate class for
4198 # given operator.
4199 if isinstance(operand, IntNode) and operator == '-':
4200 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
4201 elif isinstance(operand, UnopNode) and operand.operator == operator:
4202 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
4203 return unop_node_classes[operator](pos,
4204 operator = operator,
4205 operand = operand)
4208 class TypecastNode(ExprNode):
4209 # C type cast
4210 #
4211 # operand ExprNode
4212 # base_type CBaseTypeNode
4213 # declarator CDeclaratorNode
4214 #
4215 # If used from a transform, one can if wanted specify the attribute
4216 # "type" directly and leave base_type and declarator to None
4218 subexprs = ['operand']
4219 base_type = declarator = type = None
4221 def type_dependencies(self, env):
4222 return ()
4224 def infer_type(self, env):
4225 if self.type is None:
4226 base_type = self.base_type.analyse(env)
4227 _, self.type = self.declarator.analyse(base_type, env)
4228 return self.type
4230 def analyse_types(self, env):
4231 if self.type is None:
4232 base_type = self.base_type.analyse(env)
4233 _, self.type = self.declarator.analyse(base_type, env)
4234 if self.type.is_cfunction:
4235 error(self.pos,
4236 "Cannot cast to a function type")
4237 self.type = PyrexTypes.error_type
4238 self.operand.analyse_types(env)
4239 to_py = self.type.is_pyobject
4240 from_py = self.operand.type.is_pyobject
4241 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
4242 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
4243 if to_py and not from_py:
4244 if self.operand.type.create_to_py_utility_code(env):
4245 self.result_ctype = py_object_type
4246 self.operand = self.operand.coerce_to_pyobject(env)
4247 else:
4248 if self.operand.type.is_ptr:
4249 if not (self.operand.type.base_type.is_void or self.operand.type.base_type.is_struct):
4250 error(self.pos, "Python objects cannot be cast from pointers of primitive types")
4251 else:
4252 # Should this be an error?
4253 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
4254 self.operand = self.operand.coerce_to_simple(env)
4255 elif from_py and not to_py:
4256 if self.type.create_from_py_utility_code(env):
4257 self.operand = self.operand.coerce_to(self.type, env)
4258 elif self.type.is_ptr:
4259 if not (self.type.base_type.is_void or self.type.base_type.is_struct):
4260 error(self.pos, "Python objects cannot be cast to pointers of primitive types")
4261 else:
4262 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
4263 elif from_py and to_py:
4264 if self.typecheck and self.type.is_extension_type:
4265 self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True)
4267 def nogil_check(self, env):
4268 if self.type and self.type.is_pyobject and self.is_temp:
4269 self.gil_error()
4271 def check_const(self):
4272 return self.operand.check_const()
4274 def calculate_constant_result(self):
4275 # we usually do not know the result of a type cast at code
4276 # generation time
4277 pass
4279 def calculate_result_code(self):
4280 opnd = self.operand
4281 return self.type.cast_code(opnd.result())
4283 def get_constant_c_result_code(self):
4284 operand_result = self.operand.get_constant_c_result_code()
4285 if operand_result:
4286 return self.type.cast_code(operand_result)
4288 def result_as(self, type):
4289 if self.type.is_pyobject and not self.is_temp:
4290 # Optimise away some unnecessary casting
4291 return self.operand.result_as(type)
4292 else:
4293 return ExprNode.result_as(self, type)
4295 def generate_result_code(self, code):
4296 if self.is_temp:
4297 code.putln(
4298 "%s = (PyObject *)%s;" % (
4299 self.result(),
4300 self.operand.result()))
4301 code.put_incref(self.result(), self.ctype())
4304 class SizeofNode(ExprNode):
4305 # Abstract base class for sizeof(x) expression nodes.
4307 type = PyrexTypes.c_size_t_type
4309 def check_const(self):
4310 return True
4312 def generate_result_code(self, code):
4313 pass
4316 class SizeofTypeNode(SizeofNode):
4317 # C sizeof function applied to a type
4318 #
4319 # base_type CBaseTypeNode
4320 # declarator CDeclaratorNode
4322 subexprs = []
4323 arg_type = None
4325 def analyse_types(self, env):
4326 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
4327 # this could be better handled by more uniformly treating types as runtime-available objects
4328 if 0 and self.base_type.module_path:
4329 path = self.base_type.module_path
4330 obj = env.lookup(path[0])
4331 if obj.as_module is None:
4332 operand = NameNode(pos=self.pos, name=path[0])
4333 for attr in path[1:]:
4334 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
4335 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
4336 self.operand = operand
4337 self.__class__ = SizeofVarNode
4338 self.analyse_types(env)
4339 return
4340 if self.arg_type is None:
4341 base_type = self.base_type.analyse(env)
4342 _, arg_type = self.declarator.analyse(base_type, env)
4343 self.arg_type = arg_type
4344 self.check_type()
4346 def check_type(self):
4347 arg_type = self.arg_type
4348 if arg_type.is_pyobject and not arg_type.is_extension_type:
4349 error(self.pos, "Cannot take sizeof Python object")
4350 elif arg_type.is_void:
4351 error(self.pos, "Cannot take sizeof void")
4352 elif not arg_type.is_complete():
4353 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
4355 def calculate_result_code(self):
4356 if self.arg_type.is_extension_type:
4357 # the size of the pointer is boring
4358 # we want the size of the actual struct
4359 arg_code = self.arg_type.declaration_code("", deref=1)
4360 else:
4361 arg_code = self.arg_type.declaration_code("")
4362 return "(sizeof(%s))" % arg_code
4365 class SizeofVarNode(SizeofNode):
4366 # C sizeof function applied to a variable
4367 #
4368 # operand ExprNode
4370 subexprs = ['operand']
4372 def analyse_types(self, env):
4373 # We may actually be looking at a type rather than a variable...
4374 # If we are, traditional analysis would fail...
4375 operand_as_type = self.operand.analyse_as_type(env)
4376 if operand_as_type:
4377 self.arg_type = operand_as_type
4378 self.__class__ = SizeofTypeNode
4379 self.check_type()
4380 else:
4381 self.operand.analyse_types(env)
4383 def calculate_result_code(self):
4384 return "(sizeof(%s))" % self.operand.result()
4386 def generate_result_code(self, code):
4387 pass
4389 class TypeofNode(ExprNode):
4390 # Compile-time type of an expression, as a string.
4391 #
4392 # operand ExprNode
4393 # literal StringNode # internal
4395 literal = None
4396 type = py_object_type
4398 subexprs = ['operand', 'literal']
4400 def analyse_types(self, env):
4401 self.operand.analyse_types(env)
4402 self.literal = StringNode(
4403 self.pos, value=StringEncoding.EncodedString(str(self.operand.type)))
4404 self.literal.analyse_types(env)
4405 self.literal = self.literal.coerce_to_pyobject(env)
4407 def generate_evaluation_code(self, code):
4408 self.literal.generate_evaluation_code(code)
4410 def calculate_result_code(self):
4411 return self.literal.calculate_result_code()
4413 #-------------------------------------------------------------------
4414 #
4415 # Binary operator nodes
4416 #
4417 #-------------------------------------------------------------------
4419 def _not_in(x, seq):
4420 return x not in seq
4422 compile_time_binary_operators = {
4423 '<': operator.lt,
4424 '<=': operator.le,
4425 '==': operator.eq,
4426 '!=': operator.ne,
4427 '>=': operator.ge,
4428 '>': operator.gt,
4429 'is': operator.is_,
4430 'is_not': operator.is_not,
4431 '+': operator.add,
4432 '&': operator.and_,
4433 '/': operator.truediv,
4434 '//': operator.floordiv,
4435 '<<': operator.lshift,
4436 '%': operator.mod,
4437 '*': operator.mul,
4438 '|': operator.or_,
4439 '**': operator.pow,
4440 '>>': operator.rshift,
4441 '-': operator.sub,
4442 '^': operator.xor,
4443 'in': operator.contains,
4444 'not_in': _not_in,
4445 }
4447 def get_compile_time_binop(node):
4448 func = compile_time_binary_operators.get(node.operator)
4449 if not func:
4450 error(node.pos,
4451 "Binary '%s' not supported in compile-time expression"
4452 % node.operator)
4453 return func
4455 class BinopNode(ExprNode):
4456 # operator string
4457 # operand1 ExprNode
4458 # operand2 ExprNode
4459 #
4460 # Processing during analyse_expressions phase:
4461 #
4462 # analyse_c_operation
4463 # Called when neither operand is a pyobject.
4464 # - Check operand types and coerce if needed.
4465 # - Determine result type and result code fragment.
4466 # - Allocate temporary for result if needed.
4468 subexprs = ['operand1', 'operand2']
4470 def calculate_constant_result(self):
4471 func = compile_time_binary_operators[self.operator]
4472 self.constant_result = func(
4473 self.operand1.constant_result,
4474 self.operand2.constant_result)
4476 def compile_time_value(self, denv):
4477 func = get_compile_time_binop(self)
4478 operand1 = self.operand1.compile_time_value(denv)
4479 operand2 = self.operand2.compile_time_value(denv)
4480 try:
4481 return func(operand1, operand2)
4482 except Exception, e:
4483 self.compile_time_value_error(e)
4485 def infer_type(self, env):
4486 return self.result_type(self.operand1.infer_type(env),
4487 self.operand2.infer_type(env))
4489 def analyse_types(self, env):
4490 self.operand1.analyse_types(env)
4491 self.operand2.analyse_types(env)
4492 if self.is_py_operation():
4493 self.coerce_operands_to_pyobjects(env)
4494 self.type = py_object_type
4495 self.is_temp = 1
4496 else:
4497 self.analyse_c_operation(env)
4499 def is_py_operation(self):
4500 return self.is_py_operation_types(self.operand1.type, self.operand2.type)
4502 def is_py_operation_types(self, type1, type2):
4503 return type1.is_pyobject or type2.is_pyobject
4505 def result_type(self, type1, type2):
4506 if self.is_py_operation_types(type1, type2):
4507 return py_object_type
4508 else:
4509 return self.compute_c_result_type(type1, type2)
4511 def nogil_check(self, env):
4512 if self.is_py_operation():
4513 self.gil_error()
4515 def coerce_operands_to_pyobjects(self, env):
4516 self.operand1 = self.operand1.coerce_to_pyobject(env)
4517 self.operand2 = self.operand2.coerce_to_pyobject(env)
4519 def check_const(self):
4520 return self.operand1.check_const() and self.operand2.check_const()
4522 def generate_result_code(self, code):
4523 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4524 if self.operand1.type.is_pyobject:
4525 function = self.py_operation_function()
4526 if function == "PyNumber_Power":
4527 extra_args = ", Py_None"
4528 else:
4529 extra_args = ""
4530 code.putln(
4531 "%s = %s(%s, %s%s); %s" % (
4532 self.result(),
4533 function,
4534 self.operand1.py_result(),
4535 self.operand2.py_result(),
4536 extra_args,
4537 code.error_goto_if_null(self.result(), self.pos)))
4538 code.put_gotref(self.py_result())
4540 def type_error(self):
4541 if not (self.operand1.type.is_error
4542 or self.operand2.type.is_error):
4543 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4544 (self.operator, self.operand1.type,
4545 self.operand2.type))
4546 self.type = PyrexTypes.error_type
4549 class NumBinopNode(BinopNode):
4550 # Binary operation taking numeric arguments.
4552 infix = True
4554 def analyse_c_operation(self, env):
4555 type1 = self.operand1.type
4556 type2 = self.operand2.type
4557 self.type = self.compute_c_result_type(type1, type2)
4558 if not self.type:
4559 self.type_error()
4560 return
4561 if self.type.is_complex:
4562 self.infix = False
4563 if not self.infix:
4564 self.operand1 = self.operand1.coerce_to(self.type, env)
4565 self.operand2 = self.operand2.coerce_to(self.type, env)
4567 def compute_c_result_type(self, type1, type2):
4568 if self.c_types_okay(type1, type2):
4569 return PyrexTypes.widest_numeric_type(type1, type2)
4570 else:
4571 return None
4573 def get_constant_c_result_code(self):
4574 value1 = self.operand1.get_constant_c_result_code()
4575 value2 = self.operand2.get_constant_c_result_code()
4576 if value1 and value2:
4577 return "(%s %s %s)" % (value1, self.operator, value2)
4578 else:
4579 return None
4581 def c_types_okay(self, type1, type2):
4582 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4583 return (type1.is_numeric or type1.is_enum) \
4584 and (type2.is_numeric or type2.is_enum)
4586 def calculate_result_code(self):
4587 if self.infix:
4588 return "(%s %s %s)" % (
4589 self.operand1.result(),
4590 self.operator,
4591 self.operand2.result())
4592 else:
4593 func = self.type.binary_op(self.operator)
4594 if func is None:
4595 error(self.pos, "binary operator %s not supported for %s" % (self.operator, self.type))
4596 return "%s(%s, %s)" % (
4597 func,
4598 self.operand1.result(),
4599 self.operand2.result())
4601 def py_operation_function(self):
4602 return self.py_functions[self.operator]
4604 py_functions = {
4605 "|": "PyNumber_Or",
4606 "^": "PyNumber_Xor",
4607 "&": "PyNumber_And",
4608 "<<": "PyNumber_Lshift",
4609 ">>": "PyNumber_Rshift",
4610 "+": "PyNumber_Add",
4611 "-": "PyNumber_Subtract",
4612 "*": "PyNumber_Multiply",
4613 "/": "__Pyx_PyNumber_Divide",
4614 "//": "PyNumber_FloorDivide",
4615 "%": "PyNumber_Remainder",
4616 "**": "PyNumber_Power"
4617 }
4620 class IntBinopNode(NumBinopNode):
4621 # Binary operation taking integer arguments.
4623 def c_types_okay(self, type1, type2):
4624 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4625 return (type1.is_int or type1.is_enum) \
4626 and (type2.is_int or type2.is_enum)
4629 class AddNode(NumBinopNode):
4630 # '+' operator.
4632 def is_py_operation_types(self, type1, type2):
4633 if type1.is_string and type2.is_string:
4634 return 1
4635 else:
4636 return NumBinopNode.is_py_operation_types(self, type1, type2)
4638 def compute_c_result_type(self, type1, type2):
4639 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4640 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4641 return type1
4642 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4643 return type2
4644 else:
4645 return NumBinopNode.compute_c_result_type(
4646 self, type1, type2)
4649 class SubNode(NumBinopNode):
4650 # '-' operator.
4652 def compute_c_result_type(self, type1, type2):
4653 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4654 return type1
4655 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4656 return PyrexTypes.c_int_type
4657 else:
4658 return NumBinopNode.compute_c_result_type(
4659 self, type1, type2)
4662 class MulNode(NumBinopNode):
4663 # '*' operator.
4665 def is_py_operation_types(self, type1, type2):
4666 if (type1.is_string and type2.is_int) \
4667 or (type2.is_string and type1.is_int):
4668 return 1
4669 else:
4670 return NumBinopNode.is_py_operation_types(self, type1, type2)
4673 class DivNode(NumBinopNode):
4674 # '/' or '//' operator.
4676 cdivision = None
4677 truedivision = None # == "unknown" if operator == '/'
4678 ctruedivision = False
4679 cdivision_warnings = False
4680 zerodivision_check = None
4682 def find_compile_time_binary_operator(self, op1, op2):
4683 func = compile_time_binary_operators[self.operator]
4684 if self.operator == '/' and self.truedivision is None:
4685 # => true div for floats, floor div for integers
4686 if isinstance(op1, (int,long)) and isinstance(op2, (int,long)):
4687 func = compile_time_binary_operators['//']
4688 return func
4690 def calculate_constant_result(self):
4691 op1 = self.operand1.constant_result
4692 op2 = self.operand2.constant_result
4693 func = self.find_compile_time_binary_operator(op1, op2)
4694 self.constant_result = func(
4695 self.operand1.constant_result,
4696 self.operand2.constant_result)
4698 def compile_time_value(self, denv):
4699 operand1 = self.operand1.compile_time_value(denv)
4700 operand2 = self.operand2.compile_time_value(denv)
4701 try:
4702 func = self.find_compile_time_binary_operator(
4703 self, operand1, operand2)
4704 return func(operand1, operand2)
4705 except Exception, e:
4706 self.compile_time_value_error(e)
4708 def analyse_types(self, env):
4709 if self.cdivision or env.directives['cdivision']:
4710 self.ctruedivision = False
4711 else:
4712 self.ctruedivision = self.truedivision
4713 NumBinopNode.analyse_types(self, env)
4714 if not self.type.is_pyobject:
4715 self.zerodivision_check = (
4716 self.cdivision is None and not env.directives['cdivision']
4717 and (self.operand2.constant_result is not_a_constant or
4718 self.operand2.constant_result == 0))
4719 if self.zerodivision_check or env.directives['cdivision_warnings']:
4720 # Need to check ahead of time to warn or raise zero division error
4721 self.operand1 = self.operand1.coerce_to_simple(env)
4722 self.operand2 = self.operand2.coerce_to_simple(env)
4723 if env.nogil:
4724 error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
4726 def compute_c_result_type(self, type1, type2):
4727 if self.operator == '/' and self.ctruedivision:
4728 if not type1.is_float and not type2.is_float:
4729 widest_type = PyrexTypes.widest_numeric_type(type1, PyrexTypes.c_double_type)
4730 widest_type = PyrexTypes.widest_numeric_type(type2, widest_type)
4731 return widest_type
4732 return NumBinopNode.compute_c_result_type(self, type1, type2)
4734 def zero_division_message(self):
4735 if self.type.is_int:
4736 return "integer division or modulo by zero"
4737 else:
4738 return "float division"
4740 def generate_evaluation_code(self, code):
4741 if not self.type.is_pyobject and not self.type.is_complex:
4742 if self.cdivision is None:
4743 self.cdivision = (code.globalstate.directives['cdivision']
4744 or not self.type.signed
4745 or self.type.is_float)
4746 if not self.cdivision:
4747 code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
4748 NumBinopNode.generate_evaluation_code(self, code)
4749 self.generate_div_warning_code(code)
4751 def generate_div_warning_code(self, code):
4752 if not self.type.is_pyobject:
4753 if self.zerodivision_check:
4754 if not self.infix:
4755 zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.operand2.result())
4756 else:
4757 zero_test = "%s == 0" % self.operand2.result()
4758 code.putln("if (unlikely(%s)) {" % zero_test)
4759 code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
4760 code.putln(code.error_goto(self.pos))
4761 code.putln("}")
4762 if self.type.is_int and self.type.signed and self.operator != '%':
4763 code.globalstate.use_utility_code(division_overflow_test_code)
4764 code.putln("else if (sizeof(%s) == sizeof(long) && unlikely(%s == -1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % (
4765 self.type.declaration_code(''),
4766 self.operand2.result(),
4767 self.operand1.result()))
4768 code.putln('PyErr_Format(PyExc_OverflowError, "value too large to perform division");')
4769 code.putln(code.error_goto(self.pos))
4770 code.putln("}")
4771 if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
4772 code.globalstate.use_utility_code(cdivision_warning_utility_code)
4773 code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
4774 self.operand1.result(),
4775 self.operand2.result()))
4776 code.putln(code.set_error_info(self.pos));
4777 code.put("if (__Pyx_cdivision_warning()) ")
4778 code.put_goto(code.error_label)
4779 code.putln("}")
4781 def calculate_result_code(self):
4782 if self.type.is_complex:
4783 return NumBinopNode.calculate_result_code(self)
4784 elif self.type.is_float and self.operator == '//':
4785 return "floor(%s / %s)" % (
4786 self.operand1.result(),
4787 self.operand2.result())
4788 elif self.truedivision or self.cdivision:
4789 op1 = self.operand1.result()
4790 op2 = self.operand2.result()
4791 if self.truedivision:
4792 if self.type != self.operand1.type:
4793 op1 = self.type.cast_code(op1)
4794 if self.type != self.operand2.type:
4795 op2 = self.type.cast_code(op2)
4796 return "(%s / %s)" % (op1, op2)
4797 else:
4798 return "__Pyx_div_%s(%s, %s)" % (
4799 self.type.specalization_name(),
4800 self.operand1.result(),
4801 self.operand2.result())
4804 class ModNode(DivNode):
4805 # '%' operator.
4807 def is_py_operation_types(self, type1, type2):
4808 return (type1.is_string
4809 or type2.is_string
4810 or NumBinopNode.is_py_operation_types(self, type1, type2))
4812 def zero_division_message(self):
4813 if self.type.is_int:
4814 return "integer division or modulo by zero"
4815 else:
4816 return "float divmod()"
4818 def generate_evaluation_code(self, code):
4819 if not self.type.is_pyobject:
4820 if self.cdivision is None:
4821 self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
4822 if not self.cdivision:
4823 if self.type.is_int:
4824 code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
4825 else:
4826 code.globalstate.use_utility_code(
4827 mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
4828 NumBinopNode.generate_evaluation_code(self, code)
4829 self.generate_div_warning_code(code)
4831 def calculate_result_code(self):
4832 if self.cdivision:
4833 if self.type.is_float:
4834 return "fmod%s(%s, %s)" % (
4835 self.type.math_h_modifier,
4836 self.operand1.result(),
4837 self.operand2.result())
4838 else:
4839 return "(%s %% %s)" % (
4840 self.operand1.result(),
4841 self.operand2.result())
4842 else:
4843 return "__Pyx_mod_%s(%s, %s)" % (
4844 self.type.specalization_name(),
4845 self.operand1.result(),
4846 self.operand2.result())
4848 class PowNode(NumBinopNode):
4849 # '**' operator.
4851 def analyse_c_operation(self, env):
4852 NumBinopNode.analyse_c_operation(self, env)
4853 if self.type.is_complex:
4854 error(self.pos, "complex powers not yet supported")
4855 self.pow_func = "<error>"
4856 elif self.type.is_float:
4857 self.pow_func = "pow"
4858 else:
4859 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
4860 env.use_utility_code(
4861 int_pow_utility_code.specialize(func_name=self.pow_func,
4862 type=self.type.declaration_code('')))
4864 def calculate_result_code(self):
4865 return "%s(%s, %s)" % (
4866 self.pow_func,
4867 self.operand1.result(),
4868 self.operand2.result())
4871 # Note: This class is temporary "shut down" into an ineffective mode temp
4872 # allocation mode.
4873 #
4874 # More sophisticated temp reuse was going on before,
4875 # one could have a look at adding this again after /all/ classes
4876 # are converted to the new temp scheme. (The temp juggling cannot work
4877 # otherwise).
4878 class BoolBinopNode(ExprNode):
4879 # Short-circuiting boolean operation.
4880 #
4881 # operator string
4882 # operand1 ExprNode
4883 # operand2 ExprNode
4885 subexprs = ['operand1', 'operand2']
4887 def infer_type(self, env):
4888 type1 = self.operand1.infer_type(env)
4889 type2 = self.operand2.infer_type(env)
4890 return PyrexTypes.spanning_type(type1, type2)
4892 def calculate_constant_result(self):
4893 if self.operator == 'and':
4894 self.constant_result = \
4895 self.operand1.constant_result and \
4896 self.operand2.constant_result
4897 else:
4898 self.constant_result = \
4899 self.operand1.constant_result or \
4900 self.operand2.constant_result
4902 def compile_time_value(self, denv):
4903 if self.operator == 'and':
4904 return self.operand1.compile_time_value(denv) \
4905 and self.operand2.compile_time_value(denv)
4906 else:
4907 return self.operand1.compile_time_value(denv) \
4908 or self.operand2.compile_time_value(denv)
4910 def coerce_to_boolean(self, env):
4911 self.operand1 = self.operand1.coerce_to_boolean(env)
4912 self.operand2 = self.operand2.coerce_to_boolean(env)
4913 self.type = PyrexTypes.c_bint_type
4914 return self
4916 def analyse_types(self, env):
4917 self.operand1.analyse_types(env)
4918 self.operand2.analyse_types(env)
4919 self.type = PyrexTypes.spanning_type(self.operand1.type, self.operand2.type)
4920 self.operand1 = self.operand1.coerce_to(self.type, env)
4921 self.operand2 = self.operand2.coerce_to(self.type, env)
4923 # For what we're about to do, it's vital that
4924 # both operands be temp nodes.
4925 self.operand1 = self.operand1.coerce_to_simple(env)
4926 self.operand2 = self.operand2.coerce_to_simple(env)
4927 self.is_temp = 1
4929 gil_message = "Truth-testing Python object"
4931 def check_const(self):
4932 return self.operand1.check_const() and self.operand2.check_const()
4934 def generate_evaluation_code(self, code):
4935 code.mark_pos(self.pos)
4936 self.operand1.generate_evaluation_code(code)
4937 test_result, uses_temp = self.generate_operand1_test(code)
4938 if self.operator == 'and':
4939 sense = ""
4940 else:
4941 sense = "!"
4942 code.putln(
4943 "if (%s%s) {" % (
4944 sense,
4945 test_result))
4946 if uses_temp:
4947 code.funcstate.release_temp(test_result)
4948 self.operand1.generate_disposal_code(code)
4949 self.operand2.generate_evaluation_code(code)
4950 self.allocate_temp_result(code)
4951 self.operand2.make_owned_reference(code)
4952 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
4953 self.operand2.generate_post_assignment_code(code)
4954 self.operand2.free_temps(code)
4955 code.putln("} else {")
4956 self.operand1.make_owned_reference(code)
4957 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
4958 self.operand1.generate_post_assignment_code(code)
4959 self.operand1.free_temps(code)
4960 code.putln("}")
4962 def generate_operand1_test(self, code):
4963 # Generate code to test the truth of the first operand.
4964 if self.type.is_pyobject:
4965 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
4966 manage_ref=False)
4967 code.putln(
4968 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4969 test_result,
4970 self.operand1.py_result(),
4971 code.error_goto_if_neg(test_result, self.pos)))
4972 else:
4973 test_result = self.operand1.result()
4974 return (test_result, self.type.is_pyobject)
4977 class CondExprNode(ExprNode):
4978 # Short-circuiting conditional expression.
4979 #
4980 # test ExprNode
4981 # true_val ExprNode
4982 # false_val ExprNode
4984 true_val = None
4985 false_val = None
4987 subexprs = ['test', 'true_val', 'false_val']
4989 def type_dependencies(self, env):
4990 return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
4992 def infer_type(self, env):
4993 return self.compute_result_type(self.true_val.infer_type(env),
4994 self.false_val.infer_type(env))
4996 def calculate_constant_result(self):
4997 if self.test.constant_result:
4998 self.constant_result = self.true_val.constant_result
4999 else:
5000 self.constant_result = self.false_val.constant_result
5002 def analyse_types(self, env):
5003 self.test.analyse_types(env)
5004 self.test = self.test.coerce_to_boolean(env)
5005 self.true_val.analyse_types(env)
5006 self.false_val.analyse_types(env)
5007 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
5008 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
5009 self.true_val = self.true_val.coerce_to(self.type, env)
5010 self.false_val = self.false_val.coerce_to(self.type, env)
5011 self.is_temp = 1
5012 if self.type == PyrexTypes.error_type:
5013 self.type_error()
5015 def compute_result_type(self, type1, type2):
5016 if type1 == type2:
5017 return type1
5018 elif type1.is_numeric and type2.is_numeric:
5019 return PyrexTypes.widest_numeric_type(type1, type2)
5020 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
5021 return type2
5022 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
5023 return type1
5024 elif type1.is_pyobject or type2.is_pyobject:
5025 return py_object_type
5026 elif type1.assignable_from(type2):
5027 return type1
5028 elif type2.assignable_from(type1):
5029 return type2
5030 else:
5031 return PyrexTypes.error_type
5033 def type_error(self):
5034 if not (self.true_val.type.is_error or self.false_val.type.is_error):
5035 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
5036 (self.true_val.type, self.false_val.type))
5037 self.type = PyrexTypes.error_type
5039 def check_const(self):
5040 return (self.test.check_const()
5041 and self.true_val.check_const()
5042 and self.false_val.check_const())
5044 def generate_evaluation_code(self, code):
5045 # Because subexprs may not be evaluated we can use a more optimal
5046 # subexpr allocation strategy than the default, so override evaluation_code.
5048 code.mark_pos(self.pos)
5049 self.allocate_temp_result(code)
5050 self.test.generate_evaluation_code(code)
5051 code.putln("if (%s) {" % self.test.result() )
5052 self.eval_and_get(code, self.true_val)
5053 code.putln("} else {")
5054 self.eval_and_get(code, self.false_val)
5055 code.putln("}")
5056 self.test.generate_disposal_code(code)
5057 self.test.free_temps(code)
5059 def eval_and_get(self, code, expr):
5060 expr.generate_evaluation_code(code)
5061 expr.make_owned_reference(code)
5062 code.putln("%s = %s;" % (self.result(), expr.result()))
5063 expr.generate_post_assignment_code(code)
5064 expr.free_temps(code)
5066 richcmp_constants = {
5067 "<" : "Py_LT",
5068 "<=": "Py_LE",
5069 "==": "Py_EQ",
5070 "!=": "Py_NE",
5071 "<>": "Py_NE",
5072 ">" : "Py_GT",
5073 ">=": "Py_GE",
5074 }
5076 class CmpNode(object):
5077 # Mixin class containing code common to PrimaryCmpNodes
5078 # and CascadedCmpNodes.
5080 def infer_types(self, env):
5081 # TODO: Actually implement this (after merging with -unstable).
5082 return py_object_type
5084 def calculate_cascaded_constant_result(self, operand1_result):
5085 func = compile_time_binary_operators[self.operator]
5086 operand2_result = self.operand2.constant_result
5087 result = func(operand1_result, operand2_result)
5088 if result and self.cascade:
5089 result = result and \
5090 self.cascade.cascaded_compile_time_value(operand2_result)
5091 self.constant_result = result
5093 def cascaded_compile_time_value(self, operand1, denv):
5094 func = get_compile_time_binop(self)
5095 operand2 = self.operand2.compile_time_value(denv)
5096 try:
5097 result = func(operand1, operand2)
5098 except Exception, e:
5099 self.compile_time_value_error(e)
5100 result = None
5101 if result:
5102 cascade = self.cascade
5103 if cascade:
5104 # FIXME: I bet this must call cascaded_compile_time_value()
5105 result = result and cascade.compile_time_value(operand2, denv)
5106 return result
5108 def find_common_int_type(self, env, op, operand1, operand2):
5109 # type1 != type2 and at least one of the types is not a C int
5110 type1 = operand1.type
5111 type2 = operand2.type
5112 type1_can_be_int = False
5113 type2_can_be_int = False
5115 if isinstance(operand1, (StringNode, BytesNode)) \
5116 and operand1.can_coerce_to_char_literal():
5117 type1_can_be_int = True
5118 if isinstance(operand2, (StringNode, BytesNode)) \
5119 and operand2.can_coerce_to_char_literal():
5120 type2_can_be_int = True
5122 if type1.is_int:
5123 if type2_can_be_int:
5124 return type1
5125 elif type2.is_int:
5126 if type1_can_be_int:
5127 return type2
5128 elif type1_can_be_int:
5129 if type2_can_be_int:
5130 return PyrexTypes.c_uchar_type
5132 return None
5134 def find_common_type(self, env, op, operand1, common_type=None):
5135 operand2 = self.operand2
5136 type1 = operand1.type
5137 type2 = operand2.type
5139 new_common_type = None
5141 # catch general errors
5142 if type1 == str_type and (type2.is_string or type2 in (bytes_type, unicode_type)) or \
5143 type2 == str_type and (type1.is_string or type1 in (bytes_type, unicode_type)):
5144 error(self.pos, "Comparisons between bytes/unicode and str are not portable to Python 3")
5145 new_common_type = error_type
5147 # try to use numeric comparisons where possible
5148 elif type1.is_complex or type2.is_complex:
5149 if op not in ('==', '!='):
5150 error(self.pos, "complex types are unordered")
5151 new_common_type = error_type
5152 if type1.is_pyobject:
5153 new_common_type = type1
5154 elif type2.is_pyobject:
5155 new_common_type = type2
5156 else:
5157 new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
5158 elif type1.is_numeric and type2.is_numeric:
5159 new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
5160 elif common_type is None or not common_type.is_pyobject:
5161 new_common_type = self.find_common_int_type(env, op, operand1, operand2)
5163 if new_common_type is None:
5164 # fall back to generic type compatibility tests
5165 if type1 == type2:
5166 new_common_type = type1
5167 elif type1.is_pyobject or type2.is_pyobject:
5168 if type2.is_numeric or type2.is_string:
5169 if operand2.check_for_coercion_error(type1):
5170 new_common_type = error_type
5171 else:
5172 new_common_type = py_object_type
5173 elif type1.is_numeric or type1.is_string:
5174 if operand1.check_for_coercion_error(type2):
5175 new_common_type = error_type
5176 else:
5177 new_common_type = py_object_type
5178 elif py_object_type.assignable_from(type1) and py_object_type.assignable_from(type2):
5179 new_common_type = py_object_type
5180 else:
5181 # one Python type and one non-Python type, not assignable
5182 self.invalid_types_error(operand1, op, operand2)
5183 new_common_type = error_type
5184 elif type1.assignable_from(type2):
5185 new_common_type = type1
5186 elif type2.assignable_from(type1):
5187 new_common_type = type2
5188 else:
5189 # C types that we couldn't handle up to here are an error
5190 self.invalid_types_error(operand1, op, operand2)
5191 new_common_type = error_type
5193 # recursively merge types
5194 if common_type is None or new_common_type.is_error:
5195 common_type = new_common_type
5196 else:
5197 # we could do a lot better by splitting the comparison
5198 # into a non-Python part and a Python part, but this is
5199 # safer for now
5200 common_type = PyrexTypes.spanning_type(common_type, new_common_type)
5202 if self.cascade:
5203 common_type = self.cascade.find_common_type(env, self.operator, operand2, common_type)
5205 return common_type
5207 def invalid_types_error(self, operand1, op, operand2):
5208 error(self.pos, "Invalid types for '%s' (%s, %s)" %
5209 (op, operand1.type, operand2.type))
5211 def is_python_comparison(self):
5212 return (self.has_python_operands()
5213 or (self.cascade and self.cascade.is_python_comparison())
5214 or self.operator in ('in', 'not_in'))
5216 def coerce_operands_to(self, dst_type, env):
5217 operand2 = self.operand2
5218 if operand2.type != dst_type:
5219 self.operand2 = operand2.coerce_to(dst_type, env)
5220 if self.cascade:
5221 self.cascade.coerce_operands_to(dst_type, env)
5223 def is_python_result(self):
5224 return ((self.has_python_operands() and
5225 self.operator not in ('is', 'is_not', 'in', 'not_in'))
5226 or (self.cascade and self.cascade.is_python_result()))
5228 def generate_operation_code(self, code, result_code,
5229 operand1, op , operand2):
5230 if self.type is PyrexTypes.py_object_type:
5231 coerce_result = "__Pyx_PyBool_FromLong"
5232 else:
5233 coerce_result = ""
5234 if 'not' in op:
5235 negation = "!"
5236 else:
5237 negation = ""
5238 if op == 'in' or op == 'not_in':
5239 code.globalstate.use_utility_code(contians_utility_code)
5240 if self.type is PyrexTypes.py_object_type:
5241 coerce_result = "__Pyx_PyBoolOrNull_FromLong"
5242 if op == 'not_in':
5243 negation = "__Pyx_NegateNonNeg"
5244 if operand2.type is dict_type:
5245 code.globalstate.use_utility_code(
5246 raise_none_iter_error_utility_code)
5247 code.putln("if (unlikely(%s == Py_None)) {" % operand2.py_result())
5248 code.putln("__Pyx_RaiseNoneNotIterableError(); %s" %
5249 code.error_goto(self.pos))
5250 code.putln("} else {")
5251 method = "PyDict_Contains"
5252 else:
5253 method = "PySequence_Contains"
5254 if self.type is PyrexTypes.py_object_type:
5255 error_clause = code.error_goto_if_null
5256 got_ref = "__Pyx_XGOTREF(%s); " % result_code
5257 else:
5258 error_clause = code.error_goto_if_neg
5259 got_ref = ""
5260 code.putln(
5261 "%s = %s(%s(%s(%s, %s))); %s%s" % (
5262 result_code,
5263 coerce_result,
5264 negation,
5265 method,
5266 operand2.py_result(),
5267 operand1.py_result(),
5268 got_ref,
5269 error_clause(result_code, self.pos)))
5270 if operand2.type is dict_type:
5271 code.putln("}")
5273 elif (operand1.type.is_pyobject
5274 and op not in ('is', 'is_not')):
5275 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
5276 result_code,
5277 operand1.py_result(),
5278 operand2.py_result(),
5279 richcmp_constants[op],
5280 code.error_goto_if_null(result_code, self.pos)))
5281 code.put_gotref(result_code)
5282 elif operand1.type.is_complex:
5283 if op == "!=":
5284 negation = "!"
5285 else:
5286 negation = ""
5287 code.putln("%s = %s(%s%s(%s, %s));" % (
5288 result_code,
5289 coerce_result,
5290 negation,
5291 operand1.type.unary_op('eq'),
5292 operand1.result(),
5293 operand2.result()))
5294 else:
5295 type1 = operand1.type
5296 type2 = operand2.type
5297 if (type1.is_extension_type or type2.is_extension_type) \
5298 and not type1.same_as(type2):
5299 common_type = py_object_type
5300 elif type1.is_numeric:
5301 common_type = PyrexTypes.widest_numeric_type(type1, type2)
5302 else:
5303 common_type = type1
5304 code1 = operand1.result_as(common_type)
5305 code2 = operand2.result_as(common_type)
5306 code.putln("%s = %s(%s %s %s);" % (
5307 result_code,
5308 coerce_result,
5309 code1,
5310 self.c_operator(op),
5311 code2))
5313 def c_operator(self, op):
5314 if op == 'is':
5315 return "=="
5316 elif op == 'is_not':
5317 return "!="
5318 else:
5319 return op
5321 contians_utility_code = UtilityCode(
5322 proto="""
5323 static INLINE long __Pyx_NegateNonNeg(long b) { return unlikely(b < 0) ? b : !b; }
5324 static INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
5325 return unlikely(b < 0) ? NULL : __Pyx_PyBool_FromLong(b);
5326 }
5327 """)
5330 class PrimaryCmpNode(ExprNode, CmpNode):
5331 # Non-cascaded comparison or first comparison of
5332 # a cascaded sequence.
5333 #
5334 # operator string
5335 # operand1 ExprNode
5336 # operand2 ExprNode
5337 # cascade CascadedCmpNode
5339 # We don't use the subexprs mechanism, because
5340 # things here are too complicated for it to handle.
5341 # Instead, we override all the framework methods
5342 # which use it.
5344 child_attrs = ['operand1', 'operand2', 'cascade']
5346 cascade = None
5348 def infer_type(self, env):
5349 # TODO: Actually implement this (after merging with -unstable).
5350 return py_object_type
5352 def type_dependencies(self, env):
5353 return ()
5355 def calculate_constant_result(self):
5356 self.constant_result = self.calculate_cascaded_constant_result(
5357 self.operand1.constant_result)
5359 def compile_time_value(self, denv):
5360 operand1 = self.operand1.compile_time_value(denv)
5361 return self.cascaded_compile_time_value(operand1, denv)
5363 def analyse_types(self, env):
5364 self.operand1.analyse_types(env)
5365 self.operand2.analyse_types(env)
5366 if self.cascade:
5367 self.cascade.analyse_types(env)
5369 if self.operator in ('in', 'not_in'):
5370 common_type = py_object_type
5371 self.is_pycmp = True
5372 else:
5373 common_type = self.find_common_type(env, self.operator, self.operand1)
5374 self.is_pycmp = common_type.is_pyobject
5376 if not common_type.is_error:
5377 if self.operand1.type != common_type:
5378 self.operand1 = self.operand1.coerce_to(common_type, env)
5379 self.coerce_operands_to(common_type, env)
5381 if self.cascade:
5382 self.operand2 = self.operand2.coerce_to_simple(env)
5383 self.cascade.coerce_cascaded_operands_to_temp(env)
5384 if self.is_python_result():
5385 self.type = PyrexTypes.py_object_type
5386 else:
5387 self.type = PyrexTypes.c_bint_type
5388 cdr = self.cascade
5389 while cdr:
5390 cdr.type = self.type
5391 cdr = cdr.cascade
5392 if self.is_pycmp or self.cascade:
5393 self.is_temp = 1
5395 def has_python_operands(self):
5396 return (self.operand1.type.is_pyobject
5397 or self.operand2.type.is_pyobject)
5399 def check_const(self):
5400 if self.cascade:
5401 self.not_const()
5402 return False
5403 else:
5404 return self.operand1.check_const() and self.operand2.check_const()
5406 def calculate_result_code(self):
5407 if self.operand1.type.is_complex:
5408 if self.operator == "!=":
5409 negation = "!"
5410 else:
5411 negation = ""
5412 return "(%s%s(%s, %s))" % (
5413 negation,
5414 self.operand1.type.binary_op('=='),
5415 self.operand1.result(),
5416 self.operand2.result())
5417 else:
5418 return "(%s %s %s)" % (
5419 self.operand1.result(),
5420 self.c_operator(self.operator),
5421 self.operand2.result())
5423 def generate_evaluation_code(self, code):
5424 self.operand1.generate_evaluation_code(code)
5425 self.operand2.generate_evaluation_code(code)
5426 if self.is_temp:
5427 self.allocate_temp_result(code)
5428 self.generate_operation_code(code, self.result(),
5429 self.operand1, self.operator, self.operand2)
5430 if self.cascade:
5431 self.cascade.generate_evaluation_code(code,
5432 self.result(), self.operand2)
5433 self.operand1.generate_disposal_code(code)
5434 self.operand1.free_temps(code)
5435 self.operand2.generate_disposal_code(code)
5436 self.operand2.free_temps(code)
5438 def generate_subexpr_disposal_code(self, code):
5439 # If this is called, it is a non-cascaded cmp,
5440 # so only need to dispose of the two main operands.
5441 self.operand1.generate_disposal_code(code)
5442 self.operand2.generate_disposal_code(code)
5444 def free_subexpr_temps(self, code):
5445 # If this is called, it is a non-cascaded cmp,
5446 # so only need to dispose of the two main operands.
5447 self.operand1.free_temps(code)
5448 self.operand2.free_temps(code)
5450 def annotate(self, code):
5451 self.operand1.annotate(code)
5452 self.operand2.annotate(code)
5453 if self.cascade:
5454 self.cascade.annotate(code)
5457 class CascadedCmpNode(Node, CmpNode):
5458 # A CascadedCmpNode is not a complete expression node. It
5459 # hangs off the side of another comparison node, shares
5460 # its left operand with that node, and shares its result
5461 # with the PrimaryCmpNode at the head of the chain.
5462 #
5463 # operator string
5464 # operand2 ExprNode
5465 # cascade CascadedCmpNode
5467 child_attrs = ['operand2', 'cascade']
5469 cascade = None
5470 constant_result = constant_value_not_set # FIXME: where to calculate this?
5472 def infer_type(self, env):
5473 # TODO: Actually implement this (after merging with -unstable).
5474 return py_object_type
5476 def type_dependencies(self, env):
5477 return ()
5479 def analyse_types(self, env):
5480 self.operand2.analyse_types(env)
5481 if self.cascade:
5482 self.cascade.analyse_types(env)
5484 def has_python_operands(self):
5485 return self.operand2.type.is_pyobject
5487 def coerce_operands_to_pyobjects(self, env):
5488 self.operand2 = self.operand2.coerce_to_pyobject(env)
5489 if self.cascade:
5490 self.cascade.coerce_operands_to_pyobjects(env)
5492 def coerce_cascaded_operands_to_temp(self, env):
5493 if self.cascade:
5494 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
5495 self.operand2 = self.operand2.coerce_to_simple(env)
5496 self.cascade.coerce_cascaded_operands_to_temp(env)
5498 def generate_evaluation_code(self, code, result, operand1):
5499 if self.type.is_pyobject:
5500 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
5501 code.put_decref(result, self.type)
5502 else:
5503 code.putln("if (%s) {" % result)
5504 self.operand2.generate_evaluation_code(code)
5505 self.generate_operation_code(code, result,
5506 operand1, self.operator, self.operand2)
5507 if self.cascade:
5508 self.cascade.generate_evaluation_code(
5509 code, result, self.operand2)
5510 # Cascaded cmp result is always temp
5511 self.operand2.generate_disposal_code(code)
5512 self.operand2.free_temps(code)
5513 code.putln("}")
5515 def annotate(self, code):
5516 self.operand2.annotate(code)
5517 if self.cascade:
5518 self.cascade.annotate(code)
5521 binop_node_classes = {
5522 "or": BoolBinopNode,
5523 "and": BoolBinopNode,
5524 "|": IntBinopNode,
5525 "^": IntBinopNode,
5526 "&": IntBinopNode,
5527 "<<": IntBinopNode,
5528 ">>": IntBinopNode,
5529 "+": AddNode,
5530 "-": SubNode,
5531 "*": MulNode,
5532 "/": DivNode,
5533 "//": DivNode,
5534 "%": ModNode,
5535 "**": PowNode
5536 }
5538 def binop_node(pos, operator, operand1, operand2):
5539 # Construct binop node of appropriate class for
5540 # given operator.
5541 return binop_node_classes[operator](pos,
5542 operator = operator,
5543 operand1 = operand1,
5544 operand2 = operand2)
5546 #-------------------------------------------------------------------
5547 #
5548 # Coercion nodes
5549 #
5550 # Coercion nodes are special in that they are created during
5551 # the analyse_types phase of parse tree processing.
5552 # Their __init__ methods consequently incorporate some aspects
5553 # of that phase.
5554 #
5555 #-------------------------------------------------------------------
5557 class CoercionNode(ExprNode):
5558 # Abstract base class for coercion nodes.
5559 #
5560 # arg ExprNode node being coerced
5562 subexprs = ['arg']
5563 constant_result = not_a_constant
5565 def __init__(self, arg):
5566 self.pos = arg.pos
5567 self.arg = arg
5568 if debug_coercion:
5569 print("%s Coercing %s" % (self, self.arg))
5571 def calculate_constant_result(self):
5572 # constant folding can break type coercion, so this is disabled
5573 pass
5575 def annotate(self, code):
5576 self.arg.annotate(code)
5577 if self.arg.type != self.type:
5578 file, line, col = self.pos
5579 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
5582 class CastNode(CoercionNode):
5583 # Wrap a node in a C type cast.
5585 def __init__(self, arg, new_type):
5586 CoercionNode.__init__(self, arg)
5587 self.type = new_type
5589 def calculate_result_code(self):
5590 return self.arg.result_as(self.type)
5592 def generate_result_code(self, code):
5593 self.arg.generate_result_code(code)
5596 class PyTypeTestNode(CoercionNode):
5597 # This node is used to check that a generic Python
5598 # object is an instance of a particular extension type.
5599 # This node borrows the result of its argument node.
5601 def __init__(self, arg, dst_type, env, notnone=False):
5602 # The arg is know to be a Python object, and
5603 # the dst_type is known to be an extension type.
5604 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
5605 CoercionNode.__init__(self, arg)
5606 self.type = dst_type
5607 self.result_ctype = arg.ctype()
5608 self.notnone = notnone
5610 nogil_check = Node.gil_error
5611 gil_message = "Python type test"
5613 def analyse_types(self, env):
5614 pass
5616 def result_in_temp(self):
5617 return self.arg.result_in_temp()
5619 def is_ephemeral(self):
5620 return self.arg.is_ephemeral()
5622 def calculate_constant_result(self):
5623 # FIXME
5624 pass
5626 def calculate_result_code(self):
5627 return self.arg.result()
5629 def generate_result_code(self, code):
5630 if self.type.typeobj_is_available():
5631 if not self.type.is_builtin_type:
5632 code.globalstate.use_utility_code(type_test_utility_code)
5633 code.putln(
5634 "if (!(%s)) %s" % (
5635 self.type.type_test_code(self.arg.py_result(), self.notnone),
5636 code.error_goto(self.pos)))
5637 else:
5638 error(self.pos, "Cannot test type of extern C class "
5639 "without type object name specification")
5641 def generate_post_assignment_code(self, code):
5642 self.arg.generate_post_assignment_code(code)
5644 def free_temps(self, code):
5645 self.arg.free_temps(code)
5648 class NoneCheckNode(CoercionNode):
5649 # This node is used to check that a Python object is not None and
5650 # raises an appropriate exception (as specified by the creating
5651 # transform).
5653 def __init__(self, arg, exception_type_cname, exception_message):
5654 CoercionNode.__init__(self, arg)
5655 self.type = arg.type
5656 self.result_ctype = arg.ctype()
5657 self.exception_type_cname = exception_type_cname
5658 self.exception_message = exception_message
5660 def analyse_types(self, env):
5661 pass
5663 def result_in_temp(self):
5664 return self.arg.result_in_temp()
5666 def calculate_result_code(self):
5667 return self.arg.result()
5669 def generate_result_code(self, code):
5670 code.putln(
5671 "if (unlikely(%s == Py_None)) {" % self.arg.result())
5672 code.putln('PyErr_SetString(%s, "%s"); %s ' % (
5673 self.exception_type_cname,
5674 StringEncoding.escape_byte_string(
5675 self.exception_message.encode('UTF-8')),
5676 code.error_goto(self.pos)))
5677 code.putln("}")
5679 def generate_post_assignment_code(self, code):
5680 self.arg.generate_post_assignment_code(code)
5682 def free_temps(self, code):
5683 self.arg.free_temps(code)
5686 class CoerceToPyTypeNode(CoercionNode):
5687 # This node is used to convert a C data type
5688 # to a Python object.
5690 type = py_object_type
5691 is_temp = 1
5693 def __init__(self, arg, env, type=py_object_type):
5694 CoercionNode.__init__(self, arg)
5695 if not arg.type.create_to_py_utility_code(env):
5696 error(arg.pos,
5697 "Cannot convert '%s' to Python object" % arg.type)
5698 if type is not py_object_type:
5699 self.type = py_object_type
5700 elif arg.type.is_string:
5701 self.type = Builtin.bytes_type
5703 gil_message = "Converting to Python object"
5705 def coerce_to_boolean(self, env):
5706 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
5708 def coerce_to_integer(self, env):
5709 # If not already some C integer type, coerce to longint.
5710 if self.arg.type.is_int:
5711 return self.arg
5712 else:
5713 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
5715 def analyse_types(self, env):
5716 # The arg is always already analysed
5717 pass
5719 def generate_result_code(self, code):
5720 function = self.arg.type.to_py_function
5721 code.putln('%s = %s(%s); %s' % (
5722 self.result(),
5723 function,
5724 self.arg.result(),
5725 code.error_goto_if_null(self.result(), self.pos)))
5726 code.put_gotref(self.py_result())
5729 class CoerceFromPyTypeNode(CoercionNode):
5730 # This node is used to convert a Python object
5731 # to a C data type.
5733 def __init__(self, result_type, arg, env):
5734 CoercionNode.__init__(self, arg)
5735 self.type = result_type
5736 self.is_temp = 1
5737 if not result_type.create_from_py_utility_code(env):
5738 error(arg.pos,
5739 "Cannot convert Python object to '%s'" % result_type)
5740 if self.type.is_string and self.arg.is_ephemeral():
5741 error(arg.pos,
5742 "Obtaining char * from temporary Python value")
5744 def analyse_types(self, env):
5745 # The arg is always already analysed
5746 pass
5748 def generate_result_code(self, code):
5749 function = self.type.from_py_function
5750 operand = self.arg.py_result()
5751 rhs = "%s(%s)" % (function, operand)
5752 if self.type.is_enum:
5753 rhs = typecast(self.type, c_long_type, rhs)
5754 code.putln('%s = %s; %s' % (
5755 self.result(),
5756 rhs,
5757 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
5758 if self.type.is_pyobject:
5759 code.put_gotref(self.py_result())
5762 class CoerceToBooleanNode(CoercionNode):
5763 # This node is used when a result needs to be used
5764 # in a boolean context.
5766 type = PyrexTypes.c_bint_type
5768 def __init__(self, arg, env):
5769 CoercionNode.__init__(self, arg)
5770 if arg.type.is_pyobject:
5771 self.is_temp = 1
5773 def nogil_check(self, env):
5774 if self.arg.type.is_pyobject:
5775 self.gil_error()
5777 gil_message = "Truth-testing Python object"
5779 def check_const(self):
5780 if self.is_temp:
5781 self.not_const()
5782 return False
5783 return self.arg.check_const()
5785 def calculate_result_code(self):
5786 return "(%s != 0)" % self.arg.result()
5788 def generate_result_code(self, code):
5789 if self.arg.type.is_pyobject:
5790 code.putln(
5791 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5792 self.result(),
5793 self.arg.py_result(),
5794 code.error_goto_if_neg(self.result(), self.pos)))
5796 class CoerceToComplexNode(CoercionNode):
5798 def __init__(self, arg, dst_type, env):
5799 if arg.type.is_complex:
5800 arg = arg.coerce_to_simple(env)
5801 self.type = dst_type
5802 CoercionNode.__init__(self, arg)
5803 dst_type.create_declaration_utility_code(env)
5805 def calculate_result_code(self):
5806 if self.arg.type.is_complex:
5807 real_part = "__Pyx_CREAL(%s)" % self.arg.result()
5808 imag_part = "__Pyx_CIMAG(%s)" % self.arg.result()
5809 else:
5810 real_part = self.arg.result()
5811 imag_part = "0"
5812 return "%s(%s, %s)" % (
5813 self.type.from_parts,
5814 real_part,
5815 imag_part)
5817 def generate_result_code(self, code):
5818 pass
5820 class CoerceToTempNode(CoercionNode):
5821 # This node is used to force the result of another node
5822 # to be stored in a temporary. It is only used if the
5823 # argument node's result is not already in a temporary.
5825 def __init__(self, arg, env):
5826 CoercionNode.__init__(self, arg)
5827 self.type = self.arg.type
5828 self.is_temp = 1
5829 if self.type.is_pyobject:
5830 self.result_ctype = py_object_type
5832 gil_message = "Creating temporary Python reference"
5834 def analyse_types(self, env):
5835 # The arg is always already analysed
5836 pass
5838 def coerce_to_boolean(self, env):
5839 self.arg = self.arg.coerce_to_boolean(env)
5840 self.type = self.arg.type
5841 self.result_ctype = self.type
5842 return self
5844 def generate_result_code(self, code):
5845 #self.arg.generate_evaluation_code(code) # Already done
5846 # by generic generate_subexpr_evaluation_code!
5847 code.putln("%s = %s;" % (
5848 self.result(), self.arg.result_as(self.ctype())))
5849 if self.type.is_pyobject and self.use_managed_ref:
5850 code.put_incref(self.result(), self.ctype())
5853 class CloneNode(CoercionNode):
5854 # This node is employed when the result of another node needs
5855 # to be used multiple times. The argument node's result must
5856 # be in a temporary. This node "borrows" the result from the
5857 # argument node, and does not generate any evaluation or
5858 # disposal code for it. The original owner of the argument
5859 # node is responsible for doing those things.
5861 subexprs = [] # Arg is not considered a subexpr
5862 nogil_check = None
5864 def __init__(self, arg):
5865 CoercionNode.__init__(self, arg)
5866 if hasattr(arg, 'type'):
5867 self.type = arg.type
5868 self.result_ctype = arg.result_ctype
5869 if hasattr(arg, 'entry'):
5870 self.entry = arg.entry
5872 def result(self):
5873 return self.arg.result()
5875 def type_dependencies(self, env):
5876 return self.arg.type_dependencies(env)
5878 def infer_type(self, env):
5879 return self.arg.infer_type(env)
5881 def analyse_types(self, env):
5882 self.type = self.arg.type
5883 self.result_ctype = self.arg.result_ctype
5884 self.is_temp = 1
5885 if hasattr(self.arg, 'entry'):
5886 self.entry = self.arg.entry
5888 def generate_evaluation_code(self, code):
5889 pass
5891 def generate_result_code(self, code):
5892 pass
5894 def generate_disposal_code(self, code):
5895 pass
5897 def free_temps(self, code):
5898 pass
5901 class ModuleRefNode(ExprNode):
5902 # Simple returns the module object
5904 type = py_object_type
5905 is_temp = False
5906 subexprs = []
5908 def analyse_types(self, env):
5909 pass
5911 def calculate_result_code(self):
5912 return Naming.module_cname
5914 def generate_result_code(self, code):
5915 pass
5917 class DocstringRefNode(ExprNode):
5918 # Extracts the docstring of the body element
5920 subexprs = ['body']
5921 type = py_object_type
5922 is_temp = True
5924 def __init__(self, pos, body):
5925 ExprNode.__init__(self, pos)
5926 assert body.type.is_pyobject
5927 self.body = body
5929 def analyse_types(self, env):
5930 pass
5932 def generate_result_code(self, code):
5933 code.putln('%s = __Pyx_GetAttrString(%s, "__doc__");' %
5934 (self.result(), self.body.result()))
5935 code.put_gotref(self.result())
5939 #------------------------------------------------------------------------------------
5940 #
5941 # Runtime support code
5942 #
5943 #------------------------------------------------------------------------------------
5945 get_name_interned_utility_code = UtilityCode(
5946 proto = """
5947 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
5948 """,
5949 impl = """
5950 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
5951 PyObject *result;
5952 result = PyObject_GetAttr(dict, name);
5953 if (!result)
5954 PyErr_SetObject(PyExc_NameError, name);
5955 return result;
5956 }
5957 """)
5959 #------------------------------------------------------------------------------------
5961 import_utility_code = UtilityCode(
5962 proto = """
5963 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
5964 """,
5965 impl = """
5966 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
5967 PyObject *__import__ = 0;
5968 PyObject *empty_list = 0;
5969 PyObject *module = 0;
5970 PyObject *global_dict = 0;
5971 PyObject *empty_dict = 0;
5972 PyObject *list;
5973 __import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
5974 if (!__import__)
5975 goto bad;
5976 if (from_list)
5977 list = from_list;
5978 else {
5979 empty_list = PyList_New(0);
5980 if (!empty_list)
5981 goto bad;
5982 list = empty_list;
5983 }
5984 global_dict = PyModule_GetDict(%(GLOBALS)s);
5985 if (!global_dict)
5986 goto bad;
5987 empty_dict = PyDict_New();
5988 if (!empty_dict)
5989 goto bad;
5990 module = PyObject_CallFunctionObjArgs(__import__,
5991 name, global_dict, empty_dict, list, NULL);
5992 bad:
5993 Py_XDECREF(empty_list);
5994 Py_XDECREF(__import__);
5995 Py_XDECREF(empty_dict);
5996 return module;
5997 }
5998 """ % {
5999 "BUILTINS": Naming.builtins_cname,
6000 "GLOBALS": Naming.module_cname,
6001 })
6003 #------------------------------------------------------------------------------------
6005 get_exception_utility_code = UtilityCode(
6006 proto = """
6007 static PyObject *__Pyx_GetExcValue(void); /*proto*/
6008 """,
6009 impl = """
6010 static PyObject *__Pyx_GetExcValue(void) {
6011 PyObject *type = 0, *value = 0, *tb = 0;
6012 PyObject *tmp_type, *tmp_value, *tmp_tb;
6013 PyObject *result = 0;
6014 PyThreadState *tstate = PyThreadState_Get();
6015 PyErr_Fetch(&type, &value, &tb);
6016 PyErr_NormalizeException(&type, &value, &tb);
6017 if (PyErr_Occurred())
6018 goto bad;
6019 if (!value) {
6020 value = Py_None;
6021 Py_INCREF(value);
6022 }
6023 tmp_type = tstate->exc_type;
6024 tmp_value = tstate->exc_value;
6025 tmp_tb = tstate->exc_traceback;
6026 tstate->exc_type = type;
6027 tstate->exc_value = value;
6028 tstate->exc_traceback = tb;
6029 /* Make sure tstate is in a consistent state when we XDECREF
6030 these objects (XDECREF may run arbitrary code). */
6031 Py_XDECREF(tmp_type);
6032 Py_XDECREF(tmp_value);
6033 Py_XDECREF(tmp_tb);
6034 result = value;
6035 Py_XINCREF(result);
6036 type = 0;
6037 value = 0;
6038 tb = 0;
6039 bad:
6040 Py_XDECREF(type);
6041 Py_XDECREF(value);
6042 Py_XDECREF(tb);
6043 return result;
6044 }
6045 """)
6047 #------------------------------------------------------------------------------------
6049 type_test_utility_code = UtilityCode(
6050 proto = """
6051 static INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
6052 """,
6053 impl = """
6054 static INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
6055 if (unlikely(!type)) {
6056 PyErr_Format(PyExc_SystemError, "Missing type object");
6057 return 0;
6058 }
6059 if (likely(PyObject_TypeCheck(obj, type)))
6060 return 1;
6061 PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s",
6062 Py_TYPE(obj)->tp_name, type->tp_name);
6063 return 0;
6064 }
6065 """)
6067 #------------------------------------------------------------------------------------
6069 create_class_utility_code = UtilityCode(
6070 proto = """
6071 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
6072 """,
6073 impl = """
6074 static PyObject *__Pyx_CreateClass(
6075 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
6076 {
6077 PyObject *py_modname;
6078 PyObject *result = 0;
6080 #if PY_MAJOR_VERSION < 3
6081 py_modname = PyString_FromString(modname);
6082 #else
6083 py_modname = PyUnicode_FromString(modname);
6084 #endif
6085 if (!py_modname)
6086 goto bad;
6087 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
6088 goto bad;
6089 #if PY_MAJOR_VERSION < 3
6090 result = PyClass_New(bases, dict, name);
6091 #else
6092 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
6093 #endif
6094 bad:
6095 Py_XDECREF(py_modname);
6096 return result;
6097 }
6098 """)
6100 #------------------------------------------------------------------------------------
6102 cpp_exception_utility_code = UtilityCode(
6103 proto = """
6104 #ifndef __Pyx_CppExn2PyErr
6105 static void __Pyx_CppExn2PyErr() {
6106 try {
6107 if (PyErr_Occurred())
6108 ; // let the latest Python exn pass through and ignore the current one
6109 else
6110 throw;
6111 } catch (const std::out_of_range& exn) {
6112 // catch out_of_range explicitly so the proper Python exn may be raised
6113 PyErr_SetString(PyExc_IndexError, exn.what());
6114 } catch (const std::exception& exn) {
6115 PyErr_SetString(PyExc_RuntimeError, exn.what());
6116 }
6117 catch (...)
6118 {
6119 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
6120 }
6121 }
6122 #endif
6123 """,
6124 impl = ""
6125 )
6127 #------------------------------------------------------------------------------------
6129 # If the is_unsigned flag is set, we need to do some extra work to make
6130 # sure the index doesn't become negative.
6132 getitem_int_utility_code = UtilityCode(
6133 proto = """
6135 static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
6136 PyObject *r;
6137 if (!j) return NULL;
6138 r = PyObject_GetItem(o, j);
6139 Py_DECREF(j);
6140 return r;
6141 }
6143 """ + ''.join([
6144 """
6145 #define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6146 __Pyx_GetItemInt_%(type)s_Fast(o, i, size <= sizeof(long)) : \\
6147 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
6149 static INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6150 if (likely(o != Py_None)) {
6151 if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
6152 PyObject *r = Py%(type)s_GET_ITEM(o, i);
6153 Py_INCREF(r);
6154 return r;
6155 }
6156 else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
6157 PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
6158 Py_INCREF(r);
6159 return r;
6160 }
6161 }
6162 return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
6163 }
6164 """ % {'type' : type_name} for type_name in ('List', 'Tuple')
6165 ]) + """
6167 #define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6168 __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \\
6169 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
6171 static INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6172 PyObject *r;
6173 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
6174 r = PyList_GET_ITEM(o, i);
6175 Py_INCREF(r);
6176 }
6177 else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
6178 r = PyTuple_GET_ITEM(o, i);
6179 Py_INCREF(r);
6180 }
6181 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
6182 r = PySequence_GetItem(o, i);
6183 }
6184 else {
6185 r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
6186 }
6187 return r;
6188 }
6189 """,
6190 impl = """
6191 """)
6195 #------------------------------------------------------------------------------------
6197 setitem_int_utility_code = UtilityCode(
6198 proto = """
6199 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6200 __Pyx_SetItemInt_Fast(o, i, v, size <= sizeof(long)) : \\
6201 __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
6203 static INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
6204 int r;
6205 if (!j) return -1;
6206 r = PyObject_SetItem(o, j, v);
6207 Py_DECREF(j);
6208 return r;
6209 }
6211 static INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int fits_long) {
6212 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
6213 Py_INCREF(v);
6214 Py_DECREF(PyList_GET_ITEM(o, i));
6215 PyList_SET_ITEM(o, i, v);
6216 return 1;
6217 }
6218 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
6219 return PySequence_SetItem(o, i, v);
6220 else {
6221 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
6222 return __Pyx_SetItemInt_Generic(o, j, v);
6223 }
6224 }
6225 """,
6226 impl = """
6227 """)
6229 #------------------------------------------------------------------------------------
6231 delitem_int_utility_code = UtilityCode(
6232 proto = """
6233 #define __Pyx_DelItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6234 __Pyx_DelItemInt_Fast(o, i, size <= sizeof(long)) : \\
6235 __Pyx_DelItem_Generic(o, to_py_func(i)))
6237 static INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
6238 int r;
6239 if (!j) return -1;
6240 r = PyObject_DelItem(o, j);
6241 Py_DECREF(j);
6242 return r;
6243 }
6245 static INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6246 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
6247 return PySequence_DelItem(o, i);
6248 else {
6249 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
6250 return __Pyx_DelItem_Generic(o, j);
6251 }
6252 }
6253 """,
6254 impl = """
6255 """)
6257 #------------------------------------------------------------------------------------
6259 raise_noneattr_error_utility_code = UtilityCode(
6260 proto = """
6261 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
6262 """,
6263 impl = '''
6264 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
6265 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
6266 }
6267 ''')
6269 raise_noneindex_error_utility_code = UtilityCode(
6270 proto = """
6271 static INLINE void __Pyx_RaiseNoneIndexingError(void);
6272 """,
6273 impl = '''
6274 static INLINE void __Pyx_RaiseNoneIndexingError(void) {
6275 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
6276 }
6277 ''')
6279 raise_none_iter_error_utility_code = UtilityCode(
6280 proto = """
6281 static INLINE void __Pyx_RaiseNoneNotIterableError(void);
6282 """,
6283 impl = '''
6284 static INLINE void __Pyx_RaiseNoneNotIterableError(void) {
6285 PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
6286 }
6287 ''')
6289 raise_too_many_values_to_unpack = UtilityCode(
6290 proto = """
6291 static INLINE void __Pyx_RaiseTooManyValuesError(void);
6292 """,
6293 impl = '''
6294 static INLINE void __Pyx_RaiseTooManyValuesError(void) {
6295 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
6296 }
6297 ''')
6299 raise_need_more_values_to_unpack = UtilityCode(
6300 proto = """
6301 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
6302 """,
6303 impl = '''
6304 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
6305 PyErr_Format(PyExc_ValueError,
6306 #if PY_VERSION_HEX < 0x02050000
6307 "need more than %d value%s to unpack", (int)index,
6308 #else
6309 "need more than %zd value%s to unpack", index,
6310 #endif
6311 (index == 1) ? "" : "s");
6312 }
6313 ''')
6315 #------------------------------------------------------------------------------------
6317 tuple_unpacking_error_code = UtilityCode(
6318 proto = """
6319 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
6320 """,
6321 impl = """
6322 static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
6323 if (t == Py_None) {
6324 __Pyx_RaiseNoneNotIterableError();
6325 } else if (PyTuple_GET_SIZE(t) < index) {
6326 __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
6327 } else {
6328 __Pyx_RaiseTooManyValuesError();
6329 }
6330 }
6331 """,
6332 requires = [raise_none_iter_error_utility_code,
6333 raise_need_more_values_to_unpack,
6334 raise_too_many_values_to_unpack]
6335 )
6337 unpacking_utility_code = UtilityCode(
6338 proto = """
6339 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
6340 static int __Pyx_EndUnpack(PyObject *); /*proto*/
6341 """,
6342 impl = """
6343 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
6344 PyObject *item;
6345 if (!(item = PyIter_Next(iter))) {
6346 if (!PyErr_Occurred()) {
6347 __Pyx_RaiseNeedMoreValuesError(index);
6348 }
6349 }
6350 return item;
6351 }
6353 static int __Pyx_EndUnpack(PyObject *iter) {
6354 PyObject *item;
6355 if ((item = PyIter_Next(iter))) {
6356 Py_DECREF(item);
6357 __Pyx_RaiseTooManyValuesError();
6358 return -1;
6359 }
6360 else if (!PyErr_Occurred())
6361 return 0;
6362 else
6363 return -1;
6364 }
6365 """,
6366 requires = [raise_need_more_values_to_unpack,
6367 raise_too_many_values_to_unpack]
6368 )
6371 #------------------------------------------------------------------------------------
6373 int_pow_utility_code = UtilityCode(
6374 proto="""
6375 static INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
6376 """,
6377 impl="""
6378 static INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
6379 %(type)s t = b;
6380 switch (e) {
6381 case 3:
6382 t *= b;
6383 case 2:
6384 t *= b;
6385 case 1:
6386 return t;
6387 case 0:
6388 return 1;
6389 }
6390 if (unlikely(e<0)) return 0;
6391 t = 1;
6392 while (likely(e)) {
6393 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
6394 b *= b;
6395 e >>= 1;
6396 }
6397 return t;
6398 }
6399 """)
6401 # ------------------------------ Division ------------------------------------
6403 div_int_utility_code = UtilityCode(
6404 proto="""
6405 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
6406 """,
6407 impl="""
6408 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
6409 %(type)s q = a / b;
6410 %(type)s r = a - q*b;
6411 q -= ((r != 0) & ((r ^ b) < 0));
6412 return q;
6413 }
6414 """)
6416 mod_int_utility_code = UtilityCode(
6417 proto="""
6418 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6419 """,
6420 impl="""
6421 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6422 %(type)s r = a %% b;
6423 r += ((r != 0) & ((r ^ b) < 0)) * b;
6424 return r;
6425 }
6426 """)
6428 mod_float_utility_code = UtilityCode(
6429 proto="""
6430 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6431 """,
6432 impl="""
6433 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6434 %(type)s r = fmod%(math_h_modifier)s(a, b);
6435 r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
6436 return r;
6437 }
6438 """)
6440 cdivision_warning_utility_code = UtilityCode(
6441 proto="""
6442 static int __Pyx_cdivision_warning(void); /* proto */
6443 """,
6444 impl="""
6445 static int __Pyx_cdivision_warning(void) {
6446 return PyErr_WarnExplicit(PyExc_RuntimeWarning,
6447 "division with oppositely signed operands, C and Python semantics differ",
6448 %(FILENAME)s,
6449 %(LINENO)s,
6450 __Pyx_MODULE_NAME,
6451 NULL);
6452 }
6453 """ % {
6454 'FILENAME': Naming.filename_cname,
6455 'LINENO': Naming.lineno_cname,
6456 })
6458 # from intobject.c
6459 division_overflow_test_code = UtilityCode(
6460 proto="""
6461 #define UNARY_NEG_WOULD_OVERFLOW(x) \
6462 (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
6463 """)
