Cython has moved to github.
cython-devel
view Cython/Compiler/ExprNodes.py @ 2226:fa120664cec4
fix compile time constants in array size declarations (e.g. int a[enum_val+1])
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Fri Apr 10 21:21:02 2009 +0200 (3 years ago) |
| parents | a8780285a470 |
| children | 2db7bd0dc99d |
line source
1 #
2 # Pyrex - Parse tree nodes for expressions
3 #
5 import operator
7 from Errors import error, warning, InternalError
8 from Errors import hold_errors, release_errors, held_errors, report_error
9 from Cython.Utils import UtilityCode
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
16 from Builtin import list_type, tuple_type, set_type, dict_type, unicode_type
17 import Builtin
18 import Symtab
19 import Options
20 from Annotate import AnnotationItem
22 from Cython.Debugging import print_call_chain
23 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
24 debug_coercion
26 try:
27 set
28 except NameError:
29 from sets import Set as set
31 class NotConstant(object): pass # just for the name
32 not_a_constant = NotConstant()
33 constant_value_not_set = object()
35 class ExprNode(Node):
36 # subexprs [string] Class var holding names of subexpr node attrs
37 # type PyrexType Type of the result
38 # result_code string Code fragment
39 # result_ctype string C type of result_code if different from type
40 # is_temp boolean Result is in a temporary variable
41 # is_sequence_constructor
42 # boolean Is a list or tuple constructor expression
43 # is_starred boolean Is a starred expression (e.g. '*a')
44 # saved_subexpr_nodes
45 # [ExprNode or [ExprNode or None] or None]
46 # Cached result of subexpr_nodes()
48 result_ctype = None
49 type = None
50 temp_code = None
51 old_temp = None # error checker for multiple frees etc.
53 # The Analyse Expressions phase for expressions is split
54 # into two sub-phases:
55 #
56 # Analyse Types
57 # Determines the result type of the expression based
58 # on the types of its sub-expressions, and inserts
59 # coercion nodes into the expression tree where needed.
60 # Marks nodes which will need to have temporary variables
61 # allocated.
62 #
63 # Allocate Temps
64 # Allocates temporary variables where needed, and fills
65 # in the result_code field of each node.
66 #
67 # ExprNode provides some convenience routines which
68 # perform both of the above phases. These should only
69 # be called from statement nodes, and only when no
70 # coercion nodes need to be added around the expression
71 # being analysed. In that case, the above two phases
72 # should be invoked separately.
73 #
74 # Framework code in ExprNode provides much of the common
75 # processing for the various phases. It makes use of the
76 # 'subexprs' class attribute of ExprNodes, which should
77 # contain a list of the names of attributes which can
78 # hold sub-nodes or sequences of sub-nodes.
79 #
80 # The framework makes use of a number of abstract methods.
81 # Their responsibilities are as follows.
82 #
83 # Declaration Analysis phase
84 #
85 # analyse_target_declaration
86 # Called during the Analyse Declarations phase to analyse
87 # the LHS of an assignment or argument of a del statement.
88 # Nodes which cannot be the LHS of an assignment need not
89 # implement it.
90 #
91 # Expression Analysis phase
92 #
93 # analyse_types
94 # - Call analyse_types on all sub-expressions.
95 # - Check operand types, and wrap coercion nodes around
96 # sub-expressions where needed.
97 # - Set the type of this node.
98 # - If a temporary variable will be required for the
99 # result, set the is_temp flag of this node.
100 #
101 # analyse_target_types
102 # Called during the Analyse Types phase to analyse
103 # the LHS of an assignment or argument of a del
104 # statement. Similar responsibilities to analyse_types.
105 #
106 # target_code
107 # Called by the default implementation of allocate_target_temps.
108 # Should return a C lvalue for assigning to the node. The default
109 # implementation calls calculate_result_code.
110 #
111 # check_const
112 # - Check that this node and its subnodes form a
113 # legal constant expression. If so, do nothing,
114 # otherwise call not_const.
115 #
116 # The default implementation of check_const
117 # assumes that the expression is not constant.
118 #
119 # check_const_addr
120 # - Same as check_const, except check that the
121 # expression is a C lvalue whose address is
122 # constant. Otherwise, call addr_not_const.
123 #
124 # The default implementation of calc_const_addr
125 # assumes that the expression is not a constant
126 # lvalue.
127 #
128 # Code Generation phase
129 #
130 # generate_evaluation_code
131 # - Call generate_evaluation_code for sub-expressions.
132 # - Perform the functions of generate_result_code
133 # (see below).
134 # - If result is temporary, call generate_disposal_code
135 # on all sub-expressions.
136 #
137 # A default implementation of generate_evaluation_code
138 # is provided which uses the following abstract methods:
139 #
140 # generate_result_code
141 # - Generate any C statements necessary to calculate
142 # the result of this node from the results of its
143 # sub-expressions.
144 #
145 # calculate_result_code
146 # - Should return a C code fragment evaluating to the
147 # result. This is only called when the result is not
148 # a temporary.
149 #
150 # generate_assignment_code
151 # Called on the LHS of an assignment.
152 # - Call generate_evaluation_code for sub-expressions.
153 # - Generate code to perform the assignment.
154 # - If the assignment absorbed a reference, call
155 # generate_post_assignment_code on the RHS,
156 # otherwise call generate_disposal_code on it.
157 #
158 # generate_deletion_code
159 # Called on an argument of a del statement.
160 # - Call generate_evaluation_code for sub-expressions.
161 # - Generate code to perform the deletion.
162 # - Call generate_disposal_code on all sub-expressions.
163 #
164 #
166 is_sequence_constructor = 0
167 is_attribute = 0
169 saved_subexpr_nodes = None
170 is_temp = 0
171 is_target = 0
172 is_starred = 0
174 constant_result = constant_value_not_set
176 try:
177 _get_child_attrs = operator.attrgetter('subexprs')
178 except AttributeError:
179 # Python 2.3
180 def _get_child_attrs(self):
181 return self.subexprs
182 child_attrs = property(fget=_get_child_attrs)
184 def not_implemented(self, method_name):
185 print_call_chain(method_name, "not implemented") ###
186 raise InternalError(
187 "%s.%s not implemented" %
188 (self.__class__.__name__, method_name))
190 def is_lvalue(self):
191 return 0
193 def is_ephemeral(self):
194 # An ephemeral node is one whose result is in
195 # a Python temporary and we suspect there are no
196 # other references to it. Certain operations are
197 # disallowed on such values, since they are
198 # likely to result in a dangling pointer.
199 return self.type.is_pyobject and self.is_temp
201 def subexpr_nodes(self):
202 # Extract a list of subexpression nodes based
203 # on the contents of the subexprs class attribute.
204 nodes = []
205 for name in self.subexprs:
206 item = getattr(self, name)
207 if item is not None:
208 if type(item) is list:
209 nodes.extend(item)
210 else:
211 nodes.append(item)
212 return nodes
214 def result(self):
215 if self.is_temp:
216 return self.temp_code
217 else:
218 return self.calculate_result_code()
220 def result_as(self, type = None):
221 # Return the result code cast to the specified C type.
222 return typecast(type, self.ctype(), self.result())
224 def py_result(self):
225 # Return the result code cast to PyObject *.
226 return self.result_as(py_object_type)
228 def ctype(self):
229 # Return the native C type of the result (i.e. the
230 # C type of the result_code expression).
231 return self.result_ctype or self.type
233 def get_constant_c_result_code(self):
234 # Return the constant value of this node as a result code
235 # string, or None if the node is not constant. This method
236 # can be called when the constant result code is required
237 # before the code generation phase.
238 #
239 # The return value is a string that can represent a simple C
240 # value, a constant C name or a constant C expression. If the
241 # node type depends on Python code, this must return None.
242 return None
244 def calculate_constant_result(self):
245 # Calculate the constant compile time result value of this
246 # expression and store it in ``self.constant_result``. Does
247 # nothing by default, thus leaving ``self.constant_result``
248 # unknown. If valid, the result can be an arbitrary Python
249 # value.
250 #
251 # This must only be called when it is assured that all
252 # sub-expressions have a valid constant_result value. The
253 # ConstantFolding transform will do this.
254 pass
256 def compile_time_value(self, denv):
257 # Return value of compile-time expression, or report error.
258 error(self.pos, "Invalid compile-time expression")
260 def compile_time_value_error(self, e):
261 error(self.pos, "Error in compile-time expression: %s: %s" % (
262 e.__class__.__name__, e))
264 # ------------- Declaration Analysis ----------------
266 def analyse_target_declaration(self, env):
267 error(self.pos, "Cannot assign to or delete this")
269 # ------------- Expression Analysis ----------------
271 def analyse_const_expression(self, env):
272 # Called during the analyse_declarations phase of a
273 # constant expression. Analyses the expression's type,
274 # checks whether it is a legal const expression,
275 # and determines its value.
276 self.analyse_types(env)
277 self.check_const()
279 def analyse_expressions(self, env):
280 # Convenience routine performing both the Type
281 # Analysis and Temp Allocation phases for a whole
282 # expression.
283 self.analyse_types(env)
285 def analyse_target_expression(self, env, rhs):
286 # Convenience routine performing both the Type
287 # Analysis and Temp Allocation phases for the LHS of
288 # an assignment.
289 self.analyse_target_types(env)
291 def analyse_boolean_expression(self, env):
292 # Analyse expression and coerce to a boolean.
293 self.analyse_types(env)
294 bool = self.coerce_to_boolean(env)
295 return bool
297 def analyse_temp_boolean_expression(self, env):
298 # Analyse boolean expression and coerce result into
299 # a temporary. This is used when a branch is to be
300 # performed on the result and we won't have an
301 # opportunity to ensure disposal code is executed
302 # afterwards. By forcing the result into a temporary,
303 # we ensure that all disposal has been done by the
304 # time we get the result.
305 self.analyse_types(env)
306 bool = self.coerce_to_boolean(env)
307 temp_bool = bool.coerce_to_temp(env)
308 return temp_bool
310 # --------------- Type Analysis ------------------
312 def analyse_as_module(self, env):
313 # If this node can be interpreted as a reference to a
314 # cimported module, return its scope, else None.
315 return None
317 def analyse_as_type(self, env):
318 # If this node can be interpreted as a reference to a
319 # type, return that type, else None.
320 return None
322 def analyse_as_extension_type(self, env):
323 # If this node can be interpreted as a reference to an
324 # extension type, return its type, else None.
325 return None
327 def analyse_types(self, env):
328 self.not_implemented("analyse_types")
330 def analyse_target_types(self, env):
331 self.analyse_types(env)
333 def gil_check(self, env):
334 # By default, any expression based on Python objects is
335 # prevented in nogil environments. Subtypes must override
336 # this if they can work without the GIL.
337 if self.type.is_pyobject:
338 self._gil_check(env)
340 def gil_assignment_check(self, env):
341 if env.nogil and self.type.is_pyobject:
342 error(self.pos, "Assignment of Python object not allowed without gil")
344 def check_const(self):
345 self.not_const()
347 def not_const(self):
348 error(self.pos, "Not allowed in a constant expression")
350 def check_const_addr(self):
351 self.addr_not_const()
353 def addr_not_const(self):
354 error(self.pos, "Address is not constant")
356 # ----------------- Result Allocation -----------------
358 def result_in_temp(self):
359 # Return true if result is in a temporary owned by
360 # this node or one of its subexpressions. Overridden
361 # by certain nodes which can share the result of
362 # a subnode.
363 return self.is_temp
365 def target_code(self):
366 # Return code fragment for use as LHS of a C assignment.
367 return self.calculate_result_code()
369 def calculate_result_code(self):
370 self.not_implemented("calculate_result_code")
372 # def release_target_temp(self, env):
373 # # Release temporaries used by LHS of an assignment.
374 # self.release_subexpr_temps(env)
376 def allocate_temp_result(self, code):
377 if self.temp_code:
378 raise RuntimeError("Temp allocated multiple times")
379 type = self.type
380 if not type.is_void:
381 if type.is_pyobject:
382 type = PyrexTypes.py_object_type
383 self.temp_code = code.funcstate.allocate_temp(
384 type, manage_ref=True)
385 else:
386 self.temp_code = None
388 def release_temp_result(self, code):
389 if not self.temp_code:
390 if self.old_temp:
391 raise RuntimeError("temp %s released multiple times in %s" % (
392 self.old_temp, self.__class__.__name__))
393 else:
394 raise RuntimeError("no temp, but release requested in %s" % (
395 self.__class__.__name__))
396 code.funcstate.release_temp(self.temp_code)
397 self.old_temp = self.temp_code
398 self.temp_code = None
400 # ---------------- Code Generation -----------------
402 def make_owned_reference(self, code):
403 # If result is a pyobject, make sure we own
404 # a reference to it.
405 if self.type.is_pyobject and not self.result_in_temp():
406 code.put_incref(self.result(), self.ctype())
408 def generate_evaluation_code(self, code):
409 code.mark_pos(self.pos)
411 # Generate code to evaluate this node and
412 # its sub-expressions, and dispose of any
413 # temporary results of its sub-expressions.
414 self.generate_subexpr_evaluation_code(code)
416 if self.is_temp:
417 self.allocate_temp_result(code)
419 self.generate_result_code(code)
420 if self.is_temp:
421 # If we are temp we do not need to wait until this node is disposed
422 # before disposing children.
423 self.generate_subexpr_disposal_code(code)
424 self.free_subexpr_temps(code)
426 def generate_subexpr_evaluation_code(self, code):
427 for node in self.subexpr_nodes():
428 node.generate_evaluation_code(code)
430 def generate_result_code(self, code):
431 self.not_implemented("generate_result_code")
433 def generate_disposal_code(self, code):
434 if self.is_temp:
435 if self.type.is_pyobject:
436 code.put_decref_clear(self.result(), self.ctype())
437 else:
438 # Already done if self.is_temp
439 self.generate_subexpr_disposal_code(code)
441 def generate_subexpr_disposal_code(self, code):
442 # Generate code to dispose of temporary results
443 # of all sub-expressions.
444 for node in self.subexpr_nodes():
445 node.generate_disposal_code(code)
447 def generate_post_assignment_code(self, code):
448 if self.is_temp:
449 if self.type.is_pyobject:
450 code.putln("%s = 0;" % self.result())
451 else:
452 self.generate_subexpr_disposal_code(code)
454 def generate_assignment_code(self, rhs, code):
455 # Stub method for nodes which are not legal as
456 # the LHS of an assignment. An error will have
457 # been reported earlier.
458 pass
460 def generate_deletion_code(self, code):
461 # Stub method for nodes that are not legal as
462 # the argument of a del statement. An error
463 # will have been reported earlier.
464 pass
466 def free_temps(self, code):
467 if self.is_temp:
468 if not self.type.is_void:
469 self.release_temp_result(code)
470 else:
471 self.free_subexpr_temps(code)
473 def free_subexpr_temps(self, code):
474 for sub in self.subexpr_nodes():
475 sub.free_temps(code)
477 # ---------------- Annotation ---------------------
479 def annotate(self, code):
480 for node in self.subexpr_nodes():
481 node.annotate(code)
483 # ----------------- Coercion ----------------------
485 def coerce_to(self, dst_type, env):
486 # Coerce the result so that it can be assigned to
487 # something of type dst_type. If processing is necessary,
488 # wraps this node in a coercion node and returns that.
489 # Otherwise, returns this node unchanged.
490 #
491 # This method is called during the analyse_expressions
492 # phase of the src_node's processing.
493 src = self
494 src_type = self.type
495 src_is_py_type = src_type.is_pyobject
496 dst_is_py_type = dst_type.is_pyobject
498 if dst_type.is_pyobject:
499 if not src.type.is_pyobject:
500 src = CoerceToPyTypeNode(src, env)
501 if not src.type.subtype_of(dst_type):
502 if not isinstance(src, NoneNode):
503 src = PyTypeTestNode(src, dst_type, env)
504 elif src.type.is_pyobject:
505 src = CoerceFromPyTypeNode(dst_type, src, env)
506 else: # neither src nor dst are py types
507 # Added the string comparison, since for c types that
508 # is enough, but Cython gets confused when the types are
509 # in different files.
510 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
511 error(self.pos, "Cannot assign type '%s' to '%s'" %
512 (src.type, dst_type))
513 return src
515 def coerce_to_pyobject(self, env):
516 return self.coerce_to(PyrexTypes.py_object_type, env)
518 def coerce_to_boolean(self, env):
519 # Coerce result to something acceptable as
520 # a boolean value.
521 type = self.type
522 if type.is_pyobject or type.is_ptr or type.is_float:
523 return CoerceToBooleanNode(self, env)
524 else:
525 if not type.is_int and not type.is_error:
526 error(self.pos,
527 "Type '%s' not acceptable as a boolean" % type)
528 return self
530 def coerce_to_integer(self, env):
531 # If not already some C integer type, coerce to longint.
532 if self.type.is_int:
533 return self
534 else:
535 return self.coerce_to(PyrexTypes.c_long_type, env)
537 def coerce_to_temp(self, env):
538 # Ensure that the result is in a temporary.
539 if self.result_in_temp():
540 return self
541 else:
542 return CoerceToTempNode(self, env)
544 def coerce_to_simple(self, env):
545 # Ensure that the result is simple (see is_simple).
546 if self.is_simple():
547 return self
548 else:
549 return self.coerce_to_temp(env)
551 def is_simple(self):
552 # A node is simple if its result is something that can
553 # be referred to without performing any operations, e.g.
554 # a constant, local var, C global var, struct member
555 # reference, or temporary.
556 return self.result_in_temp()
558 def as_cython_attribute(self):
559 return None
561 class AtomicExprNode(ExprNode):
562 # Abstract base class for expression nodes which have
563 # no sub-expressions.
565 subexprs = []
567 # Override to optimize -- we know we have no children
568 def generate_subexpr_evaluation_code(self, code):
569 pass
570 def generate_subexpr_disposal_code(self, code):
571 pass
573 class PyConstNode(AtomicExprNode):
574 # Abstract base class for constant Python values.
576 is_literal = 1
578 def is_simple(self):
579 return 1
581 def analyse_types(self, env):
582 self.type = py_object_type
584 def calculate_result_code(self):
585 return self.value
587 def generate_result_code(self, code):
588 pass
591 class NoneNode(PyConstNode):
592 # The constant value None
594 value = "Py_None"
596 constant_result = None
597 gil_check = None
599 def compile_time_value(self, denv):
600 return None
602 class EllipsisNode(PyConstNode):
603 # '...' in a subscript list.
605 value = "Py_Ellipsis"
607 constant_result = Ellipsis
609 def compile_time_value(self, denv):
610 return Ellipsis
613 class ConstNode(AtomicExprNode):
614 # Abstract base type for literal constant nodes.
615 #
616 # value string C code fragment
618 is_literal = 1
619 gil_check = None
621 def is_simple(self):
622 return 1
624 def analyse_types(self, env):
625 pass # Types are held in class variables
627 def check_const(self):
628 pass
630 def get_constant_c_result_code(self):
631 return self.calculate_result_code()
633 def calculate_result_code(self):
634 return str(self.value)
636 def generate_result_code(self, code):
637 pass
640 class BoolNode(ConstNode):
641 type = PyrexTypes.c_bint_type
642 # The constant value True or False
644 def calculate_constant_result(self):
645 self.constant_result = self.value
647 def compile_time_value(self, denv):
648 return self.value
650 def calculate_result_code(self):
651 return str(int(self.value))
654 class NullNode(ConstNode):
655 type = PyrexTypes.c_null_ptr_type
656 value = "NULL"
657 constant_result = 0
659 def get_constant_c_result_code(self):
660 return self.value
663 class CharNode(ConstNode):
664 type = PyrexTypes.c_char_type
666 def calculate_constant_result(self):
667 self.constant_result = ord(self.value)
669 def compile_time_value(self, denv):
670 return ord(self.value)
672 def calculate_result_code(self):
673 return "'%s'" % StringEncoding.escape_character(self.value)
676 class IntNode(ConstNode):
678 # unsigned "" or "U"
679 # longness "" or "L" or "LL"
681 unsigned = ""
682 longness = ""
683 type = PyrexTypes.c_long_type
685 def coerce_to(self, dst_type, env):
686 if dst_type.is_numeric:
687 self.type = PyrexTypes.c_long_type
688 return self
689 # Arrange for a Python version of the number to be pre-allocated
690 # when coercing to a Python type.
691 if dst_type.is_pyobject:
692 self.type = PyrexTypes.py_object_type
693 # We still need to perform normal coerce_to processing on the
694 # result, because we might be coercing to an extension type,
695 # in which case a type test node will be needed.
696 return ConstNode.coerce_to(self, dst_type, env)
698 def coerce_to_boolean(self, env):
699 self.type = PyrexTypes.c_bint_type
700 return self
702 def generate_evaluation_code(self, code):
703 if self.type.is_pyobject:
704 self.result_code = code.get_py_num(self.value, self.longness)
705 else:
706 self.result_code = self.get_constant_c_result_code()
708 def get_constant_c_result_code(self):
709 return str(self.value) + self.unsigned + self.longness
711 def calculate_result_code(self):
712 return self.result_code
714 def calculate_constant_result(self):
715 self.constant_result = int(self.value, 0)
717 def compile_time_value(self, denv):
718 return int(self.value, 0)
721 class FloatNode(ConstNode):
722 type = PyrexTypes.c_double_type
724 def calculate_constant_result(self):
725 # calculating float values is usually not a good idea
726 #self.constant_result = float(self.value)
727 pass
729 def compile_time_value(self, denv):
730 return float(self.value)
732 def calculate_result_code(self):
733 strval = repr(float(self.value))
734 if strval == 'nan':
735 return "(Py_HUGE_VAL * 0)"
736 elif strval == 'inf':
737 return "Py_HUGE_VAL"
738 elif strval == '-inf':
739 return "(-Py_HUGE_VAL)"
740 else:
741 return strval
744 class StringNode(ConstNode):
745 type = PyrexTypes.c_char_ptr_type
747 def compile_time_value(self, denv):
748 return self.value
750 def analyse_as_type(self, env):
751 type = PyrexTypes.parse_basic_type(self.value)
752 if type is not None:
753 return type
754 from TreeFragment import TreeFragment
755 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
756 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
757 sizeof_node = declaration.root.stats[0].expr
758 sizeof_node.analyse_types(env)
759 if isinstance(sizeof_node, SizeofTypeNode):
760 return sizeof_node.arg_type
762 def coerce_to(self, dst_type, env):
763 if dst_type == PyrexTypes.c_char_ptr_type:
764 self.type = PyrexTypes.c_char_ptr_type
765 return self
767 if dst_type.is_int:
768 if not self.type.is_pyobject and len(self.value) == 1:
769 return CharNode(self.pos, value=self.value)
770 else:
771 error(self.pos, "Only single-character byte strings can be coerced into ints.")
772 return self
773 # Arrange for a Python version of the string to be pre-allocated
774 # when coercing to a Python type.
775 if dst_type.is_pyobject and not self.type.is_pyobject:
776 node = self.as_py_string_node(env)
777 else:
778 node = self
779 # We still need to perform normal coerce_to processing on the
780 # result, because we might be coercing to an extension type,
781 # in which case a type test node will be needed.
782 return ConstNode.coerce_to(node, dst_type, env)
784 def as_py_string_node(self, env):
785 # Return a new StringNode with the same value as this node
786 # but whose type is a Python type instead of a C type.
787 return StringNode(self.pos, value = self.value, type = py_object_type)
789 def generate_evaluation_code(self, code):
790 if self.type.is_pyobject:
791 self.result_code = code.get_py_string_const(self.value)
792 else:
793 self.result_code = code.get_string_const(self.value)
795 def get_constant_c_result_code(self):
796 return None # FIXME
798 def calculate_result_code(self):
799 return self.result_code
802 class UnicodeNode(PyConstNode):
803 type = unicode_type
805 def coerce_to(self, dst_type, env):
806 if dst_type.is_pyobject:
807 return self
808 else:
809 error(self.pos, "Unicode objects do not support coercion to C types.")
810 return self
812 def generate_evaluation_code(self, code):
813 if self.type.is_pyobject:
814 self.result_code = code.get_py_string_const(self.value)
815 else:
816 self.result_code = code.get_string_const(self.value)
818 def calculate_result_code(self):
819 return self.result_code
821 def compile_time_value(self, env):
822 return self.value
825 class IdentifierStringNode(ConstNode):
826 # A Python string that behaves like an identifier, e.g. for
827 # keyword arguments in a call, or for imported names
828 type = PyrexTypes.py_object_type
830 def generate_evaluation_code(self, code):
831 if self.type.is_pyobject:
832 self.result_code = code.get_py_string_const(self.value, True)
833 else:
834 self.result_code = code.get_string_const(self.value)
836 def get_constant_c_result_code(self):
837 return None
839 def calculate_result_code(self):
840 return self.result_code
843 class LongNode(AtomicExprNode):
844 # Python long integer literal
845 #
846 # value string
848 def calculate_constant_result(self):
849 self.constant_result = long(self.value)
851 def compile_time_value(self, denv):
852 return long(self.value)
854 def analyse_types(self, env):
855 self.type = py_object_type
856 self.is_temp = 1
858 gil_message = "Constructing Python long int"
860 def generate_result_code(self, code):
861 code.putln(
862 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
863 self.result(),
864 self.value,
865 code.error_goto_if_null(self.result(), self.pos)))
866 code.put_gotref(self.py_result())
869 class ImagNode(AtomicExprNode):
870 # Imaginary number literal
871 #
872 # value float imaginary part
874 def calculate_constant_result(self):
875 self.constant_result = complex(0.0, self.value)
877 def compile_time_value(self, denv):
878 return complex(0.0, self.value)
880 def analyse_types(self, env):
881 self.type = py_object_type
882 self.is_temp = 1
884 gil_message = "Constructing complex number"
886 def generate_result_code(self, code):
887 code.putln(
888 "%s = PyComplex_FromDoubles(0.0, %r); %s" % (
889 self.result(),
890 float(self.value),
891 code.error_goto_if_null(self.result(), self.pos)))
892 code.put_gotref(self.py_result())
896 class NameNode(AtomicExprNode):
897 # Reference to a local or global variable name.
898 #
899 # name string Python name of the variable
900 # entry Entry Symbol table entry
901 # type_entry Entry For extension type names, the original type entry
903 is_name = True
904 is_cython_module = False
905 cython_attribute = None
906 lhs_of_first_assignment = False
907 is_used_as_rvalue = 0
908 entry = None
909 type_entry = None
911 def create_analysed_rvalue(pos, env, entry):
912 node = NameNode(pos)
913 node.analyse_types(env, entry=entry)
914 return node
916 def as_cython_attribute(self):
917 return self.cython_attribute
919 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
921 def compile_time_value(self, denv):
922 try:
923 return denv.lookup(self.name)
924 except KeyError:
925 error(self.pos, "Compile-time name '%s' not defined" % self.name)
927 def get_constant_c_result_code(self):
928 if not self.entry or self.entry.type.is_pyobject:
929 return None
930 return self.entry.cname
932 def coerce_to(self, dst_type, env):
933 # If coercing to a generic pyobject and this is a builtin
934 # C function with a Python equivalent, manufacture a NameNode
935 # referring to the Python builtin.
936 #print "NameNode.coerce_to:", self.name, dst_type ###
937 if dst_type is py_object_type:
938 entry = self.entry
939 if entry and entry.is_cfunction:
940 var_entry = entry.as_variable
941 if var_entry:
942 if var_entry.is_builtin and Options.cache_builtins:
943 var_entry = env.declare_builtin(var_entry.name, self.pos)
944 node = NameNode(self.pos, name = self.name)
945 node.entry = var_entry
946 node.analyse_rvalue_entry(env)
947 return node
948 return super(NameNode, self).coerce_to(dst_type, env)
950 def analyse_as_module(self, env):
951 # Try to interpret this as a reference to a cimported module.
952 # Returns the module scope, or None.
953 entry = self.entry
954 if not entry:
955 entry = env.lookup(self.name)
956 if entry and entry.as_module:
957 return entry.as_module
958 return None
960 def analyse_as_type(self, env):
961 if self.cython_attribute:
962 type = PyrexTypes.parse_basic_type(self.cython_attribute)
963 else:
964 type = PyrexTypes.parse_basic_type(self.name)
965 if type:
966 return type
967 entry = self.entry
968 if not entry:
969 entry = env.lookup(self.name)
970 if entry and entry.is_type:
971 return entry.type
972 else:
973 return None
975 def analyse_as_extension_type(self, env):
976 # Try to interpret this as a reference to an extension type.
977 # Returns the extension type, or None.
978 entry = self.entry
979 if not entry:
980 entry = env.lookup(self.name)
981 if entry and entry.is_type and entry.type.is_extension_type:
982 return entry.type
983 else:
984 return None
986 def analyse_target_declaration(self, env):
987 if not self.entry:
988 self.entry = env.lookup_here(self.name)
989 if not self.entry:
990 self.entry = env.declare_var(self.name, py_object_type, self.pos)
991 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
992 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
993 if self.entry.is_declared_generic:
994 self.result_ctype = py_object_type
996 def analyse_types(self, env):
997 if self.entry is None:
998 self.entry = env.lookup(self.name)
999 if not self.entry:
1000 self.entry = env.declare_builtin(self.name, self.pos)
1001 if not self.entry:
1002 self.type = PyrexTypes.error_type
1003 return
1004 entry = self.entry
1005 if entry:
1006 entry.used = 1
1007 if entry.type.is_buffer:
1008 import Buffer
1009 Buffer.used_buffer_aux_vars(entry)
1010 if entry.utility_code:
1011 env.use_utility_code(entry.utility_code)
1012 self.analyse_rvalue_entry(env)
1014 def analyse_target_types(self, env):
1015 self.analyse_entry(env)
1016 if not self.is_lvalue():
1017 error(self.pos, "Assignment to non-lvalue '%s'"
1018 % self.name)
1019 self.type = PyrexTypes.error_type
1020 self.entry.used = 1
1021 if self.entry.type.is_buffer:
1022 import Buffer
1023 Buffer.used_buffer_aux_vars(self.entry)
1025 def analyse_rvalue_entry(self, env):
1026 #print "NameNode.analyse_rvalue_entry:", self.name ###
1027 #print "Entry:", self.entry.__dict__ ###
1028 self.analyse_entry(env)
1029 entry = self.entry
1030 if entry.is_declared_generic:
1031 self.result_ctype = py_object_type
1032 if entry.is_pyglobal or entry.is_builtin:
1033 if Options.cache_builtins and entry.is_builtin:
1034 self.is_temp = 0
1035 else:
1036 self.is_temp = 1
1037 self.is_used_as_rvalue = 1
1038 env.use_utility_code(get_name_interned_utility_code)
1040 def gil_check(self, env):
1041 if self.is_used_as_rvalue:
1042 entry = self.entry
1043 if entry.is_builtin:
1044 # if not Options.cache_builtins: # cached builtins are ok
1045 self._gil_check(env)
1046 elif entry.is_pyglobal:
1047 self._gil_check(env)
1049 gil_message = "Accessing Python global or builtin"
1051 def analyse_entry(self, env):
1052 #print "NameNode.analyse_entry:", self.name ###
1053 self.check_identifier_kind()
1054 entry = self.entry
1055 type = entry.type
1056 self.type = type
1058 def check_identifier_kind(self):
1059 # Check that this is an appropriate kind of name for use in an
1060 # expression. Also finds the variable entry associated with
1061 # an extension type.
1062 entry = self.entry
1063 if entry.is_type and entry.type.is_extension_type:
1064 self.type_entry = entry
1065 if not (entry.is_const or entry.is_variable
1066 or entry.is_builtin or entry.is_cfunction):
1067 if self.entry.as_variable:
1068 self.entry = self.entry.as_variable
1069 else:
1070 error(self.pos,
1071 "'%s' is not a constant, variable or function identifier" % self.name)
1073 def is_simple(self):
1074 # If it's not a C variable, it'll be in a temp.
1075 return 1
1077 def calculate_target_results(self, env):
1078 pass
1080 def check_const(self):
1081 entry = self.entry
1082 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1083 self.not_const()
1085 def check_const_addr(self):
1086 entry = self.entry
1087 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1088 self.addr_not_const()
1090 def is_lvalue(self):
1091 return self.entry.is_variable and \
1092 not self.entry.type.is_array and \
1093 not self.entry.is_readonly
1095 def is_ephemeral(self):
1096 # Name nodes are never ephemeral, even if the
1097 # result is in a temporary.
1098 return 0
1100 def calculate_result_code(self):
1101 entry = self.entry
1102 if not entry:
1103 return "<error>" # There was an error earlier
1104 return entry.cname
1106 def generate_result_code(self, code):
1107 assert hasattr(self, 'entry')
1108 entry = self.entry
1109 if entry is None:
1110 return # There was an error earlier
1111 if entry.is_builtin and Options.cache_builtins:
1112 return # Lookup already cached
1113 elif entry.is_pyglobal or entry.is_builtin:
1114 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1115 interned_cname = code.intern_identifier(self.entry.name)
1116 if entry.is_builtin:
1117 namespace = Naming.builtins_cname
1118 else: # entry.is_pyglobal
1119 namespace = entry.scope.namespace_cname
1120 code.putln(
1121 '%s = __Pyx_GetName(%s, %s); %s' % (
1122 self.result(),
1123 namespace,
1124 interned_cname,
1125 code.error_goto_if_null(self.result(), self.pos)))
1126 code.put_gotref(self.py_result())
1128 elif entry.is_local and False:
1129 # control flow not good enough yet
1130 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1131 if assigned is False:
1132 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1133 elif not Options.init_local_none and assigned is None:
1134 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
1135 (entry.cname, entry.name, code.error_goto(self.pos)))
1136 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1138 def generate_assignment_code(self, rhs, code):
1139 #print "NameNode.generate_assignment_code:", self.name ###
1140 entry = self.entry
1141 if entry is None:
1142 return # There was an error earlier
1144 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1145 and not self.lhs_of_first_assignment):
1146 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1148 # is_pyglobal seems to be True for module level-globals only.
1149 # We use this to access class->tp_dict if necessary.
1150 if entry.is_pyglobal:
1151 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1152 interned_cname = code.intern_identifier(self.entry.name)
1153 namespace = self.entry.scope.namespace_cname
1154 if entry.is_member:
1155 # if the entry is a member we have to cheat: SetAttr does not work
1156 # on types, so we create a descriptor which is then added to tp_dict
1157 code.put_error_if_neg(self.pos,
1158 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1159 namespace,
1160 interned_cname,
1161 rhs.py_result()))
1162 rhs.generate_disposal_code(code)
1163 rhs.free_temps(code)
1164 # in Py2.6+, we need to invalidate the method cache
1165 code.putln("PyType_Modified(%s);" %
1166 entry.scope.parent_type.typeptr_cname)
1167 else:
1168 code.put_error_if_neg(self.pos,
1169 'PyObject_SetAttr(%s, %s, %s)' % (
1170 namespace,
1171 interned_cname,
1172 rhs.py_result()))
1173 if debug_disposal_code:
1174 print("NameNode.generate_assignment_code:")
1175 print("...generating disposal code for %s" % rhs)
1176 rhs.generate_disposal_code(code)
1177 rhs.free_temps(code)
1178 else:
1179 if self.type.is_buffer:
1180 # Generate code for doing the buffer release/acquisition.
1181 # This might raise an exception in which case the assignment (done
1182 # below) will not happen.
1183 #
1184 # The reason this is not in a typetest-like node is because the
1185 # variables that the acquired buffer info is stored to is allocated
1186 # per entry and coupled with it.
1187 self.generate_acquire_buffer(rhs, code)
1189 if self.type.is_pyobject:
1190 rhs.make_owned_reference(code)
1191 #print "NameNode.generate_assignment_code: to", self.name ###
1192 #print "...from", rhs ###
1193 #print "...LHS type", self.type, "ctype", self.ctype() ###
1194 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1195 if entry.is_cglobal:
1196 code.put_gotref(self.py_result())
1197 if not self.lhs_of_first_assignment:
1198 if entry.is_local and not Options.init_local_none:
1199 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1200 if initalized is True:
1201 code.put_decref(self.result(), self.ctype())
1202 elif initalized is None:
1203 code.put_xdecref(self.result(), self.ctype())
1204 else:
1205 code.put_decref(self.result(), self.ctype())
1206 if entry.is_cglobal:
1207 code.put_giveref(rhs.py_result())
1208 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1209 if debug_disposal_code:
1210 print("NameNode.generate_assignment_code:")
1211 print("...generating post-assignment code for %s" % rhs)
1212 rhs.generate_post_assignment_code(code)
1213 rhs.free_temps(code)
1215 def generate_acquire_buffer(self, rhs, code):
1216 # rhstmp is only used in case the rhs is a complicated expression leading to
1217 # the object, to avoid repeating the same C expression for every reference
1218 # to the rhs. It does NOT hold a reference.
1219 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1220 if pretty_rhs:
1221 rhstmp = rhs.result_as(self.ctype())
1222 else:
1223 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1224 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1226 buffer_aux = self.entry.buffer_aux
1227 bufstruct = buffer_aux.buffer_info_var.cname
1228 import Buffer
1229 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1230 is_initialized=not self.lhs_of_first_assignment,
1231 pos=self.pos, code=code)
1233 if not pretty_rhs:
1234 code.putln("%s = 0;" % rhstmp)
1235 code.funcstate.release_temp(rhstmp)
1237 def generate_deletion_code(self, code):
1238 if self.entry is None:
1239 return # There was an error earlier
1240 if not self.entry.is_pyglobal:
1241 error(self.pos, "Deletion of local or C global name not supported")
1242 return
1243 code.put_error_if_neg(self.pos,
1244 '__Pyx_DelAttrString(%s, "%s")' % (
1245 Naming.module_cname,
1246 self.entry.name))
1248 def annotate(self, code):
1249 if hasattr(self, 'is_called') and self.is_called:
1250 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1251 if self.type.is_pyobject:
1252 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1253 else:
1254 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1256 class BackquoteNode(ExprNode):
1257 # `expr`
1258 #
1259 # arg ExprNode
1261 subexprs = ['arg']
1263 def analyse_types(self, env):
1264 self.arg.analyse_types(env)
1265 self.arg = self.arg.coerce_to_pyobject(env)
1266 self.type = py_object_type
1267 self.is_temp = 1
1269 gil_message = "Backquote expression"
1271 def calculate_constant_result(self):
1272 self.constant_result = repr(self.arg.constant_result)
1274 def generate_result_code(self, code):
1275 code.putln(
1276 "%s = PyObject_Repr(%s); %s" % (
1277 self.result(),
1278 self.arg.py_result(),
1279 code.error_goto_if_null(self.result(), self.pos)))
1280 code.put_gotref(self.py_result())
1284 class ImportNode(ExprNode):
1285 # Used as part of import statement implementation.
1286 # Implements result =
1287 # __import__(module_name, globals(), None, name_list)
1288 #
1289 # module_name IdentifierStringNode dotted name of module
1290 # name_list ListNode or None list of names to be imported
1292 subexprs = ['module_name', 'name_list']
1294 def analyse_types(self, env):
1295 self.module_name.analyse_types(env)
1296 self.module_name = self.module_name.coerce_to_pyobject(env)
1297 if self.name_list:
1298 self.name_list.analyse_types(env)
1299 self.name_list.coerce_to_pyobject(env)
1300 self.type = py_object_type
1301 self.is_temp = 1
1302 env.use_utility_code(import_utility_code)
1304 gil_message = "Python import"
1306 def generate_result_code(self, code):
1307 if self.name_list:
1308 name_list_code = self.name_list.py_result()
1309 else:
1310 name_list_code = "0"
1311 code.putln(
1312 "%s = __Pyx_Import(%s, %s); %s" % (
1313 self.result(),
1314 self.module_name.py_result(),
1315 name_list_code,
1316 code.error_goto_if_null(self.result(), self.pos)))
1317 code.put_gotref(self.py_result())
1320 class IteratorNode(ExprNode):
1321 # Used as part of for statement implementation.
1322 #
1323 # allocate_counter_temp/release_counter_temp needs to be called
1324 # by parent (ForInStatNode)
1325 #
1326 # Implements result = iter(sequence)
1327 #
1328 # sequence ExprNode
1330 subexprs = ['sequence']
1332 def analyse_types(self, env):
1333 self.sequence.analyse_types(env)
1334 self.sequence = self.sequence.coerce_to_pyobject(env)
1335 self.type = py_object_type
1336 self.is_temp = 1
1338 gil_message = "Iterating over Python object"
1340 def allocate_counter_temp(self, code):
1341 self.counter_cname = code.funcstate.allocate_temp(
1342 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1344 def release_counter_temp(self, code):
1345 code.funcstate.release_temp(self.counter_cname)
1347 def generate_result_code(self, code):
1348 is_builtin_sequence = self.sequence.type is list_type or \
1349 self.sequence.type is tuple_type
1350 if is_builtin_sequence:
1351 code.putln(
1352 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1353 else:
1354 code.putln(
1355 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1356 self.sequence.py_result(),
1357 self.sequence.py_result()))
1358 code.putln(
1359 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
1360 self.counter_cname,
1361 self.result(),
1362 self.sequence.py_result(),
1363 self.result()))
1364 code.putln("} else {")
1365 if is_builtin_sequence:
1366 code.putln(
1367 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1368 code.error_goto(self.pos))
1369 else:
1370 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1371 self.counter_cname,
1372 self.result(),
1373 self.sequence.py_result(),
1374 code.error_goto_if_null(self.result(), self.pos)))
1375 code.put_gotref(self.py_result())
1376 code.putln("}")
1379 class NextNode(AtomicExprNode):
1380 # Used as part of for statement implementation.
1381 # Implements result = iterator.next()
1382 # Created during analyse_types phase.
1383 # The iterator is not owned by this node.
1384 #
1385 # iterator ExprNode
1387 def __init__(self, iterator, env):
1388 self.pos = iterator.pos
1389 self.iterator = iterator
1390 self.type = py_object_type
1391 self.is_temp = 1
1393 def generate_result_code(self, code):
1394 if self.iterator.sequence.type is list_type:
1395 type_checks = [(list_type, "List")]
1396 elif self.iterator.sequence.type is tuple_type:
1397 type_checks = [(tuple_type, "Tuple")]
1398 else:
1399 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1401 for py_type, prefix in type_checks:
1402 if len(type_checks) > 1:
1403 code.putln(
1404 "if (likely(Py%s_CheckExact(%s))) {" % (
1405 prefix, self.iterator.py_result()))
1406 code.putln(
1407 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1408 self.iterator.counter_cname,
1409 prefix,
1410 self.iterator.py_result()))
1411 code.putln(
1412 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1413 self.result(),
1414 prefix,
1415 self.iterator.py_result(),
1416 self.iterator.counter_cname,
1417 self.result(),
1418 self.iterator.counter_cname))
1419 if len(type_checks) > 1:
1420 code.put("} else ")
1421 if len(type_checks) == 1:
1422 return
1423 code.putln("{")
1424 code.putln(
1425 "%s = PyIter_Next(%s);" % (
1426 self.result(),
1427 self.iterator.py_result()))
1428 code.putln(
1429 "if (!%s) {" %
1430 self.result())
1431 code.putln(code.error_goto_if_PyErr(self.pos))
1432 code.putln("break;")
1433 code.putln("}")
1434 code.put_gotref(self.py_result())
1435 code.putln("}")
1438 class ExcValueNode(AtomicExprNode):
1439 # Node created during analyse_types phase
1440 # of an ExceptClauseNode to fetch the current
1441 # exception value.
1443 def __init__(self, pos, env):
1444 ExprNode.__init__(self, pos)
1445 self.type = py_object_type
1447 def set_var(self, var):
1448 self.var = var
1450 def calculate_result_code(self):
1451 return self.var
1453 def generate_result_code(self, code):
1454 pass
1456 def analyse_types(self, env):
1457 pass
1460 class TempNode(ExprNode):
1461 # Node created during analyse_types phase
1462 # of some nodes to hold a temporary value.
1463 #
1464 # Note: One must call "allocate" and "release" on
1465 # the node during code generation to get/release the temp.
1466 # This is because the temp result is often used outside of
1467 # the regular cycle.
1469 subexprs = []
1471 def __init__(self, pos, type, env):
1472 ExprNode.__init__(self, pos)
1473 self.type = type
1474 if type.is_pyobject:
1475 self.result_ctype = py_object_type
1476 self.is_temp = 1
1478 def analyse_types(self, env):
1479 return self.type
1481 def generate_result_code(self, code):
1482 pass
1484 def allocate(self, code):
1485 self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=True)
1487 def release(self, code):
1488 code.funcstate.release_temp(self.temp_cname)
1489 self.temp_cname = None
1491 def result(self):
1492 try:
1493 return self.temp_cname
1494 except:
1495 assert False, "Remember to call allocate/release on TempNode"
1496 raise
1498 # Do not participate in normal temp alloc/dealloc:
1499 def allocate_temp_result(self, code):
1500 pass
1502 def release_temp_result(self, code):
1503 pass
1505 class PyTempNode(TempNode):
1506 # TempNode holding a Python value.
1508 def __init__(self, pos, env):
1509 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1512 #-------------------------------------------------------------------
1513 #
1514 # Trailer nodes
1515 #
1516 #-------------------------------------------------------------------
1518 class IndexNode(ExprNode):
1519 # Sequence indexing.
1520 #
1521 # base ExprNode
1522 # index ExprNode
1523 # indices [ExprNode]
1524 # is_buffer_access boolean Whether this is a buffer access.
1525 #
1526 # indices is used on buffer access, index on non-buffer access.
1527 # The former contains a clean list of index parameters, the
1528 # latter whatever Python object is needed for index access.
1530 subexprs = ['base', 'index', 'indices']
1531 indices = None
1533 def __init__(self, pos, index, *args, **kw):
1534 ExprNode.__init__(self, pos, index=index, *args, **kw)
1535 self._index = index
1537 def calculate_constant_result(self):
1538 self.constant_result = \
1539 self.base.constant_result[self.index.constant_result]
1541 def compile_time_value(self, denv):
1542 base = self.base.compile_time_value(denv)
1543 index = self.index.compile_time_value(denv)
1544 try:
1545 return base[index]
1546 except Exception, e:
1547 self.compile_time_value_error(e)
1549 def is_ephemeral(self):
1550 return self.base.is_ephemeral()
1552 def analyse_target_declaration(self, env):
1553 pass
1555 def analyse_as_type(self, env):
1556 base_type = self.base.analyse_as_type(env)
1557 if base_type and not base_type.is_pyobject:
1558 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1559 return None
1561 def analyse_types(self, env):
1562 self.analyse_base_and_index_types(env, getting = 1)
1564 def analyse_target_types(self, env):
1565 self.analyse_base_and_index_types(env, setting = 1)
1567 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1568 # Note: This might be cleaned up by having IndexNode
1569 # parsed in a saner way and only construct the tuple if
1570 # needed.
1572 # Note that this function must leave IndexNode in a cloneable state.
1573 # For buffers, self.index is packed out on the initial analysis, and
1574 # when cloning self.indices is copied.
1575 self.is_buffer_access = False
1577 self.base.analyse_types(env)
1578 # Handle the case where base is a literal char* (and we expect a string, not an int)
1579 if isinstance(self.base, StringNode):
1580 self.base = self.base.coerce_to_pyobject(env)
1582 skip_child_analysis = False
1583 buffer_access = False
1584 if self.base.type.is_buffer:
1585 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1586 if self.indices:
1587 indices = self.indices
1588 else:
1589 # On cloning, indices is cloned. Otherwise, unpack index into indices
1590 assert not isinstance(self.index, CloneNode)
1591 if isinstance(self.index, TupleNode):
1592 indices = self.index.args
1593 else:
1594 indices = [self.index]
1595 if len(indices) == self.base.type.ndim:
1596 buffer_access = True
1597 skip_child_analysis = True
1598 for x in indices:
1599 x.analyse_types(env)
1600 if not x.type.is_int:
1601 buffer_access = False
1603 if buffer_access:
1604 self.indices = indices
1605 self.index = None
1606 self.type = self.base.type.dtype
1607 self.is_buffer_access = True
1608 self.buffer_type = self.base.entry.type
1610 if getting and self.type.is_pyobject:
1611 self.is_temp = True
1612 if setting:
1613 if not self.base.entry.type.writable:
1614 error(self.pos, "Writing to readonly buffer")
1615 else:
1616 self.base.entry.buffer_aux.writable_needed = True
1617 else:
1618 if isinstance(self.index, TupleNode):
1619 self.index.analyse_types(env, skip_children=skip_child_analysis)
1620 elif not skip_child_analysis:
1621 self.index.analyse_types(env)
1622 self.original_index_type = self.index.type
1623 if self.base.type.is_pyobject:
1624 if self.index.type.is_int:
1625 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1626 else:
1627 self.index = self.index.coerce_to_pyobject(env)
1628 self.type = py_object_type
1629 self.is_temp = 1
1630 else:
1631 if self.base.type.is_ptr or self.base.type.is_array:
1632 self.type = self.base.type.base_type
1633 else:
1634 error(self.pos,
1635 "Attempting to index non-array type '%s'" %
1636 self.base.type)
1637 self.type = PyrexTypes.error_type
1638 if self.index.type.is_pyobject:
1639 self.index = self.index.coerce_to(
1640 PyrexTypes.c_py_ssize_t_type, env)
1641 if not self.index.type.is_int:
1642 error(self.pos,
1643 "Invalid index type '%s'" %
1644 self.index.type)
1646 def gil_check(self, env):
1647 if not self.is_buffer_access:
1648 if self.base.type.is_pyobject:
1649 self._gil_check(env)
1651 gil_message = "Indexing Python object"
1653 def check_const_addr(self):
1654 self.base.check_const_addr()
1655 self.index.check_const()
1657 def is_lvalue(self):
1658 return 1
1660 def calculate_result_code(self):
1661 if self.is_buffer_access:
1662 return "(*%s)" % self.buffer_ptr_code
1663 else:
1664 return "(%s[%s])" % (
1665 self.base.result(), self.index.result())
1667 def extra_index_params(self):
1668 if self.index.type.is_int:
1669 if self.original_index_type.signed:
1670 size_adjustment = ""
1671 else:
1672 size_adjustment = "+1"
1673 return ", sizeof(%s)%s, %s" % (self.original_index_type.declaration_code(""), size_adjustment, self.original_index_type.to_py_function)
1674 else:
1675 return ""
1677 def generate_subexpr_evaluation_code(self, code):
1678 self.base.generate_evaluation_code(code)
1679 if not self.indices:
1680 self.index.generate_evaluation_code(code)
1681 else:
1682 for i in self.indices:
1683 i.generate_evaluation_code(code)
1685 def generate_subexpr_disposal_code(self, code):
1686 self.base.generate_disposal_code(code)
1687 if not self.indices:
1688 self.index.generate_disposal_code(code)
1689 else:
1690 for i in self.indices:
1691 i.generate_disposal_code(code)
1693 def free_subexpr_temps(self, code):
1694 self.base.free_temps(code)
1695 if not self.indices:
1696 self.index.free_temps(code)
1697 else:
1698 for i in self.indices:
1699 i.free_temps(code)
1701 def generate_result_code(self, code):
1702 if self.is_buffer_access:
1703 if code.globalstate.directives['nonecheck']:
1704 self.put_nonecheck(code)
1705 self.buffer_ptr_code = self.buffer_lookup_code(code)
1706 if self.type.is_pyobject:
1707 # is_temp is True, so must pull out value and incref it.
1708 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1709 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
1710 elif self.type.is_pyobject:
1711 if self.index.type.is_int:
1712 index_code = self.index.result()
1713 if self.base.type is list_type:
1714 function = "__Pyx_GetItemInt_List"
1715 elif self.base.type is tuple_type:
1716 function = "__Pyx_GetItemInt_Tuple"
1717 else:
1718 function = "__Pyx_GetItemInt"
1719 code.globalstate.use_utility_code(getitem_int_utility_code)
1720 else:
1721 function = "PyObject_GetItem"
1722 index_code = self.index.py_result()
1723 sign_code = ""
1724 code.putln(
1725 "%s = %s(%s, %s%s); if (!%s) %s" % (
1726 self.result(),
1727 function,
1728 self.base.py_result(),
1729 index_code,
1730 self.extra_index_params(),
1731 self.result(),
1732 code.error_goto(self.pos)))
1733 code.put_gotref(self.py_result())
1735 def generate_setitem_code(self, value_code, code):
1736 if self.index.type.is_int:
1737 function = "__Pyx_SetItemInt"
1738 index_code = self.index.result()
1739 code.globalstate.use_utility_code(setitem_int_utility_code)
1740 else:
1741 index_code = self.index.py_result()
1742 if self.base.type is dict_type:
1743 function = "PyDict_SetItem"
1744 elif self.base.type is list_type:
1745 function = "PyList_SetItem"
1746 # don't use PyTuple_SetItem(), as we'd normally get a
1747 # TypeError when changing a tuple, while PyTuple_SetItem()
1748 # would allow updates
1749 #
1750 #elif self.base.type is tuple_type:
1751 # function = "PyTuple_SetItem"
1752 else:
1753 function = "PyObject_SetItem"
1754 code.putln(
1755 "if (%s(%s, %s, %s%s) < 0) %s" % (
1756 function,
1757 self.base.py_result(),
1758 index_code,
1759 value_code,
1760 self.extra_index_params(),
1761 code.error_goto(self.pos)))
1763 def generate_buffer_setitem_code(self, rhs, code, op=""):
1764 # Used from generate_assignment_code and InPlaceAssignmentNode
1765 if code.globalstate.directives['nonecheck']:
1766 self.put_nonecheck(code)
1767 ptrexpr = self.buffer_lookup_code(code)
1768 if self.buffer_type.dtype.is_pyobject:
1769 # Must manage refcounts. Decref what is already there
1770 # and incref what we put in.
1771 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
1772 rhs_code = rhs.result()
1773 code.putln("%s = %s;" % (ptr, ptrexpr))
1774 code.put_gotref("*%s" % ptr)
1775 code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
1776 ptr, rhs_code
1777 ))
1778 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1779 code.put_giveref("*%s" % ptr)
1780 code.funcstate.release_temp(ptr)
1781 else:
1782 # Simple case
1783 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1785 def generate_assignment_code(self, rhs, code):
1786 self.generate_subexpr_evaluation_code(code)
1787 if self.is_buffer_access:
1788 self.generate_buffer_setitem_code(rhs, code)
1789 elif self.type.is_pyobject:
1790 self.generate_setitem_code(rhs.py_result(), code)
1791 else:
1792 code.putln(
1793 "%s = %s;" % (
1794 self.result(), rhs.result()))
1795 self.generate_subexpr_disposal_code(code)
1796 self.free_subexpr_temps(code)
1797 rhs.generate_disposal_code(code)
1798 rhs.free_temps(code)
1800 def generate_deletion_code(self, code):
1801 self.generate_subexpr_evaluation_code(code)
1802 #if self.type.is_pyobject:
1803 if self.index.type.is_int:
1804 function = "__Pyx_DelItemInt"
1805 index_code = self.index.result()
1806 code.globalstate.use_utility_code(delitem_int_utility_code)
1807 else:
1808 index_code = self.index.py_result()
1809 if self.base.type is dict_type:
1810 function = "PyDict_DelItem"
1811 else:
1812 function = "PyObject_DelItem"
1813 code.putln(
1814 "if (%s(%s, %s%s) < 0) %s" % (
1815 function,
1816 self.base.py_result(),
1817 index_code,
1818 self.extra_index_params(),
1819 code.error_goto(self.pos)))
1820 self.generate_subexpr_disposal_code(code)
1821 self.free_subexpr_temps(code)
1823 def buffer_lookup_code(self, code):
1824 # Assign indices to temps
1825 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
1826 for temp, index in zip(index_temps, self.indices):
1827 code.putln("%s = %s;" % (temp, index.result()))
1828 # Generate buffer access code using these temps
1829 import Buffer
1830 # The above could happen because child_attrs is wrong somewhere so that
1831 # options are not propagated.
1832 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1833 index_signeds=[i.type.signed for i in self.indices],
1834 index_cnames=index_temps,
1835 options=code.globalstate.directives,
1836 pos=self.pos, code=code)
1838 def put_nonecheck(self, code):
1839 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
1840 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
1841 code.putln("__Pyx_RaiseNoneIndexingError();")
1842 code.putln(code.error_goto(self.pos))
1843 code.putln("}")
1845 class SliceIndexNode(ExprNode):
1846 # 2-element slice indexing
1847 #
1848 # base ExprNode
1849 # start ExprNode or None
1850 # stop ExprNode or None
1852 subexprs = ['base', 'start', 'stop']
1854 def calculate_constant_result(self):
1855 self.constant_result = self.base.constant_result[
1856 self.start.constant_result : self.stop.constant_result]
1858 def compile_time_value(self, denv):
1859 base = self.base.compile_time_value(denv)
1860 if self.start is None:
1861 start = 0
1862 else:
1863 start = self.start.compile_time_value(denv)
1864 if self.stop is None:
1865 stop = None
1866 else:
1867 stop = self.stop.compile_time_value(denv)
1868 try:
1869 return base[start:stop]
1870 except Exception, e:
1871 self.compile_time_value_error(e)
1873 def analyse_target_declaration(self, env):
1874 pass
1876 def analyse_types(self, env):
1877 self.base.analyse_types(env)
1878 if self.start:
1879 self.start.analyse_types(env)
1880 if self.stop:
1881 self.stop.analyse_types(env)
1882 if self.base.type.is_string:
1883 self.type = py_object_type
1884 elif self.base.type.is_array or self.base.type.is_ptr:
1885 # we need a ptr type here instead of an array type, as
1886 # array types can result in invalid type casts in the C
1887 # code
1888 self.type = PyrexTypes.CPtrType(self.base.type.base_type)
1889 else:
1890 self.base = self.base.coerce_to_pyobject(env)
1891 self.type = py_object_type
1892 c_int = PyrexTypes.c_py_ssize_t_type
1893 if self.start:
1894 self.start = self.start.coerce_to(c_int, env)
1895 if self.stop:
1896 self.stop = self.stop.coerce_to(c_int, env)
1897 self.is_temp = 1
1899 gil_check = ExprNode._gil_check
1900 gil_message = "Slicing Python object"
1902 def generate_result_code(self, code):
1903 if not self.type.is_pyobject:
1904 error(self.pos,
1905 "Slicing is not currently supported for '%s'." % self.type)
1906 return
1907 if self.base.type.is_string:
1908 if self.stop is None:
1909 code.putln(
1910 "%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
1911 self.result(),
1912 self.base.result(),
1913 self.start_code(),
1914 code.error_goto_if_null(self.result(), self.pos)))
1915 else:
1916 code.putln(
1917 "%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
1918 self.result(),
1919 self.base.result(),
1920 self.start_code(),
1921 self.stop_code(),
1922 self.start_code(),
1923 code.error_goto_if_null(self.result(), self.pos)))
1924 else:
1925 code.putln(
1926 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1927 self.result(),
1928 self.base.py_result(),
1929 self.start_code(),
1930 self.stop_code(),
1931 code.error_goto_if_null(self.result(), self.pos)))
1932 code.put_gotref(self.py_result())
1934 def generate_assignment_code(self, rhs, code):
1935 self.generate_subexpr_evaluation_code(code)
1936 if self.type.is_pyobject:
1937 code.put_error_if_neg(self.pos,
1938 "PySequence_SetSlice(%s, %s, %s, %s)" % (
1939 self.base.py_result(),
1940 self.start_code(),
1941 self.stop_code(),
1942 rhs.result()))
1943 else:
1944 start_offset = ''
1945 if self.start:
1946 start_offset = self.start_code()
1947 if start_offset == '0':
1948 start_offset = ''
1949 else:
1950 start_offset += '+'
1951 if rhs.type.is_array:
1952 array_length = rhs.type.size
1953 self.generate_slice_guard_code(code, array_length)
1954 else:
1955 error(self.pos,
1956 "Slice assignments from pointers are not yet supported.")
1957 # FIXME: fix the array size according to start/stop
1958 array_length = self.base.type.size
1959 for i in range(array_length):
1960 code.putln("%s[%s%s] = %s[%d];" % (
1961 self.base.result(), start_offset, i,
1962 rhs.result(), i))
1963 self.generate_subexpr_disposal_code(code)
1964 self.free_subexpr_temps(code)
1965 rhs.generate_disposal_code(code)
1966 rhs.free_temps(code)
1968 def generate_deletion_code(self, code):
1969 if not self.base.type.is_pyobject:
1970 error(self.pos,
1971 "Deleting slices is only supported for Python types, not '%s'." % self.type)
1972 return
1973 self.generate_subexpr_evaluation_code(code)
1974 code.put_error_if_neg(self.pos,
1975 "PySequence_DelSlice(%s, %s, %s)" % (
1976 self.base.py_result(),
1977 self.start_code(),
1978 self.stop_code()))
1979 self.generate_subexpr_disposal_code(code)
1981 def generate_slice_guard_code(self, code, target_size):
1982 if not self.base.type.is_array:
1983 return
1984 slice_size = self.base.type.size
1985 start = stop = None
1986 if self.stop:
1987 stop = self.stop.result()
1988 try:
1989 stop = int(stop)
1990 if stop < 0:
1991 slice_size = self.base.type.size + stop
1992 else:
1993 slice_size = stop
1994 stop = None
1995 except ValueError:
1996 pass
1997 if self.start:
1998 start = self.start.result()
1999 try:
2000 start = int(start)
2001 if start < 0:
2002 start = self.base.type.size + start
2003 slice_size -= start
2004 start = None
2005 except ValueError:
2006 pass
2007 check = None
2008 if slice_size < 0:
2009 if target_size > 0:
2010 error(self.pos, "Assignment to empty slice.")
2011 elif start is None and stop is None:
2012 # we know the exact slice length
2013 if target_size != slice_size:
2014 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2015 slice_size, target_size))
2016 elif start is not None:
2017 if stop is None:
2018 stop = slice_size
2019 check = "(%s)-(%s)" % (stop, start)
2020 else: # stop is not None:
2021 check = stop
2022 if check:
2023 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2024 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%d, got %%d", %d, (%s));' % (
2025 target_size, check))
2026 code.putln(code.error_goto(self.pos))
2027 code.putln("}")
2029 def start_code(self):
2030 if self.start:
2031 return self.start.result()
2032 else:
2033 return "0"
2035 def stop_code(self):
2036 if self.stop:
2037 return self.stop.result()
2038 elif self.base.type.is_array:
2039 return self.base.type.size
2040 else:
2041 return "PY_SSIZE_T_MAX"
2043 def calculate_result_code(self):
2044 # self.result() is not used, but this method must exist
2045 return "<unused>"
2048 class SliceNode(ExprNode):
2049 # start:stop:step in subscript list
2050 #
2051 # start ExprNode
2052 # stop ExprNode
2053 # step ExprNode
2055 def calculate_constant_result(self):
2056 self.constant_result = self.base.constant_result[
2057 self.start.constant_result : \
2058 self.stop.constant_result : \
2059 self.step.constant_result]
2061 def compile_time_value(self, denv):
2062 start = self.start.compile_time_value(denv)
2063 if self.stop is None:
2064 stop = None
2065 else:
2066 stop = self.stop.compile_time_value(denv)
2067 if self.step is None:
2068 step = None
2069 else:
2070 step = self.step.compile_time_value(denv)
2071 try:
2072 return slice(start, stop, step)
2073 except Exception, e:
2074 self.compile_time_value_error(e)
2076 subexprs = ['start', 'stop', 'step']
2078 def analyse_types(self, env):
2079 self.start.analyse_types(env)
2080 self.stop.analyse_types(env)
2081 self.step.analyse_types(env)
2082 self.start = self.start.coerce_to_pyobject(env)
2083 self.stop = self.stop.coerce_to_pyobject(env)
2084 self.step = self.step.coerce_to_pyobject(env)
2085 self.type = py_object_type
2086 self.is_temp = 1
2088 gil_message = "Constructing Python slice object"
2090 def generate_result_code(self, code):
2091 code.putln(
2092 "%s = PySlice_New(%s, %s, %s); %s" % (
2093 self.result(),
2094 self.start.py_result(),
2095 self.stop.py_result(),
2096 self.step.py_result(),
2097 code.error_goto_if_null(self.result(), self.pos)))
2098 code.put_gotref(self.py_result())
2101 class CallNode(ExprNode):
2102 def analyse_as_type_constructor(self, env):
2103 type = self.function.analyse_as_type(env)
2104 if type and type.is_struct_or_union:
2105 args, kwds = self.explicit_args_kwds()
2106 items = []
2107 for arg, member in zip(args, type.scope.var_entries):
2108 items.append(DictItemNode(pos=arg.pos, key=IdentifierStringNode(pos=arg.pos, value=member.name), value=arg))
2109 if kwds:
2110 items += kwds.key_value_pairs
2111 self.key_value_pairs = items
2112 self.__class__ = DictNode
2113 self.analyse_types(env)
2114 self.coerce_to(type, env)
2115 return True
2117 def gil_check(self, env):
2118 func_type = self.function_type()
2119 if func_type.is_pyobject:
2120 self._gil_check(env)
2121 elif not getattr(func_type, 'nogil', False):
2122 self._gil_check(env)
2124 gil_message = "Calling gil-requiring function"
2127 class SimpleCallNode(CallNode):
2128 # Function call without keyword, * or ** args.
2129 #
2130 # function ExprNode
2131 # args [ExprNode]
2132 # arg_tuple ExprNode or None used internally
2133 # self ExprNode or None used internally
2134 # coerced_self ExprNode or None used internally
2135 # wrapper_call bool used internally
2136 # has_optional_args bool used internally
2138 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2140 self = None
2141 coerced_self = None
2142 arg_tuple = None
2143 wrapper_call = False
2144 has_optional_args = False
2146 def compile_time_value(self, denv):
2147 function = self.function.compile_time_value(denv)
2148 args = [arg.compile_time_value(denv) for arg in self.args]
2149 try:
2150 return function(*args)
2151 except Exception, e:
2152 self.compile_time_value_error(e)
2154 def analyse_as_type(self, env):
2155 attr = self.function.as_cython_attribute()
2156 if attr == 'pointer':
2157 if len(self.args) != 1:
2158 error(self.args.pos, "only one type allowed.")
2159 else:
2160 type = self.args[0].analyse_as_type(env)
2161 if not type:
2162 error(self.args[0].pos, "Unknown type")
2163 else:
2164 return PyrexTypes.CPtrType(type)
2166 def explicit_args_kwds(self):
2167 return self.args, None
2169 def analyse_types(self, env):
2170 if self.analyse_as_type_constructor(env):
2171 return
2172 function = self.function
2173 function.is_called = 1
2174 self.function.analyse_types(env)
2175 if function.is_attribute and function.entry and function.entry.is_cmethod:
2176 # Take ownership of the object from which the attribute
2177 # was obtained, because we need to pass it as 'self'.
2178 self.self = function.obj
2179 function.obj = CloneNode(self.self)
2180 func_type = self.function_type()
2181 if func_type.is_pyobject:
2182 self.arg_tuple = TupleNode(self.pos, args = self.args)
2183 self.arg_tuple.analyse_types(env)
2184 self.args = None
2185 if function.is_name and function.type_entry:
2186 # We are calling an extension type constructor. As
2187 # long as we do not support __new__(), the result type
2188 # is clear
2189 self.type = function.type_entry.type
2190 self.result_ctype = py_object_type
2191 else:
2192 self.type = py_object_type
2193 self.is_temp = 1
2194 else:
2195 for arg in self.args:
2196 arg.analyse_types(env)
2197 if self.self and func_type.args:
2198 # Coerce 'self' to the type expected by the method.
2199 expected_type = func_type.args[0].type
2200 self.coerced_self = CloneNode(self.self).coerce_to(
2201 expected_type, env)
2202 # Insert coerced 'self' argument into argument list.
2203 self.args.insert(0, self.coerced_self)
2204 self.analyse_c_function_call(env)
2206 def function_type(self):
2207 # Return the type of the function being called, coercing a function
2208 # pointer to a function if necessary.
2209 func_type = self.function.type
2210 if func_type.is_ptr:
2211 func_type = func_type.base_type
2212 return func_type
2214 def analyse_c_function_call(self, env):
2215 func_type = self.function_type()
2216 # Check function type
2217 if not func_type.is_cfunction:
2218 if not func_type.is_error:
2219 error(self.pos, "Calling non-function type '%s'" %
2220 func_type)
2221 self.type = PyrexTypes.error_type
2222 self.result_code = "<error>"
2223 return
2224 # Check no. of args
2225 max_nargs = len(func_type.args)
2226 expected_nargs = max_nargs - func_type.optional_arg_count
2227 actual_nargs = len(self.args)
2228 if actual_nargs < expected_nargs \
2229 or (not func_type.has_varargs and actual_nargs > max_nargs):
2230 expected_str = str(expected_nargs)
2231 if func_type.has_varargs:
2232 expected_str = "at least " + expected_str
2233 elif func_type.optional_arg_count:
2234 if actual_nargs < max_nargs:
2235 expected_str = "at least " + expected_str
2236 else:
2237 expected_str = "at most " + str(max_nargs)
2238 error(self.pos,
2239 "Call with wrong number of arguments (expected %s, got %s)"
2240 % (expected_str, actual_nargs))
2241 self.args = None
2242 self.type = PyrexTypes.error_type
2243 self.result_code = "<error>"
2244 return
2245 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2246 self.has_optional_args = 1
2247 self.is_temp = 1
2248 # Coerce arguments
2249 for i in range(min(max_nargs, actual_nargs)):
2250 formal_type = func_type.args[i].type
2251 self.args[i] = self.args[i].coerce_to(formal_type, env)
2252 for i in range(max_nargs, actual_nargs):
2253 if self.args[i].type.is_pyobject:
2254 error(self.args[i].pos,
2255 "Python object cannot be passed as a varargs parameter")
2256 # Calc result type and code fragment
2257 self.type = func_type.return_type
2258 if self.type.is_pyobject:
2259 self.result_ctype = py_object_type
2260 self.is_temp = 1
2261 elif func_type.exception_value is not None \
2262 or func_type.exception_check:
2263 self.is_temp = 1
2264 # C++ exception handler
2265 if func_type.exception_check == '+':
2266 if func_type.exception_value is None:
2267 env.use_utility_code(cpp_exception_utility_code)
2269 def calculate_result_code(self):
2270 return self.c_call_code()
2272 def c_call_code(self):
2273 func_type = self.function_type()
2274 if self.args is None or not func_type.is_cfunction:
2275 return "<error>"
2276 formal_args = func_type.args
2277 arg_list_code = []
2278 args = zip(formal_args, self.args)
2279 max_nargs = len(func_type.args)
2280 expected_nargs = max_nargs - func_type.optional_arg_count
2281 actual_nargs = len(self.args)
2282 for formal_arg, actual_arg in args[:expected_nargs]:
2283 arg_code = actual_arg.result_as(formal_arg.type)
2284 arg_list_code.append(arg_code)
2286 if func_type.is_overridable:
2287 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2289 if func_type.optional_arg_count:
2290 if expected_nargs == actual_nargs:
2291 optional_args = 'NULL'
2292 else:
2293 optional_args = "&%s" % self.opt_arg_struct
2294 arg_list_code.append(optional_args)
2296 for actual_arg in self.args[len(formal_args):]:
2297 arg_list_code.append(actual_arg.result())
2298 result = "%s(%s)" % (self.function.result(),
2299 ', '.join(arg_list_code))
2300 # if self.wrapper_call or \
2301 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
2302 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
2303 return result
2305 def generate_result_code(self, code):
2306 func_type = self.function_type()
2307 if func_type.is_pyobject:
2308 arg_code = self.arg_tuple.py_result()
2309 code.putln(
2310 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2311 self.result(),
2312 self.function.py_result(),
2313 arg_code,
2314 code.error_goto_if_null(self.result(), self.pos)))
2315 code.put_gotref(self.py_result())
2316 elif func_type.is_cfunction:
2317 if self.has_optional_args:
2318 actual_nargs = len(self.args)
2319 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2320 self.opt_arg_struct = code.funcstate.allocate_temp(
2321 func_type.op_arg_struct.base_type, manage_ref=True)
2322 code.putln("%s.%s = %s;" % (
2323 self.opt_arg_struct,
2324 Naming.pyrex_prefix + "n",
2325 len(self.args) - expected_nargs))
2326 args = zip(func_type.args, self.args)
2327 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2328 code.putln("%s.%s = %s;" % (
2329 self.opt_arg_struct,
2330 formal_arg.name,
2331 actual_arg.result_as(formal_arg.type)))
2332 exc_checks = []
2333 if self.type.is_pyobject:
2334 exc_checks.append("!%s" % self.result())
2335 else:
2336 exc_val = func_type.exception_value
2337 exc_check = func_type.exception_check
2338 if exc_val is not None:
2339 exc_checks.append("%s == %s" % (self.result(), exc_val))
2340 if exc_check:
2341 exc_checks.append("PyErr_Occurred()")
2342 if self.is_temp or exc_checks:
2343 rhs = self.c_call_code()
2344 if self.result():
2345 lhs = "%s = " % self.result()
2346 if self.is_temp and self.type.is_pyobject:
2347 #return_type = self.type # func_type.return_type
2348 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2349 # "from", return_type, "to pyobject" ###
2350 rhs = typecast(py_object_type, self.type, rhs)
2351 else:
2352 lhs = ""
2353 if func_type.exception_check == '+':
2354 if func_type.exception_value is None:
2355 raise_py_exception = "__Pyx_CppExn2PyErr()"
2356 elif func_type.exception_value.type.is_pyobject:
2357 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2358 else:
2359 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2360 code.putln(
2361 "try {%s%s;} catch(...) {%s; %s}" % (
2362 lhs,
2363 rhs,
2364 raise_py_exception,
2365 code.error_goto(self.pos)))
2366 else:
2367 if exc_checks:
2368 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2369 else:
2370 goto_error = ""
2371 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2372 if self.type.is_pyobject and self.result():
2373 code.put_gotref(self.py_result())
2374 if self.has_optional_args:
2375 code.funcstate.release_temp(self.opt_arg_struct)
2378 class PythonCapiFunctionNode(ExprNode):
2379 subexprs = []
2380 def __init__(self, pos, name, func_type, utility_code = None):
2381 self.pos = pos
2382 self.name = name
2383 self.type = func_type
2384 self.utility_code = utility_code
2386 def generate_result_code(self, code):
2387 if self.utility_code:
2388 code.globalstate.use_utility_code(self.utility_code)
2390 def calculate_result_code(self):
2391 return self.name
2393 class PythonCapiCallNode(SimpleCallNode):
2394 # Python C-API Function call (only created in transforms)
2396 def __init__(self, pos, function_name, func_type,
2397 utility_code = None, **kwargs):
2398 self.type = func_type.return_type
2399 self.result_ctype = self.type
2400 self.function = PythonCapiFunctionNode(
2401 pos, function_name, func_type,
2402 utility_code = utility_code)
2403 # call this last so that we can override the constructed
2404 # attributes above with explicit keyword arguments if required
2405 SimpleCallNode.__init__(self, pos, **kwargs)
2408 class GeneralCallNode(CallNode):
2409 # General Python function call, including keyword,
2410 # * and ** arguments.
2411 #
2412 # function ExprNode
2413 # positional_args ExprNode Tuple of positional arguments
2414 # keyword_args ExprNode or None Dict of keyword arguments
2415 # starstar_arg ExprNode or None Dict of extra keyword args
2417 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2419 gil_check = CallNode._gil_check
2421 def compile_time_value(self, denv):
2422 function = self.function.compile_time_value(denv)
2423 positional_args = self.positional_args.compile_time_value(denv)
2424 keyword_args = self.keyword_args.compile_time_value(denv)
2425 starstar_arg = self.starstar_arg.compile_time_value(denv)
2426 try:
2427 keyword_args.update(starstar_arg)
2428 return function(*positional_args, **keyword_args)
2429 except Exception, e:
2430 self.compile_time_value_error(e)
2432 def explicit_args_kwds(self):
2433 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2434 raise PostParseError(self.pos,
2435 'Compile-time keyword arguments must be explicit.')
2436 return self.positional_args.args, self.keyword_args
2438 def analyse_types(self, env):
2439 if self.analyse_as_type_constructor(env):
2440 return
2441 self.function.analyse_types(env)
2442 self.positional_args.analyse_types(env)
2443 if self.keyword_args:
2444 self.keyword_args.analyse_types(env)
2445 if self.starstar_arg:
2446 self.starstar_arg.analyse_types(env)
2447 if not self.function.type.is_pyobject:
2448 if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
2449 error(self.pos, "Keyword arguments not allowed in cdef functions.")
2450 else:
2451 self.function = self.function.coerce_to_pyobject(env)
2452 self.positional_args = \
2453 self.positional_args.coerce_to_pyobject(env)
2454 if self.starstar_arg:
2455 self.starstar_arg = \
2456 self.starstar_arg.coerce_to_pyobject(env)
2457 function = self.function
2458 if function.is_name and function.type_entry:
2459 # We are calling an extension type constructor. As long
2460 # as we do not support __new__(), the result type is clear
2461 self.type = function.type_entry.type
2462 self.result_ctype = py_object_type
2463 else:
2464 self.type = py_object_type
2465 self.is_temp = 1
2467 def generate_result_code(self, code):
2468 if self.keyword_args and self.starstar_arg:
2469 code.put_error_if_neg(self.pos,
2470 "PyDict_Update(%s, %s)" % (
2471 self.keyword_args.py_result(),
2472 self.starstar_arg.py_result()))
2473 keyword_code = self.keyword_args.py_result()
2474 elif self.keyword_args:
2475 keyword_code = self.keyword_args.py_result()
2476 elif self.starstar_arg:
2477 keyword_code = self.starstar_arg.py_result()
2478 else:
2479 keyword_code = None
2480 if not keyword_code:
2481 call_code = "PyObject_Call(%s, %s, NULL)" % (
2482 self.function.py_result(),
2483 self.positional_args.py_result())
2484 else:
2485 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2486 self.function.py_result(),
2487 self.positional_args.py_result(),
2488 keyword_code)
2489 code.putln(
2490 "%s = %s; %s" % (
2491 self.result(),
2492 call_code,
2493 code.error_goto_if_null(self.result(), self.pos)))
2494 code.put_gotref(self.py_result())
2497 class AsTupleNode(ExprNode):
2498 # Convert argument to tuple. Used for normalising
2499 # the * argument of a function call.
2500 #
2501 # arg ExprNode
2503 subexprs = ['arg']
2505 def calculate_constant_result(self):
2506 self.constant_result = tuple(self.base.constant_result)
2508 def compile_time_value(self, denv):
2509 arg = self.arg.compile_time_value(denv)
2510 try:
2511 return tuple(arg)
2512 except Exception, e:
2513 self.compile_time_value_error(e)
2515 def analyse_types(self, env):
2516 self.arg.analyse_types(env)
2517 self.arg = self.arg.coerce_to_pyobject(env)
2518 self.type = tuple_type
2519 self.is_temp = 1
2521 gil_check = ExprNode._gil_check
2522 gil_message = "Constructing Python tuple"
2524 def generate_result_code(self, code):
2525 code.putln(
2526 "%s = PySequence_Tuple(%s); %s" % (
2527 self.result(),
2528 self.arg.py_result(),
2529 code.error_goto_if_null(self.result(), self.pos)))
2530 code.put_gotref(self.py_result())
2533 class AttributeNode(ExprNode):
2534 # obj.attribute
2535 #
2536 # obj ExprNode
2537 # attribute string
2538 # needs_none_check boolean Used if obj is an extension type.
2539 # If set to True, it is known that the type is not None.
2540 #
2541 # Used internally:
2542 #
2543 # is_py_attr boolean Is a Python getattr operation
2544 # member string C name of struct member
2545 # is_called boolean Function call is being done on result
2546 # entry Entry Symbol table entry of attribute
2548 is_attribute = 1
2549 subexprs = ['obj']
2551 type = PyrexTypes.error_type
2552 entry = None
2553 is_called = 0
2554 needs_none_check = True
2556 def as_cython_attribute(self):
2557 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2558 return self.attribute
2560 def coerce_to(self, dst_type, env):
2561 # If coercing to a generic pyobject and this is a cpdef function
2562 # we can create the corresponding attribute
2563 if dst_type is py_object_type:
2564 entry = self.entry
2565 if entry and entry.is_cfunction and entry.as_variable:
2566 # must be a cpdef function
2567 self.is_temp = 1
2568 self.entry = entry.as_variable
2569 self.analyse_as_python_attribute(env)
2570 return self
2571 return ExprNode.coerce_to(self, dst_type, env)
2573 def calculate_constant_result(self):
2574 attr = self.attribute
2575 if attr.startswith("__") and attr.endswith("__"):
2576 return
2577 self.constant_result = getattr(self.obj.constant_result, attr)
2579 def compile_time_value(self, denv):
2580 attr = self.attribute
2581 if attr.startswith("__") and attr.endswith("__"):
2582 error(self.pos,
2583 "Invalid attribute name '%s' in compile-time expression" % attr)
2584 return None
2585 obj = self.obj.compile_time_value(denv)
2586 try:
2587 return getattr(obj, attr)
2588 except Exception, e:
2589 self.compile_time_value_error(e)
2591 def analyse_target_declaration(self, env):
2592 pass
2594 def analyse_target_types(self, env):
2595 self.analyse_types(env, target = 1)
2597 def analyse_types(self, env, target = 0):
2598 if self.analyse_as_cimported_attribute(env, target):
2599 return
2600 if not target and self.analyse_as_unbound_cmethod(env):
2601 return
2602 self.analyse_as_ordinary_attribute(env, target)
2604 def analyse_as_cimported_attribute(self, env, target):
2605 # Try to interpret this as a reference to an imported
2606 # C const, type, var or function. If successful, mutates
2607 # this node into a NameNode and returns 1, otherwise
2608 # returns 0.
2609 module_scope = self.obj.analyse_as_module(env)
2610 if module_scope:
2611 entry = module_scope.lookup_here(self.attribute)
2612 if entry and (
2613 entry.is_cglobal or entry.is_cfunction
2614 or entry.is_type or entry.is_const):
2615 self.mutate_into_name_node(env, entry, target)
2616 return 1
2617 return 0
2619 def analyse_as_unbound_cmethod(self, env):
2620 # Try to interpret this as a reference to an unbound
2621 # C method of an extension type. If successful, mutates
2622 # this node into a NameNode and returns 1, otherwise
2623 # returns 0.
2624 type = self.obj.analyse_as_extension_type(env)
2625 if type:
2626 entry = type.scope.lookup_here(self.attribute)
2627 if entry and entry.is_cmethod:
2628 # Create a temporary entry describing the C method
2629 # as an ordinary function.
2630 ubcm_entry = Symtab.Entry(entry.name,
2631 "%s->%s" % (type.vtabptr_cname, entry.cname),
2632 entry.type)
2633 ubcm_entry.is_cfunction = 1
2634 ubcm_entry.func_cname = entry.func_cname
2635 ubcm_entry.is_unbound_cmethod = 1
2636 self.mutate_into_name_node(env, ubcm_entry, None)
2637 return 1
2638 return 0
2640 def analyse_as_type(self, env):
2641 module_scope = self.obj.analyse_as_module(env)
2642 if module_scope:
2643 return module_scope.lookup_type(self.attribute)
2644 return None
2646 def analyse_as_extension_type(self, env):
2647 # Try to interpret this as a reference to an extension type
2648 # in a cimported module. Returns the extension type, or None.
2649 module_scope = self.obj.analyse_as_module(env)
2650 if module_scope:
2651 entry = module_scope.lookup_here(self.attribute)
2652 if entry and entry.is_type and entry.type.is_extension_type:
2653 return entry.type
2654 return None
2656 def analyse_as_module(self, env):
2657 # Try to interpret this as a reference to a cimported module
2658 # in another cimported module. Returns the module scope, or None.
2659 module_scope = self.obj.analyse_as_module(env)
2660 if module_scope:
2661 entry = module_scope.lookup_here(self.attribute)
2662 if entry and entry.as_module:
2663 return entry.as_module
2664 return None
2666 def mutate_into_name_node(self, env, entry, target):
2667 # Mutate this node into a NameNode and complete the
2668 # analyse_types phase.
2669 self.__class__ = NameNode
2670 self.name = self.attribute
2671 self.entry = entry
2672 del self.obj
2673 del self.attribute
2674 if target:
2675 NameNode.analyse_target_types(self, env)
2676 else:
2677 NameNode.analyse_rvalue_entry(self, env)
2679 def analyse_as_ordinary_attribute(self, env, target):
2680 self.obj.analyse_types(env)
2681 self.analyse_attribute(env)
2682 if self.entry and self.entry.is_cmethod and not self.is_called:
2683 # error(self.pos, "C method can only be called")
2684 pass
2685 ## Reference to C array turns into pointer to first element.
2686 #while self.type.is_array:
2687 # self.type = self.type.element_ptr_type()
2688 if self.is_py_attr:
2689 if not target:
2690 self.is_temp = 1
2691 self.result_ctype = py_object_type
2693 def analyse_attribute(self, env):
2694 # Look up attribute and set self.type and self.member.
2695 self.is_py_attr = 0
2696 self.member = self.attribute
2697 if self.obj.type.is_string:
2698 self.obj = self.obj.coerce_to_pyobject(env)
2699 obj_type = self.obj.type
2700 if obj_type.is_ptr or obj_type.is_array:
2701 obj_type = obj_type.base_type
2702 self.op = "->"
2703 elif obj_type.is_extension_type:
2704 self.op = "->"
2705 else:
2706 self.op = "."
2707 if obj_type.has_attributes:
2708 entry = None
2709 if obj_type.attributes_known():
2710 entry = obj_type.scope.lookup_here(self.attribute)
2711 if entry and entry.is_member:
2712 entry = None
2713 else:
2714 error(self.pos,
2715 "Cannot select attribute of incomplete type '%s'"
2716 % obj_type)
2717 self.type = PyrexTypes.error_type
2718 return
2719 self.entry = entry
2720 if entry:
2721 if obj_type.is_extension_type and entry.name == "__weakref__":
2722 error(self.pos, "Illegal use of special attribute __weakref__")
2723 # methods need the normal attribute lookup
2724 # because they do not have struct entries
2725 if entry.is_variable or entry.is_cmethod:
2726 self.type = entry.type
2727 self.member = entry.cname
2728 return
2729 else:
2730 # If it's not a variable or C method, it must be a Python
2731 # method of an extension type, so we treat it like a Python
2732 # attribute.
2733 pass
2734 # If we get here, the base object is not a struct/union/extension
2735 # type, or it is an extension type and the attribute is either not
2736 # declared or is declared as a Python method. Treat it as a Python
2737 # attribute reference.
2738 self.analyse_as_python_attribute(env)
2740 def analyse_as_python_attribute(self, env):
2741 obj_type = self.obj.type
2742 self.member = self.attribute
2743 if obj_type.is_pyobject:
2744 self.type = py_object_type
2745 self.is_py_attr = 1
2746 else:
2747 if not obj_type.is_error:
2748 error(self.pos,
2749 "Object of type '%s' has no attribute '%s'" %
2750 (obj_type, self.attribute))
2752 def gil_check(self, env):
2753 if self.is_py_attr:
2754 self._gil_check(env)
2756 gil_message = "Accessing Python attribute"
2758 def is_simple(self):
2759 if self.obj:
2760 return self.result_in_temp() or self.obj.is_simple()
2761 else:
2762 return NameNode.is_simple(self)
2764 def is_lvalue(self):
2765 if self.obj:
2766 return 1
2767 else:
2768 return NameNode.is_lvalue(self)
2770 def is_ephemeral(self):
2771 if self.obj:
2772 return self.obj.is_ephemeral()
2773 else:
2774 return NameNode.is_ephemeral(self)
2776 def calculate_result_code(self):
2777 #print "AttributeNode.calculate_result_code:", self.member ###
2778 #print "...obj node =", self.obj, "code", self.obj.result() ###
2779 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2780 obj = self.obj
2781 obj_code = obj.result_as(obj.type)
2782 #print "...obj_code =", obj_code ###
2783 if self.entry and self.entry.is_cmethod:
2784 if obj.type.is_extension_type:
2785 return "((struct %s *)%s%s%s)->%s" % (
2786 obj.type.vtabstruct_cname, obj_code, self.op,
2787 obj.type.vtabslot_cname, self.member)
2788 else:
2789 return self.member
2790 else:
2791 return "%s%s%s" % (obj_code, self.op, self.member)
2793 def generate_result_code(self, code):
2794 interned_attr_cname = code.intern_identifier(self.attribute)
2795 if self.is_py_attr:
2796 code.putln(
2797 '%s = PyObject_GetAttr(%s, %s); %s' % (
2798 self.result(),
2799 self.obj.py_result(),
2800 interned_attr_cname,
2801 code.error_goto_if_null(self.result(), self.pos)))
2802 code.put_gotref(self.py_result())
2803 else:
2804 # result_code contains what is needed, but we may need to insert
2805 # a check and raise an exception
2806 if (self.obj.type.is_extension_type
2807 and self.needs_none_check
2808 and code.globalstate.directives['nonecheck']):
2809 self.put_nonecheck(code)
2811 def generate_assignment_code(self, rhs, code):
2812 interned_attr_cname = code.intern_identifier(self.attribute)
2813 self.obj.generate_evaluation_code(code)
2814 if self.is_py_attr:
2815 code.put_error_if_neg(self.pos,
2816 'PyObject_SetAttr(%s, %s, %s)' % (
2817 self.obj.py_result(),
2818 interned_attr_cname,
2819 rhs.py_result()))
2820 rhs.generate_disposal_code(code)
2821 rhs.free_temps(code)
2822 else:
2823 if (self.obj.type.is_extension_type
2824 and self.needs_none_check
2825 and code.globalstate.directives['nonecheck']):
2826 self.put_nonecheck(code)
2828 select_code = self.result()
2829 if self.type.is_pyobject:
2830 rhs.make_owned_reference(code)
2831 code.put_giveref(rhs.py_result())
2832 code.put_gotref(select_code)
2833 code.put_decref(select_code, self.ctype())
2834 code.putln(
2835 "%s = %s;" % (
2836 select_code,
2837 rhs.result_as(self.ctype())))
2838 #rhs.result()))
2839 rhs.generate_post_assignment_code(code)
2840 rhs.free_temps(code)
2841 self.obj.generate_disposal_code(code)
2842 self.obj.free_temps(code)
2844 def generate_deletion_code(self, code):
2845 interned_attr_cname = code.intern_identifier(self.attribute)
2846 self.obj.generate_evaluation_code(code)
2847 if self.is_py_attr:
2848 code.put_error_if_neg(self.pos,
2849 'PyObject_DelAttr(%s, %s)' % (
2850 self.obj.py_result(),
2851 interned_attr_cname))
2852 else:
2853 error(self.pos, "Cannot delete C attribute of extension type")
2854 self.obj.generate_disposal_code(code)
2855 self.obj.free_temps(code)
2857 def annotate(self, code):
2858 if self.is_py_attr:
2859 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2860 else:
2861 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2863 def put_nonecheck(self, code):
2864 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
2865 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
2866 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
2867 code.putln(code.error_goto(self.pos))
2868 code.putln("}")
2871 #-------------------------------------------------------------------
2872 #
2873 # Constructor nodes
2874 #
2875 #-------------------------------------------------------------------
2877 class StarredTargetNode(ExprNode):
2878 # A starred expression like "*a"
2879 #
2880 # This is only allowed in sequence assignment targets such as
2881 #
2882 # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4]
2883 #
2884 # and will be removed during type analysis (or generate an error
2885 # if it's found at unexpected places).
2886 #
2887 # target ExprNode
2889 subexprs = ['target']
2890 is_starred = 1
2891 type = py_object_type
2893 def __init__(self, pos, target):
2894 self.pos = pos
2895 self.target = target
2897 def analyse_declarations(self, env):
2898 error(self.pos, "can use starred expression only as assignment target")
2899 self.target.analyse_declarations(env)
2901 def analyse_types(self, env):
2902 error(self.pos, "can use starred expression only as assignment target")
2903 self.target.analyse_types(env)
2904 self.type = self.target.type
2906 def analyse_target_declaration(self, env):
2907 self.target.analyse_target_declaration(env)
2909 def analyse_target_types(self, env):
2910 self.target.analyse_target_types(env)
2911 self.type = self.target.type
2913 def calculate_result_code(self):
2914 return ""
2916 def generate_result_code(self, code):
2917 pass
2920 class SequenceNode(ExprNode):
2921 # Base class for list and tuple constructor nodes.
2922 # Contains common code for performing sequence unpacking.
2923 #
2924 # args [ExprNode]
2925 # iterator ExprNode
2926 # unpacked_items [ExprNode] or None
2927 # coerced_unpacked_items [ExprNode] or None
2929 subexprs = ['args']
2931 is_sequence_constructor = 1
2932 unpacked_items = None
2934 def compile_time_value_list(self, denv):
2935 return [arg.compile_time_value(denv) for arg in self.args]
2937 def replace_starred_target_node(self):
2938 # replace a starred node in the targets by the contained expression
2939 self.starred_assignment = False
2940 args = []
2941 for arg in self.args:
2942 if arg.is_starred:
2943 if self.starred_assignment:
2944 error(arg.pos, "more than 1 starred expression in assignment")
2945 self.starred_assignment = True
2946 arg = arg.target
2947 arg.is_starred = True
2948 args.append(arg)
2949 self.args = args
2951 def analyse_target_declaration(self, env):
2952 self.replace_starred_target_node()
2953 for arg in self.args:
2954 arg.analyse_target_declaration(env)
2956 def analyse_types(self, env, skip_children=False):
2957 for i in range(len(self.args)):
2958 arg = self.args[i]
2959 if not skip_children: arg.analyse_types(env)
2960 self.args[i] = arg.coerce_to_pyobject(env)
2961 self.type = py_object_type
2962 self.is_temp = 1
2964 def analyse_target_types(self, env):
2965 self.iterator = PyTempNode(self.pos, env)
2966 self.unpacked_items = []
2967 self.coerced_unpacked_items = []
2968 for arg in self.args:
2969 arg.analyse_target_types(env)
2970 if arg.is_starred:
2971 if not arg.type.assignable_from(Builtin.list_type):
2972 error(arg.pos,
2973 "starred target must have Python object (list) type")
2974 if arg.type is py_object_type:
2975 arg.type = Builtin.list_type
2976 unpacked_item = PyTempNode(self.pos, env)
2977 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2978 self.unpacked_items.append(unpacked_item)
2979 self.coerced_unpacked_items.append(coerced_unpacked_item)
2980 self.type = py_object_type
2981 env.use_utility_code(unpacking_utility_code)
2983 def generate_result_code(self, code):
2984 self.generate_operation_code(code)
2986 def generate_assignment_code(self, rhs, code):
2987 if self.starred_assignment:
2988 self.generate_starred_assignment_code(rhs, code)
2989 else:
2990 self.generate_parallel_assignment_code(rhs, code)
2992 for item in self.unpacked_items:
2993 item.release(code)
2994 rhs.free_temps(code)
2996 def generate_parallel_assignment_code(self, rhs, code):
2997 # Need to work around the fact that generate_evaluation_code
2998 # allocates the temps in a rather hacky way -- the assignment
2999 # is evaluated twice, within each if-block.
3001 if rhs.type is tuple_type:
3002 tuple_check = "likely(%s != Py_None)"
3003 else:
3004 tuple_check = "PyTuple_CheckExact(%s)"
3005 code.putln(
3006 "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
3007 tuple_check % rhs.py_result(),
3008 rhs.py_result(),
3009 len(self.args)))
3010 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3011 for item in self.unpacked_items:
3012 item.allocate(code)
3013 for i in range(len(self.args)):
3014 item = self.unpacked_items[i]
3015 code.put(
3016 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3017 item.result(),
3018 i))
3019 code.put_incref(item.result(), item.ctype())
3020 value_node = self.coerced_unpacked_items[i]
3021 value_node.generate_evaluation_code(code)
3022 rhs.generate_disposal_code(code)
3024 for i in range(len(self.args)):
3025 self.args[i].generate_assignment_code(
3026 self.coerced_unpacked_items[i], code)
3028 code.putln("} else {")
3030 if rhs.type is tuple_type:
3031 code.globalstate.use_utility_code(tuple_unpacking_error_code)
3032 code.putln("__Pyx_UnpackTupleError(%s, %s);" % (
3033 rhs.py_result(), len(self.args)))
3034 code.putln(code.error_goto(self.pos))
3035 else:
3036 self.iterator.allocate(code)
3037 code.putln(
3038 "%s = PyObject_GetIter(%s); %s" % (
3039 self.iterator.result(),
3040 rhs.py_result(),
3041 code.error_goto_if_null(self.iterator.result(), self.pos)))
3042 code.put_gotref(self.iterator.py_result())
3043 rhs.generate_disposal_code(code)
3044 for i in range(len(self.args)):
3045 item = self.unpacked_items[i]
3046 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3047 self.iterator.py_result(), i)
3048 code.putln(
3049 "%s = %s; %s" % (
3050 item.result(),
3051 typecast(item.ctype(), py_object_type, unpack_code),
3052 code.error_goto_if_null(item.result(), self.pos)))
3053 code.put_gotref(item.py_result())
3054 value_node = self.coerced_unpacked_items[i]
3055 value_node.generate_evaluation_code(code)
3056 code.put_error_if_neg(self.pos,
3057 "__Pyx_EndUnpack(%s)" % (
3058 self.iterator.py_result()))
3059 if debug_disposal_code:
3060 print("UnpackNode.generate_assignment_code:")
3061 print("...generating disposal code for %s" % self.iterator)
3062 self.iterator.generate_disposal_code(code)
3063 self.iterator.free_temps(code)
3064 self.iterator.release(code)
3066 for i in range(len(self.args)):
3067 self.args[i].generate_assignment_code(
3068 self.coerced_unpacked_items[i], code)
3070 code.putln("}")
3072 def generate_starred_assignment_code(self, rhs, code):
3073 for i, arg in enumerate(self.args):
3074 if arg.is_starred:
3075 starred_target = self.unpacked_items[i]
3076 fixed_args_left = self.args[:i]
3077 fixed_args_right = self.args[i+1:]
3078 break
3080 self.iterator.allocate(code)
3081 code.putln(
3082 "%s = PyObject_GetIter(%s); %s" % (
3083 self.iterator.result(),
3084 rhs.py_result(),
3085 code.error_goto_if_null(self.iterator.result(), self.pos)))
3086 code.put_gotref(self.iterator.py_result())
3087 rhs.generate_disposal_code(code)
3089 for item in self.unpacked_items:
3090 item.allocate(code)
3091 for i in range(len(fixed_args_left)):
3092 item = self.unpacked_items[i]
3093 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3094 self.iterator.py_result(), i)
3095 code.putln(
3096 "%s = %s; %s" % (
3097 item.result(),
3098 typecast(item.ctype(), py_object_type, unpack_code),
3099 code.error_goto_if_null(item.result(), self.pos)))
3100 code.put_gotref(item.py_result())
3101 value_node = self.coerced_unpacked_items[i]
3102 value_node.generate_evaluation_code(code)
3104 target_list = starred_target.result()
3105 code.putln("%s = PySequence_List(%s); %s" % (
3106 target_list, self.iterator.py_result(),
3107 code.error_goto_if_null(target_list, self.pos)))
3108 code.put_gotref(target_list)
3109 if fixed_args_right:
3110 code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
3111 unpacked_right_args = self.unpacked_items[-len(fixed_args_right):]
3112 code.putln("if (unlikely(PyList_GET_SIZE(%s) < %d)) {" % (
3113 (target_list, len(unpacked_right_args))))
3114 code.put("__Pyx_RaiseNeedMoreValuesError(%d+PyList_GET_SIZE(%s)); %s" % (
3115 len(fixed_args_left), target_list,
3116 code.error_goto(self.pos)))
3117 code.putln('}')
3118 for i, (arg, coerced_arg) in enumerate(zip(unpacked_right_args[::-1],
3119 self.coerced_unpacked_items[::-1])):
3120 code.putln(
3121 "%s = PyList_GET_ITEM(%s, PyList_GET_SIZE(%s)-1); " % (
3122 arg.py_result(),
3123 target_list, target_list))
3124 # resize the list the hard way
3125 code.putln("((PyListObject*)%s)->ob_size--;" % target_list)
3126 code.put_gotref(arg.py_result())
3127 coerced_arg.generate_evaluation_code(code)
3129 self.iterator.generate_disposal_code(code)
3130 self.iterator.free_temps(code)
3131 self.iterator.release(code)
3133 for i in range(len(self.args)):
3134 self.args[i].generate_assignment_code(
3135 self.coerced_unpacked_items[i], code)
3137 def annotate(self, code):
3138 for arg in self.args:
3139 arg.annotate(code)
3140 if self.unpacked_items:
3141 for arg in self.unpacked_items:
3142 arg.annotate(code)
3143 for arg in self.coerced_unpacked_items:
3144 arg.annotate(code)
3147 class TupleNode(SequenceNode):
3148 # Tuple constructor.
3150 gil_message = "Constructing Python tuple"
3152 def analyse_types(self, env, skip_children=False):
3153 if len(self.args) == 0:
3154 self.is_temp = 0
3155 self.is_literal = 1
3156 else:
3157 SequenceNode.analyse_types(self, env, skip_children)
3158 self.type = tuple_type
3160 def calculate_result_code(self):
3161 if len(self.args) > 0:
3162 error(self.pos, "Positive length tuples must be constructed.")
3163 else:
3164 return Naming.empty_tuple
3166 def calculate_constant_result(self):
3167 self.constant_result = tuple([
3168 arg.constant_result for arg in self.args])
3170 def compile_time_value(self, denv):
3171 values = self.compile_time_value_list(denv)
3172 try:
3173 return tuple(values)
3174 except Exception, e:
3175 self.compile_time_value_error(e)
3177 def generate_operation_code(self, code):
3178 if len(self.args) == 0:
3179 # result_code is Naming.empty_tuple
3180 return
3181 code.putln(
3182 "%s = PyTuple_New(%s); %s" % (
3183 self.result(),
3184 len(self.args),
3185 code.error_goto_if_null(self.result(), self.pos)))
3186 code.put_gotref(self.py_result())
3187 for i in range(len(self.args)):
3188 arg = self.args[i]
3189 if not arg.result_in_temp():
3190 code.put_incref(arg.result(), arg.ctype())
3191 code.putln(
3192 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3193 self.result(),
3194 i,
3195 arg.py_result()))
3196 code.put_giveref(arg.py_result())
3198 def generate_subexpr_disposal_code(self, code):
3199 # We call generate_post_assignment_code here instead
3200 # of generate_disposal_code, because values were stored
3201 # in the tuple using a reference-stealing operation.
3202 for arg in self.args:
3203 arg.generate_post_assignment_code(code)
3204 # Should NOT call free_temps -- this is invoked by the default
3205 # generate_evaluation_code which will do that.
3208 class ListNode(SequenceNode):
3209 # List constructor.
3211 # obj_conversion_errors [PyrexError] used internally
3212 # orignial_args [ExprNode] used internally
3214 gil_message = "Constructing Python list"
3216 def analyse_expressions(self, env):
3217 SequenceNode.analyse_expressions(self, env)
3218 self.coerce_to_pyobject(env)
3220 def analyse_types(self, env):
3221 hold_errors()
3222 self.original_args = list(self.args)
3223 SequenceNode.analyse_types(self, env)
3224 self.type = list_type
3225 self.obj_conversion_errors = held_errors()
3226 release_errors(ignore=True)
3228 def coerce_to(self, dst_type, env):
3229 if dst_type.is_pyobject:
3230 for err in self.obj_conversion_errors:
3231 report_error(err)
3232 self.obj_conversion_errors = []
3233 if not self.type.subtype_of(dst_type):
3234 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3235 elif dst_type.is_ptr:
3236 base_type = dst_type.base_type
3237 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3238 for i in range(len(self.original_args)):
3239 arg = self.args[i]
3240 if isinstance(arg, CoerceToPyTypeNode):
3241 arg = arg.arg
3242 self.args[i] = arg.coerce_to(base_type, env)
3243 elif dst_type.is_struct:
3244 if len(self.args) > len(dst_type.scope.var_entries):
3245 error(self.pos, "Too may members for '%s'" % dst_type)
3246 else:
3247 if len(self.args) < len(dst_type.scope.var_entries):
3248 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3249 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3250 if isinstance(arg, CoerceToPyTypeNode):
3251 arg = arg.arg
3252 self.args[i] = arg.coerce_to(member.type, env)
3253 self.type = dst_type
3254 else:
3255 self.type = error_type
3256 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3257 return self
3259 def release_temp(self, env):
3260 if self.type.is_array:
3261 # To be valid C++, we must allocate the memory on the stack
3262 # manually and be sure not to reuse it for something else.
3263 pass
3264 else:
3265 SequenceNode.release_temp(self, env)
3267 def calculate_constant_result(self):
3268 self.constant_result = [
3269 arg.constant_result for arg in self.args]
3271 def compile_time_value(self, denv):
3272 return self.compile_time_value_list(denv)
3274 def generate_operation_code(self, code):
3275 if self.type.is_pyobject:
3276 for err in self.obj_conversion_errors:
3277 report_error(err)
3278 code.putln("%s = PyList_New(%s); %s" %
3279 (self.result(),
3280 len(self.args),
3281 code.error_goto_if_null(self.result(), self.pos)))
3282 code.put_gotref(self.py_result())
3283 for i in range(len(self.args)):
3284 arg = self.args[i]
3285 #if not arg.is_temp:
3286 if not arg.result_in_temp():
3287 code.put_incref(arg.result(), arg.ctype())
3288 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3289 (self.result(),
3290 i,
3291 arg.py_result()))
3292 code.put_giveref(arg.py_result())
3293 elif self.type.is_array:
3294 for i, arg in enumerate(self.args):
3295 code.putln("%s[%s] = %s;" % (
3296 self.result(),
3297 i,
3298 arg.result()))
3299 elif self.type.is_struct:
3300 for arg, member in zip(self.args, self.type.scope.var_entries):
3301 code.putln("%s.%s = %s;" % (
3302 self.result(),
3303 member.cname,
3304 arg.result()))
3305 else:
3306 raise InternalError("List type never specified")
3308 def generate_subexpr_disposal_code(self, code):
3309 # We call generate_post_assignment_code here instead
3310 # of generate_disposal_code, because values were stored
3311 # in the list using a reference-stealing operation.
3312 for arg in self.args:
3313 arg.generate_post_assignment_code(code)
3314 # Should NOT call free_temps -- this is invoked by the default
3315 # generate_evaluation_code which will do that.
3318 class ComprehensionNode(ExprNode):
3319 subexprs = ["target"]
3320 child_attrs = ["loop", "append"]
3322 def analyse_types(self, env):
3323 self.target.analyse_expressions(env)
3324 self.type = self.target.type
3325 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3326 self.loop.analyse_declarations(env)
3327 self.loop.analyse_expressions(env)
3329 def calculate_result_code(self):
3330 return self.target.result()
3332 def generate_result_code(self, code):
3333 self.generate_operation_code(code)
3335 def generate_operation_code(self, code):
3336 self.loop.generate_execution_code(code)
3338 def annotate(self, code):
3339 self.loop.annotate(code)
3342 class ComprehensionAppendNode(ExprNode):
3343 # Need to be careful to avoid infinite recursion:
3344 # target must not be in child_attrs/subexprs
3345 subexprs = ['expr']
3347 def analyse_types(self, env):
3348 self.expr.analyse_types(env)
3349 if not self.expr.type.is_pyobject:
3350 self.expr = self.expr.coerce_to_pyobject(env)
3351 self.type = PyrexTypes.c_int_type
3352 self.is_temp = 1
3354 def generate_result_code(self, code):
3355 if self.target.type is list_type:
3356 function = "PyList_Append"
3357 elif self.target.type is set_type:
3358 function = "PySet_Add"
3359 else:
3360 raise InternalError(
3361 "Invalid type for comprehension node: %s" % self.target.type)
3363 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3364 (self.result(),
3365 function,
3366 self.target.result(),
3367 self.expr.result(),
3368 code.error_goto_if(self.result(), self.pos)))
3370 class DictComprehensionAppendNode(ComprehensionAppendNode):
3371 subexprs = ['key_expr', 'value_expr']
3373 def analyse_types(self, env):
3374 self.key_expr.analyse_types(env)
3375 if not self.key_expr.type.is_pyobject:
3376 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3377 self.value_expr.analyse_types(env)
3378 if not self.value_expr.type.is_pyobject:
3379 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3380 self.type = PyrexTypes.c_int_type
3381 self.is_temp = 1
3383 def generate_result_code(self, code):
3384 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3385 (self.result(),
3386 self.target.result(),
3387 self.key_expr.result(),
3388 self.value_expr.result(),
3389 code.error_goto_if(self.result(), self.pos)))
3392 class SetNode(ExprNode):
3393 # Set constructor.
3395 subexprs = ['args']
3397 gil_message = "Constructing Python set"
3399 def analyse_types(self, env):
3400 for i in range(len(self.args)):
3401 arg = self.args[i]
3402 arg.analyse_types(env)
3403 self.args[i] = arg.coerce_to_pyobject(env)
3404 self.type = set_type
3405 self.is_temp = 1
3407 def calculate_constant_result(self):
3408 self.constant_result = set([
3409 arg.constant_result for arg in self.args])
3411 def compile_time_value(self, denv):
3412 values = [arg.compile_time_value(denv) for arg in self.args]
3413 try:
3414 return set(values)
3415 except Exception, e:
3416 self.compile_time_value_error(e)
3418 def generate_evaluation_code(self, code):
3419 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3420 self.allocate_temp_result(code)
3421 code.putln(
3422 "%s = PySet_New(0); %s" % (
3423 self.result(),
3424 code.error_goto_if_null(self.result(), self.pos)))
3425 code.put_gotref(self.py_result())
3426 for arg in self.args:
3427 arg.generate_evaluation_code(code)
3428 code.putln(
3429 code.error_goto_if_neg(
3430 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3431 self.pos))
3432 arg.generate_disposal_code(code)
3433 arg.free_temps(code)
3436 class DictNode(ExprNode):
3437 # Dictionary constructor.
3438 #
3439 # key_value_pairs [DictItemNode]
3440 #
3441 # obj_conversion_errors [PyrexError] used internally
3443 subexprs = ['key_value_pairs']
3445 def calculate_constant_result(self):
3446 self.constant_result = dict([
3447 item.constant_result for item in self.key_value_pairs])
3449 def compile_time_value(self, denv):
3450 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3451 for item in self.key_value_pairs]
3452 try:
3453 return dict(pairs)
3454 except Exception, e:
3455 self.compile_time_value_error(e)
3457 def analyse_types(self, env):
3458 hold_errors()
3459 self.type = dict_type
3460 for item in self.key_value_pairs:
3461 item.analyse_types(env)
3462 self.obj_conversion_errors = held_errors()
3463 release_errors(ignore=True)
3464 self.is_temp = 1
3466 def coerce_to(self, dst_type, env):
3467 if dst_type.is_pyobject:
3468 self.release_errors()
3469 if not self.type.subtype_of(dst_type):
3470 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3471 elif dst_type.is_struct_or_union:
3472 self.type = dst_type
3473 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3474 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3475 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3476 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3477 for item in self.key_value_pairs:
3478 if isinstance(item.key, CoerceToPyTypeNode):
3479 item.key = item.key.arg
3480 if not isinstance(item.key, (StringNode, IdentifierStringNode)):
3481 error(item.key.pos, "Invalid struct field identifier")
3482 item.key = IdentifierStringNode(item.key.pos, value="<error>")
3483 else:
3484 member = dst_type.scope.lookup_here(item.key.value)
3485 if not member:
3486 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, item.key.value))
3487 else:
3488 value = item.value
3489 if isinstance(value, CoerceToPyTypeNode):
3490 value = value.arg
3491 item.value = value.coerce_to(member.type, env)
3492 else:
3493 self.type = error_type
3494 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3495 return self
3497 def release_errors(self):
3498 for err in self.obj_conversion_errors:
3499 report_error(err)
3500 self.obj_conversion_errors = []
3502 gil_message = "Constructing Python dict"
3504 def generate_evaluation_code(self, code):
3505 # Custom method used here because key-value
3506 # pairs are evaluated and used one at a time.
3507 code.mark_pos(self.pos)
3508 self.allocate_temp_result(code)
3509 if self.type.is_pyobject:
3510 self.release_errors()
3511 code.putln(
3512 "%s = PyDict_New(); %s" % (
3513 self.result(),
3514 code.error_goto_if_null(self.result(), self.pos)))
3515 code.put_gotref(self.py_result())
3516 for item in self.key_value_pairs:
3517 item.generate_evaluation_code(code)
3518 if self.type.is_pyobject:
3519 code.put_error_if_neg(self.pos,
3520 "PyDict_SetItem(%s, %s, %s)" % (
3521 self.result(),
3522 item.key.py_result(),
3523 item.value.py_result()))
3524 else:
3525 code.putln("%s.%s = %s;" % (
3526 self.result(),
3527 item.key.value,
3528 item.value.result()))
3529 item.generate_disposal_code(code)
3530 item.free_temps(code)
3532 def annotate(self, code):
3533 for item in self.key_value_pairs:
3534 item.annotate(code)
3536 class DictItemNode(ExprNode):
3537 # Represents a single item in a DictNode
3538 #
3539 # key ExprNode
3540 # value ExprNode
3541 subexprs = ['key', 'value']
3543 gil_check = None # handled by DictNode
3545 def calculate_constant_result(self):
3546 self.constant_result = (
3547 self.key.constant_result, self.value.constant_result)
3549 def analyse_types(self, env):
3550 self.key.analyse_types(env)
3551 self.value.analyse_types(env)
3552 self.key = self.key.coerce_to_pyobject(env)
3553 self.value = self.value.coerce_to_pyobject(env)
3555 def generate_evaluation_code(self, code):
3556 self.key.generate_evaluation_code(code)
3557 self.value.generate_evaluation_code(code)
3559 def generate_disposal_code(self, code):
3560 self.key.generate_disposal_code(code)
3561 self.value.generate_disposal_code(code)
3563 def free_temps(self, code):
3564 self.key.free_temps(code)
3565 self.value.free_temps(code)
3567 def __iter__(self):
3568 return iter([self.key, self.value])
3571 class ClassNode(ExprNode):
3572 # Helper class used in the implementation of Python
3573 # class definitions. Constructs a class object given
3574 # a name, tuple of bases and class dictionary.
3575 #
3576 # name EncodedString Name of the class
3577 # bases ExprNode Base class tuple
3578 # dict ExprNode Class dict (not owned by this node)
3579 # doc ExprNode or None Doc string
3580 # module_name string Name of defining module
3582 subexprs = ['bases', 'doc']
3584 def analyse_types(self, env):
3585 self.bases.analyse_types(env)
3586 if self.doc:
3587 self.doc.analyse_types(env)
3588 self.doc = self.doc.coerce_to_pyobject(env)
3589 self.module_name = env.global_scope().qualified_name
3590 self.type = py_object_type
3591 self.is_temp = 1
3592 env.use_utility_code(create_class_utility_code);
3594 gil_message = "Constructing Python class"
3596 def generate_result_code(self, code):
3597 cname = code.intern_identifier(self.name)
3598 if self.doc:
3599 code.put_error_if_neg(self.pos,
3600 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3601 self.dict.py_result(),
3602 self.doc.py_result()))
3603 code.putln(
3604 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3605 self.result(),
3606 self.bases.py_result(),
3607 self.dict.py_result(),
3608 cname,
3609 self.module_name,
3610 code.error_goto_if_null(self.result(), self.pos)))
3611 code.put_gotref(self.py_result())
3614 class UnboundMethodNode(ExprNode):
3615 # Helper class used in the implementation of Python
3616 # class definitions. Constructs an unbound method
3617 # object from a class and a function.
3618 #
3619 # function ExprNode Function object
3621 subexprs = ['function']
3623 def analyse_types(self, env):
3624 self.function.analyse_types(env)
3625 self.type = py_object_type
3626 self.is_temp = 1
3628 gil_message = "Constructing an unbound method"
3630 def generate_result_code(self, code):
3631 class_cname = code.pyclass_stack[-1].classobj.result()
3632 code.putln(
3633 "%s = PyMethod_New(%s, 0, %s); %s" % (
3634 self.result(),
3635 self.function.py_result(),
3636 class_cname,
3637 code.error_goto_if_null(self.result(), self.pos)))
3638 code.put_gotref(self.py_result())
3640 class PyCFunctionNode(AtomicExprNode):
3641 # Helper class used in the implementation of Python
3642 # class definitions. Constructs a PyCFunction object
3643 # from a PyMethodDef struct.
3644 #
3645 # pymethdef_cname string PyMethodDef structure
3647 def analyse_types(self, env):
3648 self.type = py_object_type
3649 self.is_temp = 1
3651 gil_message = "Constructing Python function"
3653 def generate_result_code(self, code):
3654 code.putln(
3655 "%s = PyCFunction_New(&%s, 0); %s" % (
3656 self.result(),
3657 self.pymethdef_cname,
3658 code.error_goto_if_null(self.result(), self.pos)))
3659 code.put_gotref(self.py_result())
3661 #-------------------------------------------------------------------
3662 #
3663 # Unary operator nodes
3664 #
3665 #-------------------------------------------------------------------
3667 compile_time_unary_operators = {
3668 'not': operator.not_,
3669 '~': operator.inv,
3670 '-': operator.neg,
3671 '+': operator.pos,
3672 }
3674 class UnopNode(ExprNode):
3675 # operator string
3676 # operand ExprNode
3677 #
3678 # Processing during analyse_expressions phase:
3679 #
3680 # analyse_c_operation
3681 # Called when the operand is not a pyobject.
3682 # - Check operand type and coerce if needed.
3683 # - Determine result type and result code fragment.
3684 # - Allocate temporary for result if needed.
3686 subexprs = ['operand']
3688 def calculate_constant_result(self):
3689 func = compile_time_unary_operators[self.operator]
3690 self.constant_result = func(self.operand.constant_result)
3692 def compile_time_value(self, denv):
3693 func = compile_time_unary_operators.get(self.operator)
3694 if not func:
3695 error(self.pos,
3696 "Unary '%s' not supported in compile-time expression"
3697 % self.operator)
3698 operand = self.operand.compile_time_value(denv)
3699 try:
3700 return func(operand)
3701 except Exception, e:
3702 self.compile_time_value_error(e)
3704 def analyse_types(self, env):
3705 self.operand.analyse_types(env)
3706 if self.is_py_operation():
3707 self.coerce_operand_to_pyobject(env)
3708 self.type = py_object_type
3709 self.is_temp = 1
3710 else:
3711 self.analyse_c_operation(env)
3713 def check_const(self):
3714 self.operand.check_const()
3716 def is_py_operation(self):
3717 return self.operand.type.is_pyobject
3719 def gil_check(self, env):
3720 if self.is_py_operation():
3721 self._gil_check(env)
3723 def coerce_operand_to_pyobject(self, env):
3724 self.operand = self.operand.coerce_to_pyobject(env)
3726 def generate_result_code(self, code):
3727 if self.operand.type.is_pyobject:
3728 self.generate_py_operation_code(code)
3730 def generate_py_operation_code(self, code):
3731 function = self.py_operation_function()
3732 code.putln(
3733 "%s = %s(%s); %s" % (
3734 self.result(),
3735 function,
3736 self.operand.py_result(),
3737 code.error_goto_if_null(self.result(), self.pos)))
3738 code.put_gotref(self.py_result())
3740 def type_error(self):
3741 if not self.operand.type.is_error:
3742 error(self.pos, "Invalid operand type for '%s' (%s)" %
3743 (self.operator, self.operand.type))
3744 self.type = PyrexTypes.error_type
3747 class NotNode(ExprNode):
3748 # 'not' operator
3749 #
3750 # operand ExprNode
3752 def calculate_constant_result(self):
3753 self.constant_result = not self.operand.constant_result
3755 def compile_time_value(self, denv):
3756 operand = self.operand.compile_time_value(denv)
3757 try:
3758 return not operand
3759 except Exception, e:
3760 self.compile_time_value_error(e)
3762 subexprs = ['operand']
3764 def analyse_types(self, env):
3765 self.operand.analyse_types(env)
3766 self.operand = self.operand.coerce_to_boolean(env)
3767 self.type = PyrexTypes.c_bint_type
3769 def calculate_result_code(self):
3770 return "(!%s)" % self.operand.result()
3772 def generate_result_code(self, code):
3773 pass
3776 class UnaryPlusNode(UnopNode):
3777 # unary '+' operator
3779 operator = '+'
3781 def analyse_c_operation(self, env):
3782 self.type = self.operand.type
3784 def py_operation_function(self):
3785 return "PyNumber_Positive"
3787 def calculate_result_code(self):
3788 return self.operand.result()
3791 class UnaryMinusNode(UnopNode):
3792 # unary '-' operator
3794 operator = '-'
3796 def analyse_c_operation(self, env):
3797 if self.operand.type.is_numeric:
3798 self.type = self.operand.type
3799 else:
3800 self.type_error()
3802 def py_operation_function(self):
3803 return "PyNumber_Negative"
3805 def calculate_result_code(self):
3806 return "(-%s)" % self.operand.result()
3809 class TildeNode(UnopNode):
3810 # unary '~' operator
3812 def analyse_c_operation(self, env):
3813 if self.operand.type.is_int:
3814 self.type = self.operand.type
3815 else:
3816 self.type_error()
3818 def py_operation_function(self):
3819 return "PyNumber_Invert"
3821 def calculate_result_code(self):
3822 return "(~%s)" % self.operand.result()
3825 class AmpersandNode(ExprNode):
3826 # The C address-of operator.
3827 #
3828 # operand ExprNode
3830 subexprs = ['operand']
3832 def analyse_types(self, env):
3833 self.operand.analyse_types(env)
3834 argtype = self.operand.type
3835 if not (argtype.is_cfunction or self.operand.is_lvalue()):
3836 self.error("Taking address of non-lvalue")
3837 return
3838 if argtype.is_pyobject:
3839 self.error("Cannot take address of Python variable")
3840 return
3841 self.type = PyrexTypes.c_ptr_type(argtype)
3843 def check_const(self):
3844 self.operand.check_const_addr()
3846 def error(self, mess):
3847 error(self.pos, mess)
3848 self.type = PyrexTypes.error_type
3849 self.result_code = "<error>"
3851 def calculate_result_code(self):
3852 return "(&%s)" % self.operand.result()
3854 def generate_result_code(self, code):
3855 pass
3858 unop_node_classes = {
3859 "+": UnaryPlusNode,
3860 "-": UnaryMinusNode,
3861 "~": TildeNode,
3862 }
3864 def unop_node(pos, operator, operand):
3865 # Construct unnop node of appropriate class for
3866 # given operator.
3867 if isinstance(operand, IntNode) and operator == '-':
3868 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3869 elif isinstance(operand, UnopNode) and operand.operator == operator:
3870 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3871 return unop_node_classes[operator](pos,
3872 operator = operator,
3873 operand = operand)
3876 class TypecastNode(ExprNode):
3877 # C type cast
3878 #
3879 # operand ExprNode
3880 # base_type CBaseTypeNode
3881 # declarator CDeclaratorNode
3882 #
3883 # If used from a transform, one can if wanted specify the attribute
3884 # "type" directly and leave base_type and declarator to None
3886 subexprs = ['operand']
3887 base_type = declarator = type = None
3889 def analyse_types(self, env):
3890 if self.type is None:
3891 base_type = self.base_type.analyse(env)
3892 _, self.type = self.declarator.analyse(base_type, env)
3893 if self.type.is_cfunction:
3894 error(self.pos,
3895 "Cannot cast to a function type")
3896 self.type = PyrexTypes.error_type
3897 self.operand.analyse_types(env)
3898 to_py = self.type.is_pyobject
3899 from_py = self.operand.type.is_pyobject
3900 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3901 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3902 if to_py and not from_py:
3903 if (self.operand.type.to_py_function and
3904 self.operand.type.create_convert_utility_code(env)):
3905 self.result_ctype = py_object_type
3906 self.operand = self.operand.coerce_to_pyobject(env)
3907 else:
3908 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3909 self.operand = self.operand.coerce_to_simple(env)
3910 elif from_py and not to_py:
3911 if self.type.from_py_function:
3912 self.operand = self.operand.coerce_to(self.type, env)
3913 else:
3914 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3915 elif from_py and to_py:
3916 if self.typecheck and self.type.is_extension_type:
3917 self.operand = PyTypeTestNode(self.operand, self.type, env)
3919 def gil_check(self, env):
3920 if self.type.is_pyobject and self.is_temp:
3921 self._gil_check(env)
3923 def check_const(self):
3924 self.operand.check_const()
3926 def calculate_constant_result(self):
3927 # we usually do not know the result of a type cast at code
3928 # generation time
3929 pass
3931 def calculate_result_code(self):
3932 opnd = self.operand
3933 return self.type.cast_code(opnd.result())
3935 def result_as(self, type):
3936 if self.type.is_pyobject and not self.is_temp:
3937 # Optimise away some unnecessary casting
3938 return self.operand.result_as(type)
3939 else:
3940 return ExprNode.result_as(self, type)
3942 def generate_result_code(self, code):
3943 if self.is_temp:
3944 code.putln(
3945 "%s = (PyObject *)%s;" % (
3946 self.result(),
3947 self.operand.result()))
3948 code.put_incref(self.result(), self.ctype())
3951 class SizeofNode(ExprNode):
3952 # Abstract base class for sizeof(x) expression nodes.
3954 type = PyrexTypes.c_size_t_type
3956 def check_const(self):
3957 pass
3959 def generate_result_code(self, code):
3960 pass
3963 class SizeofTypeNode(SizeofNode):
3964 # C sizeof function applied to a type
3965 #
3966 # base_type CBaseTypeNode
3967 # declarator CDeclaratorNode
3969 subexprs = []
3970 arg_type = None
3972 def analyse_types(self, env):
3973 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
3974 # this could be better handled by more uniformly treating types as runtime-available objects
3975 if 0 and self.base_type.module_path:
3976 path = self.base_type.module_path
3977 obj = env.lookup(path[0])
3978 if obj.as_module is None:
3979 operand = NameNode(pos=self.pos, name=path[0])
3980 for attr in path[1:]:
3981 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
3982 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
3983 self.operand = operand
3984 self.__class__ = SizeofVarNode
3985 self.analyse_types(env)
3986 return
3987 if self.arg_type is None:
3988 base_type = self.base_type.analyse(env)
3989 _, arg_type = self.declarator.analyse(base_type, env)
3990 self.arg_type = arg_type
3991 self.check_type()
3993 def check_type(self):
3994 arg_type = self.arg_type
3995 if arg_type.is_pyobject and not arg_type.is_extension_type:
3996 error(self.pos, "Cannot take sizeof Python object")
3997 elif arg_type.is_void:
3998 error(self.pos, "Cannot take sizeof void")
3999 elif not arg_type.is_complete():
4000 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
4002 def calculate_result_code(self):
4003 if self.arg_type.is_extension_type:
4004 # the size of the pointer is boring
4005 # we want the size of the actual struct
4006 arg_code = self.arg_type.declaration_code("", deref=1)
4007 else:
4008 arg_code = self.arg_type.declaration_code("")
4009 return "(sizeof(%s))" % arg_code
4012 class SizeofVarNode(SizeofNode):
4013 # C sizeof function applied to a variable
4014 #
4015 # operand ExprNode
4017 subexprs = ['operand']
4019 def analyse_types(self, env):
4020 # We may actually be looking at a type rather than a variable...
4021 # If we are, traditional analysis would fail...
4022 operand_as_type = self.operand.analyse_as_type(env)
4023 if operand_as_type:
4024 self.arg_type = operand_as_type
4025 self.__class__ = SizeofTypeNode
4026 self.check_type()
4027 else:
4028 self.operand.analyse_types(env)
4030 def calculate_result_code(self):
4031 return "(sizeof(%s))" % self.operand.result()
4033 def generate_result_code(self, code):
4034 pass
4037 #-------------------------------------------------------------------
4038 #
4039 # Binary operator nodes
4040 #
4041 #-------------------------------------------------------------------
4043 def _not_in(x, seq):
4044 return x not in seq
4046 compile_time_binary_operators = {
4047 '<': operator.lt,
4048 '<=': operator.le,
4049 '==': operator.eq,
4050 '!=': operator.ne,
4051 '>=': operator.ge,
4052 '>': operator.gt,
4053 'is': operator.is_,
4054 'is_not': operator.is_not,
4055 '+': operator.add,
4056 '&': operator.and_,
4057 '/': operator.div,
4058 '//': operator.floordiv,
4059 '<<': operator.lshift,
4060 '%': operator.mod,
4061 '*': operator.mul,
4062 '|': operator.or_,
4063 '**': operator.pow,
4064 '>>': operator.rshift,
4065 '-': operator.sub,
4066 #'/': operator.truediv,
4067 '^': operator.xor,
4068 'in': operator.contains,
4069 'not_in': _not_in,
4070 }
4072 def get_compile_time_binop(node):
4073 func = compile_time_binary_operators.get(node.operator)
4074 if not func:
4075 error(node.pos,
4076 "Binary '%s' not supported in compile-time expression"
4077 % node.operator)
4078 return func
4080 class BinopNode(ExprNode):
4081 # operator string
4082 # operand1 ExprNode
4083 # operand2 ExprNode
4084 #
4085 # Processing during analyse_expressions phase:
4086 #
4087 # analyse_c_operation
4088 # Called when neither operand is a pyobject.
4089 # - Check operand types and coerce if needed.
4090 # - Determine result type and result code fragment.
4091 # - Allocate temporary for result if needed.
4093 subexprs = ['operand1', 'operand2']
4095 def calculate_constant_result(self):
4096 func = compile_time_binary_operators[self.operator]
4097 self.constant_result = func(
4098 self.operand1.constant_result,
4099 self.operand2.constant_result)
4101 def compile_time_value(self, denv):
4102 func = get_compile_time_binop(self)
4103 operand1 = self.operand1.compile_time_value(denv)
4104 operand2 = self.operand2.compile_time_value(denv)
4105 try:
4106 return func(operand1, operand2)
4107 except Exception, e:
4108 self.compile_time_value_error(e)
4110 def analyse_types(self, env):
4111 self.operand1.analyse_types(env)
4112 self.operand2.analyse_types(env)
4113 if self.is_py_operation():
4114 self.coerce_operands_to_pyobjects(env)
4115 self.type = py_object_type
4116 self.is_temp = 1
4117 if Options.incref_local_binop and self.operand1.type.is_pyobject:
4118 self.operand1 = self.operand1.coerce_to_temp(env)
4119 else:
4120 self.analyse_c_operation(env)
4122 def is_py_operation(self):
4123 return (self.operand1.type.is_pyobject
4124 or self.operand2.type.is_pyobject)
4126 def gil_check(self, env):
4127 if self.is_py_operation():
4128 self._gil_check(env)
4130 def coerce_operands_to_pyobjects(self, env):
4131 self.operand1 = self.operand1.coerce_to_pyobject(env)
4132 self.operand2 = self.operand2.coerce_to_pyobject(env)
4134 def check_const(self):
4135 self.operand1.check_const()
4136 self.operand2.check_const()
4138 def generate_result_code(self, code):
4139 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4140 if self.operand1.type.is_pyobject:
4141 function = self.py_operation_function()
4142 if function == "PyNumber_Power":
4143 extra_args = ", Py_None"
4144 else:
4145 extra_args = ""
4146 code.putln(
4147 "%s = %s(%s, %s%s); %s" % (
4148 self.result(),
4149 function,
4150 self.operand1.py_result(),
4151 self.operand2.py_result(),
4152 extra_args,
4153 code.error_goto_if_null(self.result(), self.pos)))
4154 code.put_gotref(self.py_result())
4156 def type_error(self):
4157 if not (self.operand1.type.is_error
4158 or self.operand2.type.is_error):
4159 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4160 (self.operator, self.operand1.type,
4161 self.operand2.type))
4162 self.type = PyrexTypes.error_type
4165 class NumBinopNode(BinopNode):
4166 # Binary operation taking numeric arguments.
4168 def analyse_c_operation(self, env):
4169 type1 = self.operand1.type
4170 type2 = self.operand2.type
4171 self.type = self.compute_c_result_type(type1, type2)
4172 if not self.type:
4173 self.type_error()
4175 def compute_c_result_type(self, type1, type2):
4176 if self.c_types_okay(type1, type2):
4177 return PyrexTypes.widest_numeric_type(type1, type2)
4178 else:
4179 return None
4181 def get_constant_c_result_code(self):
4182 value1 = self.operand1.get_constant_c_result_code()
4183 value2 = self.operand2.get_constant_c_result_code()
4184 if value1 and value2:
4185 return "(%s %s %s)" % (value1, self.operator, value2)
4186 else:
4187 return None
4189 def c_types_okay(self, type1, type2):
4190 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4191 return (type1.is_numeric or type1.is_enum) \
4192 and (type2.is_numeric or type2.is_enum)
4194 def calculate_result_code(self):
4195 return "(%s %s %s)" % (
4196 self.operand1.result(),
4197 self.operator,
4198 self.operand2.result())
4200 def py_operation_function(self):
4201 return self.py_functions[self.operator]
4203 py_functions = {
4204 "|": "PyNumber_Or",
4205 "^": "PyNumber_Xor",
4206 "&": "PyNumber_And",
4207 "<<": "PyNumber_Lshift",
4208 ">>": "PyNumber_Rshift",
4209 "+": "PyNumber_Add",
4210 "-": "PyNumber_Subtract",
4211 "*": "PyNumber_Multiply",
4212 "/": "__Pyx_PyNumber_Divide",
4213 "//": "PyNumber_FloorDivide",
4214 "%": "PyNumber_Remainder",
4215 "**": "PyNumber_Power"
4216 }
4219 class IntBinopNode(NumBinopNode):
4220 # Binary operation taking integer arguments.
4222 def c_types_okay(self, type1, type2):
4223 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4224 return (type1.is_int or type1.is_enum) \
4225 and (type2.is_int or type2.is_enum)
4228 class AddNode(NumBinopNode):
4229 # '+' operator.
4231 def is_py_operation(self):
4232 if self.operand1.type.is_string \
4233 and self.operand2.type.is_string:
4234 return 1
4235 else:
4236 return NumBinopNode.is_py_operation(self)
4238 def compute_c_result_type(self, type1, type2):
4239 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4240 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4241 return type1
4242 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4243 return type2
4244 else:
4245 return NumBinopNode.compute_c_result_type(
4246 self, type1, type2)
4249 class SubNode(NumBinopNode):
4250 # '-' operator.
4252 def compute_c_result_type(self, type1, type2):
4253 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4254 return type1
4255 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4256 return PyrexTypes.c_int_type
4257 else:
4258 return NumBinopNode.compute_c_result_type(
4259 self, type1, type2)
4262 class MulNode(NumBinopNode):
4263 # '*' operator.
4265 def is_py_operation(self):
4266 type1 = self.operand1.type
4267 type2 = self.operand2.type
4268 if (type1.is_string and type2.is_int) \
4269 or (type2.is_string and type1.is_int):
4270 return 1
4271 else:
4272 return NumBinopNode.is_py_operation(self)
4275 class DivNode(NumBinopNode):
4276 # '/' or '//' operator.
4278 cdivision = None
4279 cdivision_warnings = False
4281 def analyse_types(self, env):
4282 NumBinopNode.analyse_types(self, env)
4283 if not self.type.is_pyobject and env.directives['cdivision_warnings']:
4284 self.operand1 = self.operand1.coerce_to_simple(env)
4285 self.operand2 = self.operand2.coerce_to_simple(env)
4287 def generate_evaluation_code(self, code):
4288 if not self.type.is_pyobject:
4289 if self.cdivision is None:
4290 self.cdivision = (code.globalstate.directives['cdivision']
4291 or not self.type.signed
4292 or self.type.is_float)
4293 if not self.cdivision:
4294 code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
4295 NumBinopNode.generate_evaluation_code(self, code)
4296 if not self.type.is_pyobject and code.globalstate.directives['cdivision_warnings']:
4297 self.generate_div_warning_code(code)
4299 def generate_div_warning_code(self, code):
4300 code.globalstate.use_utility_code(cdivision_warning_utility_code)
4301 code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
4302 self.operand1.result(),
4303 self.operand2.result()))
4304 code.putln(code.set_error_info(self.pos));
4305 code.put("if (__Pyx_cdivision_warning()) ")
4306 code.put_goto(code.error_label)
4307 code.putln("}")
4309 def calculate_result_code(self):
4310 if self.type.is_float and self.operator == '//':
4311 return "floor(%s / %s)" % (
4312 self.operand1.result(),
4313 self.operand2.result())
4314 elif self.cdivision:
4315 return "(%s / %s)" % (
4316 self.operand1.result(),
4317 self.operand2.result())
4318 else:
4319 return "__Pyx_div_%s(%s, %s)" % (
4320 self.type.specalization_name(),
4321 self.operand1.result(),
4322 self.operand2.result())
4325 class ModNode(DivNode):
4326 # '%' operator.
4328 def is_py_operation(self):
4329 return (self.operand1.type.is_string
4330 or self.operand2.type.is_string
4331 or NumBinopNode.is_py_operation(self))
4333 def generate_evaluation_code(self, code):
4334 if not self.type.is_pyobject:
4335 if self.cdivision is None:
4336 self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
4337 if not self.cdivision:
4338 if self.type.is_int:
4339 code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
4340 else:
4341 code.globalstate.use_utility_code(
4342 mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
4343 NumBinopNode.generate_evaluation_code(self, code)
4344 if not self.type.is_pyobject and code.globalstate.directives['cdivision_warnings']:
4345 self.generate_div_warning_code(code)
4347 def calculate_result_code(self):
4348 if self.cdivision:
4349 if self.type.is_float:
4350 return "fmod%s(%s, %s)" % (
4351 self.type.math_h_modifier,
4352 self.operand1.result(),
4353 self.operand2.result())
4354 else:
4355 return "(%s %% %s)" % (
4356 self.operand1.result(),
4357 self.operand2.result())
4358 else:
4359 return "__Pyx_mod_%s(%s, %s)" % (
4360 self.type.specalization_name(),
4361 self.operand1.result(),
4362 self.operand2.result())
4364 class PowNode(NumBinopNode):
4365 # '**' operator.
4367 def analyse_c_operation(self, env):
4368 NumBinopNode.analyse_c_operation(self, env)
4369 if self.operand1.type.is_float or self.operand2.type.is_float:
4370 self.pow_func = "pow"
4371 else:
4372 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
4373 env.use_utility_code(
4374 int_pow_utility_code.specialize(func_name=self.pow_func,
4375 type=self.type.declaration_code('')))
4377 def calculate_result_code(self):
4378 return "%s(%s, %s)" % (
4379 self.pow_func,
4380 self.operand1.result(),
4381 self.operand2.result())
4384 # Note: This class is temporary "shut down" into an ineffective mode temp
4385 # allocation mode.
4386 #
4387 # More sophisticated temp reuse was going on before,
4388 # one could have a look at adding this again after /all/ classes
4389 # are converted to the new temp scheme. (The temp juggling cannot work
4390 # otherwise).
4391 class BoolBinopNode(ExprNode):
4392 # Short-circuiting boolean operation.
4393 #
4394 # operator string
4395 # operand1 ExprNode
4396 # operand2 ExprNode
4398 subexprs = ['operand1', 'operand2']
4400 def calculate_constant_result(self):
4401 if self.operator == 'and':
4402 self.constant_result = \
4403 self.operand1.constant_result and \
4404 self.operand2.constant_result
4405 else:
4406 self.constant_result = \
4407 self.operand1.constant_result or \
4408 self.operand2.constant_result
4410 def compile_time_value(self, denv):
4411 if self.operator == 'and':
4412 return self.operand1.compile_time_value(denv) \
4413 and self.operand2.compile_time_value(denv)
4414 else:
4415 return self.operand1.compile_time_value(denv) \
4416 or self.operand2.compile_time_value(denv)
4418 def coerce_to_boolean(self, env):
4419 self.operand1 = self.operand1.coerce_to_boolean(env)
4420 self.operand2 = self.operand2.coerce_to_boolean(env)
4421 self.type = PyrexTypes.c_bint_type
4422 return self
4424 def analyse_types(self, env):
4425 self.operand1.analyse_types(env)
4426 self.operand2.analyse_types(env)
4427 if self.operand1.type.is_pyobject or \
4428 self.operand2.type.is_pyobject:
4429 self.operand1 = self.operand1.coerce_to_pyobject(env)
4430 self.operand2 = self.operand2.coerce_to_pyobject(env)
4431 self.type = py_object_type
4432 else:
4433 self.operand1 = self.operand1.coerce_to_boolean(env)
4434 self.operand2 = self.operand2.coerce_to_boolean(env)
4435 self.type = PyrexTypes.c_bint_type
4437 # Below disabled for
4439 # For what we're about to do, it's vital that
4440 # both operands be temp nodes.
4441 # self.operand1 = self.operand1.coerce_to_temp(env) #CTT
4442 # self.operand2 = self.operand2.coerce_to_temp(env)
4443 self.is_temp = 1
4445 gil_message = "Truth-testing Python object"
4447 def check_const(self):
4448 self.operand1.check_const()
4449 self.operand2.check_const()
4451 def calculate_result_code(self):
4452 return "(%s %s %s)" % (
4453 self.operand1.result(),
4454 self.py_to_c_op[self.operator],
4455 self.operand2.result())
4457 py_to_c_op = {'and': "&&", 'or': "||"}
4459 def generate_evaluation_code(self, code):
4460 code.mark_pos(self.pos)
4461 self.operand1.generate_evaluation_code(code)
4462 test_result, uses_temp = self.generate_operand1_test(code)
4463 if self.operator == 'and':
4464 sense = ""
4465 else:
4466 sense = "!"
4467 code.putln(
4468 "if (%s%s) {" % (
4469 sense,
4470 test_result))
4471 if uses_temp:
4472 code.funcstate.release_temp(test_result)
4473 self.operand1.generate_disposal_code(code)
4474 self.operand2.generate_evaluation_code(code)
4475 self.allocate_temp_result(code)
4476 self.operand2.make_owned_reference(code)
4477 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
4478 self.operand2.generate_post_assignment_code(code)
4479 self.operand2.free_temps(code)
4480 code.putln("} else {")
4481 self.operand1.make_owned_reference(code)
4482 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
4483 self.operand1.generate_post_assignment_code(code)
4484 self.operand1.free_temps(code)
4485 code.putln("}")
4487 def generate_operand1_test(self, code):
4488 # Generate code to test the truth of the first operand.
4489 if self.type.is_pyobject:
4490 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
4491 manage_ref=False)
4492 code.putln(
4493 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4494 test_result,
4495 self.operand1.py_result(),
4496 code.error_goto_if_neg(test_result, self.pos)))
4497 else:
4498 test_result = self.operand1.result()
4499 return (test_result, self.type.is_pyobject)
4502 class CondExprNode(ExprNode):
4503 # Short-circuiting conditional expression.
4504 #
4505 # test ExprNode
4506 # true_val ExprNode
4507 # false_val ExprNode
4509 true_val = None
4510 false_val = None
4512 subexprs = ['test', 'true_val', 'false_val']
4514 def calculate_constant_result(self):
4515 if self.test.constant_result:
4516 self.constant_result = self.true_val.constant_result
4517 else:
4518 self.constant_result = self.false_val.constant_result
4520 def analyse_types(self, env):
4521 self.test.analyse_types(env)
4522 self.test = self.test.coerce_to_boolean(env)
4523 self.true_val.analyse_types(env)
4524 self.false_val.analyse_types(env)
4525 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
4526 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
4527 self.true_val = self.true_val.coerce_to(self.type, env)
4528 self.false_val = self.false_val.coerce_to(self.type, env)
4529 self.is_temp = 1
4530 if self.type == PyrexTypes.error_type:
4531 self.type_error()
4533 def compute_result_type(self, type1, type2):
4534 if type1 == type2:
4535 return type1
4536 elif type1.is_numeric and type2.is_numeric:
4537 return PyrexTypes.widest_numeric_type(type1, type2)
4538 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
4539 return type2
4540 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
4541 return type1
4542 elif type1.is_pyobject or type2.is_pyobject:
4543 return py_object_type
4544 elif type1.assignable_from(type2):
4545 return type1
4546 elif type2.assignable_from(type1):
4547 return type2
4548 else:
4549 return PyrexTypes.error_type
4551 def type_error(self):
4552 if not (self.true_val.type.is_error or self.false_val.type.is_error):
4553 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
4554 (self.true_val.type, self.false_val.type))
4555 self.type = PyrexTypes.error_type
4557 def check_const(self):
4558 self.test.check_const()
4559 self.true_val.check_const()
4560 self.false_val.check_const()
4562 def generate_evaluation_code(self, code):
4563 # Because subexprs may not be evaluated we can use a more optimal
4564 # subexpr allocation strategy than the default, so override evaluation_code.
4566 code.mark_pos(self.pos)
4567 self.allocate_temp_result(code)
4568 self.test.generate_evaluation_code(code)
4569 code.putln("if (%s) {" % self.test.result() )
4570 self.eval_and_get(code, self.true_val)
4571 code.putln("} else {")
4572 self.eval_and_get(code, self.false_val)
4573 code.putln("}")
4574 self.test.generate_disposal_code(code)
4575 self.test.free_temps(code)
4577 def eval_and_get(self, code, expr):
4578 expr.generate_evaluation_code(code)
4579 expr.make_owned_reference(code)
4580 code.putln("%s = %s;" % (self.result(), expr.result()))
4581 expr.generate_post_assignment_code(code)
4582 expr.free_temps(code)
4584 richcmp_constants = {
4585 "<" : "Py_LT",
4586 "<=": "Py_LE",
4587 "==": "Py_EQ",
4588 "!=": "Py_NE",
4589 "<>": "Py_NE",
4590 ">" : "Py_GT",
4591 ">=": "Py_GE",
4592 }
4594 class CmpNode(object):
4595 # Mixin class containing code common to PrimaryCmpNodes
4596 # and CascadedCmpNodes.
4598 def calculate_cascaded_constant_result(self, operand1_result):
4599 func = compile_time_binary_operators[self.operator]
4600 operand2_result = self.operand2.constant_result
4601 result = func(operand1_result, operand2_result)
4602 if result and self.cascade:
4603 result = result and \
4604 self.cascade.cascaded_compile_time_value(operand2_result)
4605 self.constant_result = result
4607 def cascaded_compile_time_value(self, operand1, denv):
4608 func = get_compile_time_binop(self)
4609 operand2 = self.operand2.compile_time_value(denv)
4610 try:
4611 result = func(operand1, operand2)
4612 except Exception, e:
4613 self.compile_time_value_error(e)
4614 result = None
4615 if result:
4616 cascade = self.cascade
4617 if cascade:
4618 # FIXME: I bet this must call cascaded_compile_time_value()
4619 result = result and cascade.compile_time_value(operand2, denv)
4620 return result
4622 def is_python_comparison(self):
4623 return (self.has_python_operands()
4624 or (self.cascade and self.cascade.is_python_comparison())
4625 or self.operator in ('in', 'not_in'))
4627 def is_python_result(self):
4628 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
4629 or (self.cascade and self.cascade.is_python_result()))
4631 def check_types(self, env, operand1, op, operand2):
4632 if not self.types_okay(operand1, op, operand2):
4633 error(self.pos, "Invalid types for '%s' (%s, %s)" %
4634 (self.operator, operand1.type, operand2.type))
4636 def types_okay(self, operand1, op, operand2):
4637 type1 = operand1.type
4638 type2 = operand2.type
4639 if type1.is_error or type2.is_error:
4640 return 1
4641 if type1.is_pyobject: # type2 will be, too
4642 return 1
4643 elif type1.is_ptr or type1.is_array:
4644 return type1.is_null_ptr or type2.is_null_ptr \
4645 or ((type2.is_ptr or type2.is_array)
4646 and type1.base_type.same_as(type2.base_type))
4647 elif ((type1.is_numeric and type2.is_numeric
4648 or type1.is_enum and (type1 is type2 or type2.is_int)
4649 or type1.is_int and type2.is_enum)
4650 and op not in ('is', 'is_not')):
4651 return 1
4652 else:
4653 return type1.is_cfunction and type1.is_cfunction and type1 == type2
4655 def generate_operation_code(self, code, result_code,
4656 operand1, op , operand2):
4657 if self.type is PyrexTypes.py_object_type:
4658 coerce_result = "__Pyx_PyBool_FromLong"
4659 else:
4660 coerce_result = ""
4661 if 'not' in op: negation = "!"
4662 else: negation = ""
4663 if op == 'in' or op == 'not_in':
4664 code.putln(
4665 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
4666 result_code,
4667 coerce_result,
4668 negation,
4669 operand2.py_result(),
4670 operand1.py_result(),
4671 code.error_goto_if_neg(result_code, self.pos)))
4672 elif (operand1.type.is_pyobject
4673 and op not in ('is', 'is_not')):
4674 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
4675 result_code,
4676 operand1.py_result(),
4677 operand2.py_result(),
4678 richcmp_constants[op],
4679 code.error_goto_if_null(result_code, self.pos)))
4680 code.put_gotref(result_code)
4681 else:
4682 type1 = operand1.type
4683 type2 = operand2.type
4684 if (type1.is_extension_type or type2.is_extension_type) \
4685 and not type1.same_as(type2):
4686 common_type = py_object_type
4687 elif type1.is_numeric:
4688 common_type = PyrexTypes.widest_numeric_type(type1, type2)
4689 else:
4690 common_type = type1
4691 code1 = operand1.result_as(common_type)
4692 code2 = operand2.result_as(common_type)
4693 code.putln("%s = %s(%s %s %s);" % (
4694 result_code,
4695 coerce_result,
4696 code1,
4697 self.c_operator(op),
4698 code2))
4700 def c_operator(self, op):
4701 if op == 'is':
4702 return "=="
4703 elif op == 'is_not':
4704 return "!="
4705 else:
4706 return op
4709 class PrimaryCmpNode(ExprNode, CmpNode):
4710 # Non-cascaded comparison or first comparison of
4711 # a cascaded sequence.
4712 #
4713 # operator string
4714 # operand1 ExprNode
4715 # operand2 ExprNode
4716 # cascade CascadedCmpNode
4718 # We don't use the subexprs mechanism, because
4719 # things here are too complicated for it to handle.
4720 # Instead, we override all the framework methods
4721 # which use it.
4723 child_attrs = ['operand1', 'operand2', 'cascade']
4725 cascade = None
4727 def calculate_constant_result(self):
4728 self.constant_result = self.calculate_cascaded_constant_result(
4729 self.operand1.constant_result)
4731 def compile_time_value(self, denv):
4732 operand1 = self.operand1.compile_time_value(denv)
4733 return self.cascaded_compile_time_value(operand1, denv)
4735 def analyse_types(self, env):
4736 self.operand1.analyse_types(env)
4737 self.operand2.analyse_types(env)
4738 if self.cascade:
4739 self.cascade.analyse_types(env, self.operand2)
4740 self.is_pycmp = self.is_python_comparison()
4741 if self.is_pycmp:
4742 self.coerce_operands_to_pyobjects(env)
4743 if self.has_int_operands():
4744 self.coerce_chars_to_ints(env)
4745 if self.cascade:
4746 self.operand2 = self.operand2.coerce_to_simple(env)
4747 self.cascade.coerce_cascaded_operands_to_temp(env)
4748 self.check_operand_types(env)
4749 if self.is_python_result():
4750 self.type = PyrexTypes.py_object_type
4751 else:
4752 self.type = PyrexTypes.c_bint_type
4753 cdr = self.cascade
4754 while cdr:
4755 cdr.type = self.type
4756 cdr = cdr.cascade
4757 if self.is_pycmp or self.cascade:
4758 self.is_temp = 1
4760 def check_operand_types(self, env):
4761 self.check_types(env,
4762 self.operand1, self.operator, self.operand2)
4763 if self.cascade:
4764 self.cascade.check_operand_types(env, self.operand2)
4766 def has_python_operands(self):
4767 return (self.operand1.type.is_pyobject
4768 or self.operand2.type.is_pyobject)
4770 def coerce_operands_to_pyobjects(self, env):
4771 self.operand1 = self.operand1.coerce_to_pyobject(env)
4772 self.operand2 = self.operand2.coerce_to_pyobject(env)
4773 if self.cascade:
4774 self.cascade.coerce_operands_to_pyobjects(env)
4776 def has_int_operands(self):
4777 return (self.operand1.type.is_int or self.operand2.type.is_int) \
4778 or (self.cascade and self.cascade.has_int_operands())
4780 def coerce_chars_to_ints(self, env):
4781 # coerce literal single-char strings to c chars
4782 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
4783 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
4784 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4785 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4786 if self.cascade:
4787 self.cascade.coerce_chars_to_ints(env)
4789 def check_const(self):
4790 self.operand1.check_const()
4791 self.operand2.check_const()
4792 if self.cascade:
4793 self.not_const()
4795 def calculate_result_code(self):
4796 return "(%s %s %s)" % (
4797 self.operand1.result(),
4798 self.c_operator(self.operator),
4799 self.operand2.result())
4801 def generate_evaluation_code(self, code):
4802 self.operand1.generate_evaluation_code(code)
4803 self.operand2.generate_evaluation_code(code)
4804 if self.is_temp:
4805 self.allocate_temp_result(code)
4806 self.generate_operation_code(code, self.result(),
4807 self.operand1, self.operator, self.operand2)
4808 if self.cascade:
4809 self.cascade.generate_evaluation_code(code,
4810 self.result(), self.operand2)
4811 self.operand1.generate_disposal_code(code)
4812 self.operand1.free_temps(code)
4813 self.operand2.generate_disposal_code(code)
4814 self.operand2.free_temps(code)
4816 def generate_subexpr_disposal_code(self, code):
4817 # If this is called, it is a non-cascaded cmp,
4818 # so only need to dispose of the two main operands.
4819 self.operand1.generate_disposal_code(code)
4820 self.operand2.generate_disposal_code(code)
4822 def free_subexpr_temps(self, code):
4823 # If this is called, it is a non-cascaded cmp,
4824 # so only need to dispose of the two main operands.
4825 self.operand1.free_temps(code)
4826 self.operand2.free_temps(code)
4828 def annotate(self, code):
4829 self.operand1.annotate(code)
4830 self.operand2.annotate(code)
4831 if self.cascade:
4832 self.cascade.annotate(code)
4835 class CascadedCmpNode(Node, CmpNode):
4836 # A CascadedCmpNode is not a complete expression node. It
4837 # hangs off the side of another comparison node, shares
4838 # its left operand with that node, and shares its result
4839 # with the PrimaryCmpNode at the head of the chain.
4840 #
4841 # operator string
4842 # operand2 ExprNode
4843 # cascade CascadedCmpNode
4845 child_attrs = ['operand2', 'cascade']
4847 cascade = None
4848 constant_result = constant_value_not_set # FIXME: where to calculate this?
4850 def analyse_types(self, env, operand1):
4851 self.operand2.analyse_types(env)
4852 if self.cascade:
4853 self.cascade.analyse_types(env, self.operand2)
4855 def check_operand_types(self, env, operand1):
4856 self.check_types(env,
4857 operand1, self.operator, self.operand2)
4858 if self.cascade:
4859 self.cascade.check_operand_types(env, self.operand2)
4861 def has_python_operands(self):
4862 return self.operand2.type.is_pyobject
4864 def coerce_operands_to_pyobjects(self, env):
4865 self.operand2 = self.operand2.coerce_to_pyobject(env)
4866 if self.cascade:
4867 self.cascade.coerce_operands_to_pyobjects(env)
4869 def has_int_operands(self):
4870 return self.operand2.type.is_int
4872 def coerce_chars_to_ints(self, env):
4873 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4874 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4876 def coerce_cascaded_operands_to_temp(self, env):
4877 if self.cascade:
4878 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
4879 self.operand2 = self.operand2.coerce_to_simple(env)
4880 self.cascade.coerce_cascaded_operands_to_temp(env)
4882 def generate_evaluation_code(self, code, result, operand1):
4883 if self.type.is_pyobject:
4884 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
4885 code.put_decref(result, self.type)
4886 else:
4887 code.putln("if (%s) {" % result)
4888 self.operand2.generate_evaluation_code(code)
4889 self.generate_operation_code(code, result,
4890 operand1, self.operator, self.operand2)
4891 if self.cascade:
4892 self.cascade.generate_evaluation_code(
4893 code, result, self.operand2)
4894 # Cascaded cmp result is always temp
4895 self.operand2.generate_disposal_code(code)
4896 self.operand2.free_temps(code)
4897 code.putln("}")
4899 def annotate(self, code):
4900 self.operand2.annotate(code)
4901 if self.cascade:
4902 self.cascade.annotate(code)
4905 binop_node_classes = {
4906 "or": BoolBinopNode,
4907 "and": BoolBinopNode,
4908 "|": IntBinopNode,
4909 "^": IntBinopNode,
4910 "&": IntBinopNode,
4911 "<<": IntBinopNode,
4912 ">>": IntBinopNode,
4913 "+": AddNode,
4914 "-": SubNode,
4915 "*": MulNode,
4916 "/": DivNode,
4917 "//": DivNode,
4918 "%": ModNode,
4919 "**": PowNode
4920 }
4922 def binop_node(pos, operator, operand1, operand2):
4923 # Construct binop node of appropriate class for
4924 # given operator.
4925 return binop_node_classes[operator](pos,
4926 operator = operator,
4927 operand1 = operand1,
4928 operand2 = operand2)
4930 #-------------------------------------------------------------------
4931 #
4932 # Coercion nodes
4933 #
4934 # Coercion nodes are special in that they are created during
4935 # the analyse_types phase of parse tree processing.
4936 # Their __init__ methods consequently incorporate some aspects
4937 # of that phase.
4938 #
4939 #-------------------------------------------------------------------
4941 class CoercionNode(ExprNode):
4942 # Abstract base class for coercion nodes.
4943 #
4944 # arg ExprNode node being coerced
4946 subexprs = ['arg']
4948 def __init__(self, arg):
4949 self.pos = arg.pos
4950 self.arg = arg
4951 if debug_coercion:
4952 print("%s Coercing %s" % (self, self.arg))
4954 def calculate_constant_result(self):
4955 # constant folding can break type coercion, so this is disabled
4956 pass
4958 def annotate(self, code):
4959 self.arg.annotate(code)
4960 if self.arg.type != self.type:
4961 file, line, col = self.pos
4962 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
4965 class CastNode(CoercionNode):
4966 # Wrap a node in a C type cast.
4968 def __init__(self, arg, new_type):
4969 CoercionNode.__init__(self, arg)
4970 self.type = new_type
4972 def calculate_result_code(self):
4973 return self.arg.result_as(self.type)
4975 def generate_result_code(self, code):
4976 self.arg.generate_result_code(code)
4979 class PyTypeTestNode(CoercionNode):
4980 # This node is used to check that a generic Python
4981 # object is an instance of a particular extension type.
4982 # This node borrows the result of its argument node.
4984 def __init__(self, arg, dst_type, env):
4985 # The arg is know to be a Python object, and
4986 # the dst_type is known to be an extension type.
4987 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
4988 CoercionNode.__init__(self, arg)
4989 self.type = dst_type
4990 self.result_ctype = arg.ctype()
4992 gil_check = CoercionNode._gil_check
4993 gil_message = "Python type test"
4995 def analyse_types(self, env):
4996 pass
4998 def result_in_temp(self):
4999 return self.arg.result_in_temp()
5001 def is_ephemeral(self):
5002 return self.arg.is_ephemeral()
5004 def calculate_constant_result(self):
5005 # FIXME
5006 pass
5008 def calculate_result_code(self):
5009 return self.arg.result()
5011 def generate_result_code(self, code):
5012 if self.type.typeobj_is_available():
5013 if not self.type.is_builtin_type:
5014 code.globalstate.use_utility_code(type_test_utility_code)
5015 code.putln(
5016 "if (!(%s)) %s" % (
5017 self.type.type_test_code(self.arg.py_result()),
5018 code.error_goto(self.pos)))
5019 else:
5020 error(self.pos, "Cannot test type of extern C class "
5021 "without type object name specification")
5023 def generate_post_assignment_code(self, code):
5024 self.arg.generate_post_assignment_code(code)
5026 def free_temps(self, code):
5027 self.arg.free_temps(code)
5030 class NoneCheckNode(CoercionNode):
5031 # This node is used to check that a Python object is not None and
5032 # raises an appropriate exception (as specified by the creating
5033 # transform).
5035 def __init__(self, arg, exception_type_cname, exception_message):
5036 CoercionNode.__init__(self, arg)
5037 self.type = arg.type
5038 self.result_ctype = arg.ctype()
5039 self.exception_type_cname = exception_type_cname
5040 self.exception_message = exception_message
5042 def analyse_types(self, env):
5043 pass
5045 def result_in_temp(self):
5046 return self.arg.result_in_temp()
5048 def calculate_result_code(self):
5049 return self.arg.result()
5051 def generate_result_code(self, code):
5052 code.putln(
5053 "if (unlikely(%s == Py_None)) {" % self.arg.result())
5054 code.putln('PyErr_SetString(%s, "%s"); %s ' % (
5055 self.exception_type_cname,
5056 StringEncoding.escape_byte_string(self.exception_message),
5057 code.error_goto(self.pos)))
5058 code.putln("}")
5060 def generate_post_assignment_code(self, code):
5061 self.arg.generate_post_assignment_code(code)
5063 def free_temps(self, code):
5064 self.arg.free_temps(code)
5067 class CoerceToPyTypeNode(CoercionNode):
5068 # This node is used to convert a C data type
5069 # to a Python object.
5071 def __init__(self, arg, env):
5072 CoercionNode.__init__(self, arg)
5073 self.type = py_object_type
5074 self.is_temp = 1
5075 if not arg.type.to_py_function or not arg.type.create_convert_utility_code(env):
5076 error(arg.pos,
5077 "Cannot convert '%s' to Python object" % arg.type)
5079 gil_message = "Converting to Python object"
5081 def coerce_to_boolean(self, env):
5082 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
5084 def coerce_to_integer(self, env):
5085 # If not already some C integer type, coerce to longint.
5086 if self.arg.type.is_int:
5087 return self.arg
5088 else:
5089 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
5091 def analyse_types(self, env):
5092 # The arg is always already analysed
5093 pass
5095 def generate_result_code(self, code):
5096 function = self.arg.type.to_py_function
5097 code.putln('%s = %s(%s); %s' % (
5098 self.result(),
5099 function,
5100 self.arg.result(),
5101 code.error_goto_if_null(self.result(), self.pos)))
5102 code.put_gotref(self.py_result())
5105 class CoerceFromPyTypeNode(CoercionNode):
5106 # This node is used to convert a Python object
5107 # to a C data type.
5109 def __init__(self, result_type, arg, env):
5110 CoercionNode.__init__(self, arg)
5111 self.type = result_type
5112 self.is_temp = 1
5113 if not result_type.from_py_function:
5114 error(arg.pos,
5115 "Cannot convert Python object to '%s'" % result_type)
5116 if self.type.is_string and self.arg.is_ephemeral():
5117 error(arg.pos,
5118 "Obtaining char * from temporary Python value")
5120 def analyse_types(self, env):
5121 # The arg is always already analysed
5122 pass
5124 def generate_result_code(self, code):
5125 function = self.type.from_py_function
5126 operand = self.arg.py_result()
5127 rhs = "%s(%s)" % (function, operand)
5128 if self.type.is_enum:
5129 rhs = typecast(self.type, c_long_type, rhs)
5130 code.putln('%s = %s; %s' % (
5131 self.result(),
5132 rhs,
5133 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
5134 if self.type.is_pyobject:
5135 code.put_gotref(self.py_result())
5138 class CoerceToBooleanNode(CoercionNode):
5139 # This node is used when a result needs to be used
5140 # in a boolean context.
5142 def __init__(self, arg, env):
5143 CoercionNode.__init__(self, arg)
5144 self.type = PyrexTypes.c_bint_type
5145 if arg.type.is_pyobject:
5146 self.is_temp = 1
5148 def gil_check(self, env):
5149 if self.arg.type.is_pyobject:
5150 self._gil_check(env)
5152 gil_message = "Truth-testing Python object"
5154 def check_const(self):
5155 if self.is_temp:
5156 self.not_const()
5157 self.arg.check_const()
5159 def calculate_result_code(self):
5160 return "(%s != 0)" % self.arg.result()
5162 def generate_result_code(self, code):
5163 if self.arg.type.is_pyobject:
5164 code.putln(
5165 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5166 self.result(),
5167 self.arg.py_result(),
5168 code.error_goto_if_neg(self.result(), self.pos)))
5171 class CoerceToTempNode(CoercionNode):
5172 # This node is used to force the result of another node
5173 # to be stored in a temporary. It is only used if the
5174 # argument node's result is not already in a temporary.
5176 def __init__(self, arg, env):
5177 CoercionNode.__init__(self, arg)
5178 self.type = self.arg.type
5179 self.is_temp = 1
5180 if self.type.is_pyobject:
5181 self.result_ctype = py_object_type
5183 gil_message = "Creating temporary Python reference"
5185 def analyse_types(self, env):
5186 # The arg is always already analysed
5187 pass
5189 def coerce_to_boolean(self, env):
5190 self.arg = self.arg.coerce_to_boolean(env)
5191 self.type = self.arg.type
5192 self.result_ctype = self.type
5193 return self
5195 def generate_result_code(self, code):
5196 #self.arg.generate_evaluation_code(code) # Already done
5197 # by generic generate_subexpr_evaluation_code!
5198 code.putln("%s = %s;" % (
5199 self.result(), self.arg.result_as(self.ctype())))
5200 if self.type.is_pyobject:
5201 code.put_incref(self.result(), self.ctype())
5204 class CloneNode(CoercionNode):
5205 # This node is employed when the result of another node needs
5206 # to be used multiple times. The argument node's result must
5207 # be in a temporary. This node "borrows" the result from the
5208 # argument node, and does not generate any evaluation or
5209 # disposal code for it. The original owner of the argument
5210 # node is responsible for doing those things.
5212 subexprs = [] # Arg is not considered a subexpr
5213 gil_check = None
5215 def __init__(self, arg):
5216 CoercionNode.__init__(self, arg)
5217 if hasattr(arg, 'type'):
5218 self.type = arg.type
5219 self.result_ctype = arg.result_ctype
5220 if hasattr(arg, 'entry'):
5221 self.entry = arg.entry
5223 def result(self):
5224 return self.arg.result()
5226 def analyse_types(self, env):
5227 self.type = self.arg.type
5228 self.result_ctype = self.arg.result_ctype
5229 self.is_temp = 1
5230 if hasattr(self.arg, 'entry'):
5231 self.entry = self.arg.entry
5233 def generate_evaluation_code(self, code):
5234 pass
5236 def generate_result_code(self, code):
5237 pass
5239 def generate_disposal_code(self, code):
5240 pass
5242 def free_temps(self, code):
5243 pass
5246 #------------------------------------------------------------------------------------
5247 #
5248 # Runtime support code
5249 #
5250 #------------------------------------------------------------------------------------
5252 get_name_interned_utility_code = UtilityCode(
5253 proto = """
5254 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
5255 """,
5256 impl = """
5257 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
5258 PyObject *result;
5259 result = PyObject_GetAttr(dict, name);
5260 if (!result)
5261 PyErr_SetObject(PyExc_NameError, name);
5262 return result;
5263 }
5264 """)
5266 #------------------------------------------------------------------------------------
5268 import_utility_code = UtilityCode(
5269 proto = """
5270 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
5271 """,
5272 impl = """
5273 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
5274 PyObject *__import__ = 0;
5275 PyObject *empty_list = 0;
5276 PyObject *module = 0;
5277 PyObject *global_dict = 0;
5278 PyObject *empty_dict = 0;
5279 PyObject *list;
5280 __import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
5281 if (!__import__)
5282 goto bad;
5283 if (from_list)
5284 list = from_list;
5285 else {
5286 empty_list = PyList_New(0);
5287 if (!empty_list)
5288 goto bad;
5289 list = empty_list;
5290 }
5291 global_dict = PyModule_GetDict(%(GLOBALS)s);
5292 if (!global_dict)
5293 goto bad;
5294 empty_dict = PyDict_New();
5295 if (!empty_dict)
5296 goto bad;
5297 module = PyObject_CallFunctionObjArgs(__import__,
5298 name, global_dict, empty_dict, list, NULL);
5299 bad:
5300 Py_XDECREF(empty_list);
5301 Py_XDECREF(__import__);
5302 Py_XDECREF(empty_dict);
5303 return module;
5304 }
5305 """ % {
5306 "BUILTINS": Naming.builtins_cname,
5307 "GLOBALS": Naming.module_cname,
5308 })
5310 #------------------------------------------------------------------------------------
5312 get_exception_utility_code = UtilityCode(
5313 proto = """
5314 static PyObject *__Pyx_GetExcValue(void); /*proto*/
5315 """,
5316 impl = """
5317 static PyObject *__Pyx_GetExcValue(void) {
5318 PyObject *type = 0, *value = 0, *tb = 0;
5319 PyObject *tmp_type, *tmp_value, *tmp_tb;
5320 PyObject *result = 0;
5321 PyThreadState *tstate = PyThreadState_Get();
5322 PyErr_Fetch(&type, &value, &tb);
5323 PyErr_NormalizeException(&type, &value, &tb);
5324 if (PyErr_Occurred())
5325 goto bad;
5326 if (!value) {
5327 value = Py_None;
5328 Py_INCREF(value);
5329 }
5330 tmp_type = tstate->exc_type;
5331 tmp_value = tstate->exc_value;
5332 tmp_tb = tstate->exc_traceback;
5333 tstate->exc_type = type;
5334 tstate->exc_value = value;
5335 tstate->exc_traceback = tb;
5336 /* Make sure tstate is in a consistent state when we XDECREF
5337 these objects (XDECREF may run arbitrary code). */
5338 Py_XDECREF(tmp_type);
5339 Py_XDECREF(tmp_value);
5340 Py_XDECREF(tmp_tb);
5341 result = value;
5342 Py_XINCREF(result);
5343 type = 0;
5344 value = 0;
5345 tb = 0;
5346 bad:
5347 Py_XDECREF(type);
5348 Py_XDECREF(value);
5349 Py_XDECREF(tb);
5350 return result;
5351 }
5352 """)
5354 #------------------------------------------------------------------------------------
5356 type_test_utility_code = UtilityCode(
5357 proto = """
5358 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
5359 """,
5360 impl = """
5361 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
5362 if (!type) {
5363 PyErr_Format(PyExc_SystemError, "Missing type object");
5364 return 0;
5365 }
5366 if (obj == Py_None || PyObject_TypeCheck(obj, type))
5367 return 1;
5368 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
5369 Py_TYPE(obj)->tp_name, type->tp_name);
5370 return 0;
5371 }
5372 """)
5374 #------------------------------------------------------------------------------------
5376 create_class_utility_code = UtilityCode(
5377 proto = """
5378 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
5379 """,
5380 impl = """
5381 static PyObject *__Pyx_CreateClass(
5382 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
5383 {
5384 PyObject *py_modname;
5385 PyObject *result = 0;
5387 #if PY_MAJOR_VERSION < 3
5388 py_modname = PyString_FromString(modname);
5389 #else
5390 py_modname = PyUnicode_FromString(modname);
5391 #endif
5392 if (!py_modname)
5393 goto bad;
5394 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
5395 goto bad;
5396 #if PY_MAJOR_VERSION < 3
5397 result = PyClass_New(bases, dict, name);
5398 #else
5399 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
5400 #endif
5401 bad:
5402 Py_XDECREF(py_modname);
5403 return result;
5404 }
5405 """)
5407 #------------------------------------------------------------------------------------
5409 cpp_exception_utility_code = UtilityCode(
5410 proto = """
5411 #ifndef __Pyx_CppExn2PyErr
5412 static void __Pyx_CppExn2PyErr() {
5413 try {
5414 if (PyErr_Occurred())
5415 ; // let the latest Python exn pass through and ignore the current one
5416 else
5417 throw;
5418 } catch (const std::out_of_range& exn) {
5419 // catch out_of_range explicitly so the proper Python exn may be raised
5420 PyErr_SetString(PyExc_IndexError, exn.what());
5421 } catch (const std::exception& exn) {
5422 PyErr_SetString(PyExc_RuntimeError, exn.what());
5423 }
5424 catch (...)
5425 {
5426 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
5427 }
5428 }
5429 #endif
5430 """,
5431 impl = ""
5432 )
5434 #------------------------------------------------------------------------------------
5436 # If the is_unsigned flag is set, we need to do some extra work to make
5437 # sure the index doesn't become negative.
5439 getitem_int_utility_code = UtilityCode(
5440 proto = """
5442 static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
5443 PyObject *r;
5444 if (!j) return NULL;
5445 r = PyObject_GetItem(o, j);
5446 Py_DECREF(j);
5447 return r;
5448 }
5450 """ + ''.join([
5451 """
5452 #define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5453 __Pyx_GetItemInt_%(type)s_Fast(o, i, size <= sizeof(long)) : \\
5454 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
5456 static INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5457 if (likely(o != Py_None)) {
5458 if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
5459 PyObject *r = Py%(type)s_GET_ITEM(o, i);
5460 Py_INCREF(r);
5461 return r;
5462 }
5463 else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
5464 PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
5465 Py_INCREF(r);
5466 return r;
5467 }
5468 }
5469 return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
5470 }
5471 """ % {'type' : type_name} for type_name in ('List', 'Tuple')
5472 ]) + """
5474 #define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5475 __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \\
5476 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
5478 static INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5479 PyObject *r;
5480 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
5481 r = PyList_GET_ITEM(o, i);
5482 Py_INCREF(r);
5483 }
5484 else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
5485 r = PyTuple_GET_ITEM(o, i);
5486 Py_INCREF(r);
5487 }
5488 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
5489 r = PySequence_GetItem(o, i);
5490 }
5491 else {
5492 r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
5493 }
5494 return r;
5495 }
5496 """,
5497 impl = """
5498 """)
5502 #------------------------------------------------------------------------------------
5504 setitem_int_utility_code = UtilityCode(
5505 proto = """
5506 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5507 __Pyx_SetItemInt_Fast(o, i, v, size <= sizeof(long)) : \\
5508 __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
5510 static INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
5511 int r;
5512 if (!j) return -1;
5513 r = PyObject_SetItem(o, j, v);
5514 Py_DECREF(j);
5515 return r;
5516 }
5518 static INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int fits_long) {
5519 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
5520 Py_INCREF(v);
5521 Py_DECREF(PyList_GET_ITEM(o, i));
5522 PyList_SET_ITEM(o, i, v);
5523 return 1;
5524 }
5525 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
5526 return PySequence_SetItem(o, i, v);
5527 else {
5528 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
5529 return __Pyx_SetItemInt_Generic(o, j, v);
5530 }
5531 }
5532 """,
5533 impl = """
5534 """)
5536 #------------------------------------------------------------------------------------
5538 delitem_int_utility_code = UtilityCode(
5539 proto = """
5540 #define __Pyx_DelItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5541 __Pyx_DelItemInt_Fast(o, i, size <= sizeof(long)) : \\
5542 __Pyx_DelItem_Generic(o, to_py_func(i)))
5544 static INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
5545 int r;
5546 if (!j) return -1;
5547 r = PyObject_DelItem(o, j);
5548 Py_DECREF(j);
5549 return r;
5550 }
5552 static INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5553 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
5554 return PySequence_DelItem(o, i);
5555 else {
5556 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
5557 return __Pyx_DelItem_Generic(o, j);
5558 }
5559 }
5560 """,
5561 impl = """
5562 """)
5564 #------------------------------------------------------------------------------------
5566 raise_noneattr_error_utility_code = UtilityCode(
5567 proto = """
5568 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
5569 """,
5570 impl = '''
5571 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
5572 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
5573 }
5574 ''')
5576 raise_noneindex_error_utility_code = UtilityCode(
5577 proto = """
5578 static INLINE void __Pyx_RaiseNoneIndexingError(void);
5579 """,
5580 impl = '''
5581 static INLINE void __Pyx_RaiseNoneIndexingError(void) {
5582 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
5583 }
5584 ''')
5586 raise_none_iter_error_utility_code = UtilityCode(
5587 proto = """
5588 static INLINE void __Pyx_RaiseNoneNotIterableError(void);
5589 """,
5590 impl = '''
5591 static INLINE void __Pyx_RaiseNoneNotIterableError(void) {
5592 PyErr_SetString(PyExc_TypeError, "'NoneType' object is iterable");
5593 }
5594 ''')
5596 raise_too_many_values_to_unpack = UtilityCode(
5597 proto = """
5598 static INLINE void __Pyx_RaiseTooManyValuesError(void);
5599 """,
5600 impl = '''
5601 static INLINE void __Pyx_RaiseTooManyValuesError(void) {
5602 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
5603 }
5604 ''')
5606 raise_need_more_values_to_unpack = UtilityCode(
5607 proto = """
5608 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
5609 """,
5610 impl = '''
5611 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
5612 PyErr_Format(PyExc_ValueError,
5613 #if PY_VERSION_HEX < 0x02050000
5614 "need more than %d value%s to unpack", (int)index,
5615 #else
5616 "need more than %zd value%s to unpack", index,
5617 #endif
5618 (index == 1) ? "" : "s");
5619 }
5620 ''')
5622 #------------------------------------------------------------------------------------
5624 tuple_unpacking_error_code = UtilityCode(
5625 proto = """
5626 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
5627 """,
5628 impl = """
5629 static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
5630 if (t == Py_None) {
5631 __Pyx_RaiseNoneNotIterableError();
5632 } else if (PyTuple_GET_SIZE(t) < index) {
5633 __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
5634 } else {
5635 __Pyx_RaiseTooManyValuesError();
5636 }
5637 }
5638 """,
5639 requires = [raise_none_iter_error_utility_code,
5640 raise_need_more_values_to_unpack,
5641 raise_too_many_values_to_unpack]
5642 )
5644 unpacking_utility_code = UtilityCode(
5645 proto = """
5646 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
5647 static int __Pyx_EndUnpack(PyObject *); /*proto*/
5648 """,
5649 impl = """
5650 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
5651 PyObject *item;
5652 if (!(item = PyIter_Next(iter))) {
5653 if (!PyErr_Occurred()) {
5654 __Pyx_RaiseNeedMoreValuesError(index);
5655 }
5656 }
5657 return item;
5658 }
5660 static int __Pyx_EndUnpack(PyObject *iter) {
5661 PyObject *item;
5662 if ((item = PyIter_Next(iter))) {
5663 Py_DECREF(item);
5664 __Pyx_RaiseTooManyValuesError();
5665 return -1;
5666 }
5667 else if (!PyErr_Occurred())
5668 return 0;
5669 else
5670 return -1;
5671 }
5672 """,
5673 requires = [raise_need_more_values_to_unpack,
5674 raise_too_many_values_to_unpack]
5675 )
5678 #------------------------------------------------------------------------------------
5680 int_pow_utility_code = UtilityCode(
5681 proto="""
5682 static INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
5683 """,
5684 impl="""
5685 static INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
5686 %(type)s t = b;
5687 switch (e) {
5688 case 3:
5689 t *= b;
5690 case 2:
5691 t *= b;
5692 case 1:
5693 return t;
5694 case 0:
5695 return 1;
5696 }
5697 if (unlikely(e<0)) return 0;
5698 t = 1;
5699 while (likely(e)) {
5700 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
5701 b *= b;
5702 e >>= 1;
5703 }
5704 return t;
5705 }
5706 """)
5708 # ------------------------------ Division ------------------------------------
5710 div_int_utility_code = UtilityCode(
5711 proto="""
5712 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
5713 """,
5714 impl="""
5715 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
5716 %(type)s q = a / b;
5717 %(type)s r = a - q*b;
5718 q -= ((r != 0) & ((r ^ b) < 0));
5719 return q;
5720 }
5721 """)
5723 mod_int_utility_code = UtilityCode(
5724 proto="""
5725 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
5726 """,
5727 impl="""
5728 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
5729 %(type)s r = a %% b;
5730 r += ((r != 0) & ((r ^ b) < 0)) * b;
5731 return r;
5732 }
5733 """)
5735 mod_float_utility_code = UtilityCode(
5736 proto="""
5737 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
5738 """,
5739 impl="""
5740 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
5741 %(type)s r = fmod%(math_h_modifier)s(a, b);
5742 r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
5743 return r;
5744 }
5745 """)
5747 cdivision_warning_utility_code = UtilityCode(
5748 proto="""
5749 static int __Pyx_cdivision_warning(void); /* proto */
5750 """,
5751 impl="""
5752 static int __Pyx_cdivision_warning(void) {
5753 return PyErr_WarnExplicit(PyExc_RuntimeWarning,
5754 "division with oppositely signed operands, C and Python semantics differ",
5755 %(FILENAME)s,
5756 %(LINENO)s,
5757 %(MODULENAME)s,
5758 NULL);
5759 }
5760 """ % {
5761 'FILENAME': Naming.filename_cname,
5762 'MODULENAME': Naming.modulename_cname,
5763 'LINENO': Naming.lineno_cname,
5764 })
