Cython has moved to github.
cython-devel
view Cython/Compiler/ExprNodes.py @ 2299:a3ad25325fe4
fix __future__ division semantics for constant expressions and C integers
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Wed Jul 08 21:13:14 2009 +0200 (2 years ago) |
| parents | 67a370779b96 |
| children | 495a6e5911e3 |
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 Code import UtilityCode
10 import StringEncoding
11 import Naming
12 import Nodes
13 from Nodes import Node
14 import PyrexTypes
15 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
16 from Builtin import list_type, tuple_type, set_type, dict_type, unicode_type, bytes_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 nogil_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_error()
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 elif (dst_type.is_complex
507 and src_type != dst_type
508 and dst_type.assignable_from(src_type)
509 and not env.directives['c99_complex']):
510 src = CoerceToComplexNode(src, dst_type, env)
511 else: # neither src nor dst are py types
512 # Added the string comparison, since for c types that
513 # is enough, but Cython gets confused when the types are
514 # in different pxi files.
515 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
516 error(self.pos, "Cannot assign type '%s' to '%s'" %
517 (src.type, dst_type))
518 return src
520 def coerce_to_pyobject(self, env):
521 return self.coerce_to(PyrexTypes.py_object_type, env)
523 def coerce_to_boolean(self, env):
524 # Coerce result to something acceptable as
525 # a boolean value.
526 type = self.type
527 if type.is_pyobject or type.is_ptr or type.is_float:
528 return CoerceToBooleanNode(self, env)
529 else:
530 if not type.is_int and not type.is_error:
531 error(self.pos,
532 "Type '%s' not acceptable as a boolean" % type)
533 return self
535 def coerce_to_integer(self, env):
536 # If not already some C integer type, coerce to longint.
537 if self.type.is_int:
538 return self
539 else:
540 return self.coerce_to(PyrexTypes.c_long_type, env)
542 def coerce_to_temp(self, env):
543 # Ensure that the result is in a temporary.
544 if self.result_in_temp():
545 return self
546 else:
547 return CoerceToTempNode(self, env)
549 def coerce_to_simple(self, env):
550 # Ensure that the result is simple (see is_simple).
551 if self.is_simple():
552 return self
553 else:
554 return self.coerce_to_temp(env)
556 def is_simple(self):
557 # A node is simple if its result is something that can
558 # be referred to without performing any operations, e.g.
559 # a constant, local var, C global var, struct member
560 # reference, or temporary.
561 return self.result_in_temp()
563 def as_cython_attribute(self):
564 return None
566 class AtomicExprNode(ExprNode):
567 # Abstract base class for expression nodes which have
568 # no sub-expressions.
570 subexprs = []
572 # Override to optimize -- we know we have no children
573 def generate_subexpr_evaluation_code(self, code):
574 pass
575 def generate_subexpr_disposal_code(self, code):
576 pass
578 class PyConstNode(AtomicExprNode):
579 # Abstract base class for constant Python values.
581 is_literal = 1
583 def is_simple(self):
584 return 1
586 def analyse_types(self, env):
587 self.type = py_object_type
589 def calculate_result_code(self):
590 return self.value
592 def generate_result_code(self, code):
593 pass
596 class NoneNode(PyConstNode):
597 # The constant value None
599 value = "Py_None"
601 constant_result = None
603 nogil_check = None
605 def compile_time_value(self, denv):
606 return None
608 class EllipsisNode(PyConstNode):
609 # '...' in a subscript list.
611 value = "Py_Ellipsis"
613 constant_result = Ellipsis
615 def compile_time_value(self, denv):
616 return Ellipsis
619 class ConstNode(AtomicExprNode):
620 # Abstract base type for literal constant nodes.
621 #
622 # value string C code fragment
624 is_literal = 1
625 nogil_check = None
627 def is_simple(self):
628 return 1
630 def analyse_types(self, env):
631 pass # Types are held in class variables
633 def check_const(self):
634 pass
636 def get_constant_c_result_code(self):
637 return self.calculate_result_code()
639 def calculate_result_code(self):
640 return str(self.value)
642 def generate_result_code(self, code):
643 pass
646 class BoolNode(ConstNode):
647 type = PyrexTypes.c_bint_type
648 # The constant value True or False
650 def calculate_constant_result(self):
651 self.constant_result = self.value
653 def compile_time_value(self, denv):
654 return self.value
656 def calculate_result_code(self):
657 return str(int(self.value))
660 class NullNode(ConstNode):
661 type = PyrexTypes.c_null_ptr_type
662 value = "NULL"
663 constant_result = 0
665 def get_constant_c_result_code(self):
666 return self.value
669 class CharNode(ConstNode):
670 type = PyrexTypes.c_char_type
672 def calculate_constant_result(self):
673 self.constant_result = ord(self.value)
675 def compile_time_value(self, denv):
676 return ord(self.value)
678 def calculate_result_code(self):
679 return "'%s'" % StringEncoding.escape_character(self.value)
682 class IntNode(ConstNode):
684 # unsigned "" or "U"
685 # longness "" or "L" or "LL"
687 unsigned = ""
688 longness = ""
689 type = PyrexTypes.c_long_type
691 def coerce_to(self, dst_type, env):
692 if dst_type.is_numeric and not dst_type.is_complex:
693 self.type = PyrexTypes.c_long_type
694 return self
695 # Arrange for a Python version of the number to be pre-allocated
696 # when coercing to a Python type.
697 if dst_type.is_pyobject:
698 self.type = PyrexTypes.py_object_type
699 # We still need to perform normal coerce_to processing on the
700 # result, because we might be coercing to an extension type,
701 # in which case a type test node will be needed.
702 return ConstNode.coerce_to(self, dst_type, env)
704 def coerce_to_boolean(self, env):
705 self.type = PyrexTypes.c_bint_type
706 return self
708 def generate_evaluation_code(self, code):
709 if self.type.is_pyobject:
710 self.result_code = code.get_py_num(self.value, self.longness)
711 else:
712 self.result_code = self.get_constant_c_result_code()
714 def get_constant_c_result_code(self):
715 return str(self.value) + self.unsigned + self.longness
717 def calculate_result_code(self):
718 return self.result_code
720 def calculate_constant_result(self):
721 self.constant_result = int(self.value, 0)
723 def compile_time_value(self, denv):
724 return int(self.value, 0)
727 class FloatNode(ConstNode):
728 type = PyrexTypes.c_double_type
730 def calculate_constant_result(self):
731 self.constant_result = float(self.value)
733 def compile_time_value(self, denv):
734 return float(self.value)
736 def calculate_result_code(self):
737 strval = repr(float(self.value))
738 if strval == 'nan':
739 return "(Py_HUGE_VAL * 0)"
740 elif strval == 'inf':
741 return "Py_HUGE_VAL"
742 elif strval == '-inf':
743 return "(-Py_HUGE_VAL)"
744 else:
745 return strval
748 class StringNode(ConstNode):
749 type = PyrexTypes.c_char_ptr_type
751 def compile_time_value(self, denv):
752 return self.value
754 def analyse_as_type(self, env):
755 type = PyrexTypes.parse_basic_type(self.value)
756 if type is not None:
757 return type
758 from TreeFragment import TreeFragment
759 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
760 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
761 sizeof_node = declaration.root.stats[0].expr
762 sizeof_node.analyse_types(env)
763 if isinstance(sizeof_node, SizeofTypeNode):
764 return sizeof_node.arg_type
766 def coerce_to(self, dst_type, env):
767 if dst_type == PyrexTypes.c_char_ptr_type:
768 self.type = PyrexTypes.c_char_ptr_type
769 return self
771 if dst_type.is_int:
772 if not self.type.is_pyobject and len(self.value) == 1:
773 return CharNode(self.pos, value=self.value)
774 else:
775 error(self.pos, "Only single-character byte strings can be coerced into ints.")
776 return self
777 # Arrange for a Python version of the string to be pre-allocated
778 # when coercing to a Python type.
779 if dst_type.is_pyobject and not self.type.is_pyobject:
780 node = self.as_py_string_node(env)
781 else:
782 node = self
783 # We still need to perform normal coerce_to processing on the
784 # result, because we might be coercing to an extension type,
785 # in which case a type test node will be needed.
786 return ConstNode.coerce_to(node, dst_type, env)
788 def as_py_string_node(self, env):
789 # Return a new StringNode with the same value as this node
790 # but whose type is a Python type instead of a C type.
791 return StringNode(self.pos, value = self.value, type = py_object_type)
793 def generate_evaluation_code(self, code):
794 if self.type.is_pyobject:
795 self.result_code = code.get_py_string_const(self.value)
796 else:
797 self.result_code = code.get_string_const(self.value)
799 def get_constant_c_result_code(self):
800 return None # FIXME
802 def calculate_result_code(self):
803 return self.result_code
806 class UnicodeNode(PyConstNode):
807 type = unicode_type
809 def coerce_to(self, dst_type, env):
810 if dst_type.is_pyobject:
811 return self
812 else:
813 error(self.pos, "Unicode objects do not support coercion to C types.")
814 return self
816 def generate_evaluation_code(self, code):
817 if self.type.is_pyobject:
818 self.result_code = code.get_py_string_const(self.value)
819 else:
820 self.result_code = code.get_string_const(self.value)
822 def calculate_result_code(self):
823 return self.result_code
825 def compile_time_value(self, env):
826 return self.value
829 class IdentifierStringNode(ConstNode):
830 # A Python string that behaves like an identifier, e.g. for
831 # keyword arguments in a call, or for imported names
832 type = PyrexTypes.py_object_type
834 def generate_evaluation_code(self, code):
835 if self.type.is_pyobject:
836 self.result_code = code.get_py_string_const(self.value, True)
837 else:
838 self.result_code = code.get_string_const(self.value)
840 def get_constant_c_result_code(self):
841 return None
843 def calculate_result_code(self):
844 return self.result_code
847 class LongNode(AtomicExprNode):
848 # Python long integer literal
849 #
850 # value string
852 def calculate_constant_result(self):
853 self.constant_result = long(self.value)
855 def compile_time_value(self, denv):
856 return long(self.value)
858 def analyse_types(self, env):
859 self.type = py_object_type
860 self.is_temp = 1
862 gil_message = "Constructing Python long int"
864 def generate_result_code(self, code):
865 code.putln(
866 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
867 self.result(),
868 self.value,
869 code.error_goto_if_null(self.result(), self.pos)))
870 code.put_gotref(self.py_result())
873 class ImagNode(AtomicExprNode):
874 # Imaginary number literal
875 #
876 # value float imaginary part
878 type = PyrexTypes.c_double_complex_type
880 def calculate_constant_result(self):
881 self.constant_result = complex(0.0, self.value)
883 def compile_time_value(self, denv):
884 return complex(0.0, self.value)
886 def analyse_types(self, env):
887 self.type.create_declaration_utility_code(env)
889 def coerce_to(self, dst_type, env):
890 # Arrange for a Python version of the number to be pre-allocated
891 # when coercing to a Python type.
892 if dst_type.is_pyobject:
893 self.is_temp = 1
894 self.type = PyrexTypes.py_object_type
895 # We still need to perform normal coerce_to processing on the
896 # result, because we might be coercing to an extension type,
897 # in which case a type test node will be needed.
898 return AtomicExprNode.coerce_to(self, dst_type, env)
900 gil_message = "Constructing complex number"
902 def calculate_result_code(self):
903 if self.type.is_pyobject:
904 return self.result()
905 elif self.c99_complex:
906 return "%rj" % float(self.value)
907 else:
908 return "%s(0, %r)" % (self.type.from_parts, float(self.value))
910 def generate_result_code(self, code):
911 if self.type.is_pyobject:
912 code.putln(
913 "%s = PyComplex_FromDoubles(0.0, %r); %s" % (
914 self.result(),
915 float(self.value),
916 code.error_goto_if_null(self.result(), self.pos)))
917 code.put_gotref(self.py_result())
918 else:
919 self.c99_complex = code.globalstate.directives['c99_complex']
923 class NameNode(AtomicExprNode):
924 # Reference to a local or global variable name.
925 #
926 # name string Python name of the variable
927 # entry Entry Symbol table entry
928 # type_entry Entry For extension type names, the original type entry
930 is_name = True
931 is_cython_module = False
932 cython_attribute = None
933 lhs_of_first_assignment = False
934 is_used_as_rvalue = 0
935 entry = None
936 type_entry = None
938 def create_analysed_rvalue(pos, env, entry):
939 node = NameNode(pos)
940 node.analyse_types(env, entry=entry)
941 return node
943 def as_cython_attribute(self):
944 return self.cython_attribute
946 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
948 def compile_time_value(self, denv):
949 try:
950 return denv.lookup(self.name)
951 except KeyError:
952 error(self.pos, "Compile-time name '%s' not defined" % self.name)
954 def get_constant_c_result_code(self):
955 if not self.entry or self.entry.type.is_pyobject:
956 return None
957 return self.entry.cname
959 def coerce_to(self, dst_type, env):
960 # If coercing to a generic pyobject and this is a builtin
961 # C function with a Python equivalent, manufacture a NameNode
962 # referring to the Python builtin.
963 #print "NameNode.coerce_to:", self.name, dst_type ###
964 if dst_type is py_object_type:
965 entry = self.entry
966 if entry and entry.is_cfunction:
967 var_entry = entry.as_variable
968 if var_entry:
969 if var_entry.is_builtin and Options.cache_builtins:
970 var_entry = env.declare_builtin(var_entry.name, self.pos)
971 node = NameNode(self.pos, name = self.name)
972 node.entry = var_entry
973 node.analyse_rvalue_entry(env)
974 return node
975 return super(NameNode, self).coerce_to(dst_type, env)
977 def analyse_as_module(self, env):
978 # Try to interpret this as a reference to a cimported module.
979 # Returns the module scope, or None.
980 entry = self.entry
981 if not entry:
982 entry = env.lookup(self.name)
983 if entry and entry.as_module:
984 return entry.as_module
985 return None
987 def analyse_as_type(self, env):
988 if self.cython_attribute:
989 type = PyrexTypes.parse_basic_type(self.cython_attribute)
990 else:
991 type = PyrexTypes.parse_basic_type(self.name)
992 if type:
993 return type
994 entry = self.entry
995 if not entry:
996 entry = env.lookup(self.name)
997 if entry and entry.is_type:
998 return entry.type
999 else:
1000 return None
1002 def analyse_as_extension_type(self, env):
1003 # Try to interpret this as a reference to an extension type.
1004 # Returns the extension type, or None.
1005 entry = self.entry
1006 if not entry:
1007 entry = env.lookup(self.name)
1008 if entry and entry.is_type and entry.type.is_extension_type:
1009 return entry.type
1010 else:
1011 return None
1013 def analyse_target_declaration(self, env):
1014 if not self.entry:
1015 self.entry = env.lookup_here(self.name)
1016 if not self.entry:
1017 self.entry = env.declare_var(self.name, py_object_type, self.pos)
1018 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1019 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1020 if self.entry.is_declared_generic:
1021 self.result_ctype = py_object_type
1023 def analyse_types(self, env):
1024 if self.entry is None:
1025 self.entry = env.lookup(self.name)
1026 if not self.entry:
1027 self.entry = env.declare_builtin(self.name, self.pos)
1028 if not self.entry:
1029 self.type = PyrexTypes.error_type
1030 return
1031 entry = self.entry
1032 if entry:
1033 entry.used = 1
1034 if entry.type.is_buffer:
1035 import Buffer
1036 Buffer.used_buffer_aux_vars(entry)
1037 if entry.utility_code:
1038 env.use_utility_code(entry.utility_code)
1039 self.analyse_rvalue_entry(env)
1041 def analyse_target_types(self, env):
1042 self.analyse_entry(env)
1043 if not self.is_lvalue():
1044 error(self.pos, "Assignment to non-lvalue '%s'"
1045 % self.name)
1046 self.type = PyrexTypes.error_type
1047 self.entry.used = 1
1048 if self.entry.type.is_buffer:
1049 import Buffer
1050 Buffer.used_buffer_aux_vars(self.entry)
1052 def analyse_rvalue_entry(self, env):
1053 #print "NameNode.analyse_rvalue_entry:", self.name ###
1054 #print "Entry:", self.entry.__dict__ ###
1055 self.analyse_entry(env)
1056 entry = self.entry
1057 if entry.is_declared_generic:
1058 self.result_ctype = py_object_type
1059 if entry.is_pyglobal or entry.is_builtin:
1060 if Options.cache_builtins and entry.is_builtin:
1061 self.is_temp = 0
1062 else:
1063 self.is_temp = 1
1064 self.is_used_as_rvalue = 1
1065 env.use_utility_code(get_name_interned_utility_code)
1067 def nogil_check(self, env):
1068 if self.is_used_as_rvalue:
1069 entry = self.entry
1070 if entry.is_builtin:
1071 # if not Options.cache_builtins: # cached builtins are ok
1072 self.gil_error()
1073 elif entry.is_pyglobal:
1074 self.gil_error()
1076 gil_message = "Accessing Python global or builtin"
1078 def analyse_entry(self, env):
1079 #print "NameNode.analyse_entry:", self.name ###
1080 self.check_identifier_kind()
1081 entry = self.entry
1082 type = entry.type
1083 self.type = type
1085 def check_identifier_kind(self):
1086 # Check that this is an appropriate kind of name for use in an
1087 # expression. Also finds the variable entry associated with
1088 # an extension type.
1089 entry = self.entry
1090 if entry.is_type and entry.type.is_extension_type:
1091 self.type_entry = entry
1092 if not (entry.is_const or entry.is_variable
1093 or entry.is_builtin or entry.is_cfunction):
1094 if self.entry.as_variable:
1095 self.entry = self.entry.as_variable
1096 else:
1097 error(self.pos,
1098 "'%s' is not a constant, variable or function identifier" % self.name)
1100 def is_simple(self):
1101 # If it's not a C variable, it'll be in a temp.
1102 return 1
1104 def calculate_target_results(self, env):
1105 pass
1107 def check_const(self):
1108 entry = self.entry
1109 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1110 self.not_const()
1112 def check_const_addr(self):
1113 entry = self.entry
1114 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1115 self.addr_not_const()
1117 def is_lvalue(self):
1118 return self.entry.is_variable and \
1119 not self.entry.type.is_array and \
1120 not self.entry.is_readonly
1122 def is_ephemeral(self):
1123 # Name nodes are never ephemeral, even if the
1124 # result is in a temporary.
1125 return 0
1127 def calculate_result_code(self):
1128 entry = self.entry
1129 if not entry:
1130 return "<error>" # There was an error earlier
1131 return entry.cname
1133 def generate_result_code(self, code):
1134 assert hasattr(self, 'entry')
1135 entry = self.entry
1136 if entry is None:
1137 return # There was an error earlier
1138 if entry.is_builtin and Options.cache_builtins:
1139 return # Lookup already cached
1140 elif entry.is_pyglobal or entry.is_builtin:
1141 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1142 interned_cname = code.intern_identifier(self.entry.name)
1143 if entry.is_builtin:
1144 namespace = Naming.builtins_cname
1145 else: # entry.is_pyglobal
1146 namespace = entry.scope.namespace_cname
1147 code.putln(
1148 '%s = __Pyx_GetName(%s, %s); %s' % (
1149 self.result(),
1150 namespace,
1151 interned_cname,
1152 code.error_goto_if_null(self.result(), self.pos)))
1153 code.put_gotref(self.py_result())
1155 elif entry.is_local and False:
1156 # control flow not good enough yet
1157 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1158 if assigned is False:
1159 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1160 elif not Options.init_local_none and assigned is None:
1161 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
1162 (entry.cname, entry.name, code.error_goto(self.pos)))
1163 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1165 def generate_assignment_code(self, rhs, code):
1166 #print "NameNode.generate_assignment_code:", self.name ###
1167 entry = self.entry
1168 if entry is None:
1169 return # There was an error earlier
1171 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1172 and not self.lhs_of_first_assignment):
1173 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1175 # is_pyglobal seems to be True for module level-globals only.
1176 # We use this to access class->tp_dict if necessary.
1177 if entry.is_pyglobal:
1178 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1179 interned_cname = code.intern_identifier(self.entry.name)
1180 namespace = self.entry.scope.namespace_cname
1181 if entry.is_member:
1182 # if the entry is a member we have to cheat: SetAttr does not work
1183 # on types, so we create a descriptor which is then added to tp_dict
1184 code.put_error_if_neg(self.pos,
1185 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1186 namespace,
1187 interned_cname,
1188 rhs.py_result()))
1189 rhs.generate_disposal_code(code)
1190 rhs.free_temps(code)
1191 # in Py2.6+, we need to invalidate the method cache
1192 code.putln("PyType_Modified(%s);" %
1193 entry.scope.parent_type.typeptr_cname)
1194 else:
1195 code.put_error_if_neg(self.pos,
1196 'PyObject_SetAttr(%s, %s, %s)' % (
1197 namespace,
1198 interned_cname,
1199 rhs.py_result()))
1200 if debug_disposal_code:
1201 print("NameNode.generate_assignment_code:")
1202 print("...generating disposal code for %s" % rhs)
1203 rhs.generate_disposal_code(code)
1204 rhs.free_temps(code)
1205 else:
1206 if self.type.is_buffer:
1207 # Generate code for doing the buffer release/acquisition.
1208 # This might raise an exception in which case the assignment (done
1209 # below) will not happen.
1210 #
1211 # The reason this is not in a typetest-like node is because the
1212 # variables that the acquired buffer info is stored to is allocated
1213 # per entry and coupled with it.
1214 self.generate_acquire_buffer(rhs, code)
1216 if self.type.is_pyobject:
1217 rhs.make_owned_reference(code)
1218 #print "NameNode.generate_assignment_code: to", self.name ###
1219 #print "...from", rhs ###
1220 #print "...LHS type", self.type, "ctype", self.ctype() ###
1221 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1222 if entry.is_cglobal:
1223 code.put_gotref(self.py_result())
1224 if not self.lhs_of_first_assignment:
1225 if entry.is_local and not Options.init_local_none:
1226 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1227 if initalized is True:
1228 code.put_decref(self.result(), self.ctype())
1229 elif initalized is None:
1230 code.put_xdecref(self.result(), self.ctype())
1231 else:
1232 code.put_decref(self.result(), self.ctype())
1233 if entry.is_cglobal:
1234 code.put_giveref(rhs.py_result())
1235 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1236 if debug_disposal_code:
1237 print("NameNode.generate_assignment_code:")
1238 print("...generating post-assignment code for %s" % rhs)
1239 rhs.generate_post_assignment_code(code)
1240 rhs.free_temps(code)
1242 def generate_acquire_buffer(self, rhs, code):
1243 # rhstmp is only used in case the rhs is a complicated expression leading to
1244 # the object, to avoid repeating the same C expression for every reference
1245 # to the rhs. It does NOT hold a reference.
1246 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1247 if pretty_rhs:
1248 rhstmp = rhs.result_as(self.ctype())
1249 else:
1250 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1251 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1253 buffer_aux = self.entry.buffer_aux
1254 bufstruct = buffer_aux.buffer_info_var.cname
1255 import Buffer
1256 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1257 is_initialized=not self.lhs_of_first_assignment,
1258 pos=self.pos, code=code)
1260 if not pretty_rhs:
1261 code.putln("%s = 0;" % rhstmp)
1262 code.funcstate.release_temp(rhstmp)
1264 def generate_deletion_code(self, code):
1265 if self.entry is None:
1266 return # There was an error earlier
1267 if not self.entry.is_pyglobal:
1268 error(self.pos, "Deletion of local or C global name not supported")
1269 return
1270 code.put_error_if_neg(self.pos,
1271 '__Pyx_DelAttrString(%s, "%s")' % (
1272 Naming.module_cname,
1273 self.entry.name))
1275 def annotate(self, code):
1276 if hasattr(self, 'is_called') and self.is_called:
1277 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1278 if self.type.is_pyobject:
1279 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1280 else:
1281 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1283 class BackquoteNode(ExprNode):
1284 # `expr`
1285 #
1286 # arg ExprNode
1288 subexprs = ['arg']
1290 def analyse_types(self, env):
1291 self.arg.analyse_types(env)
1292 self.arg = self.arg.coerce_to_pyobject(env)
1293 self.type = py_object_type
1294 self.is_temp = 1
1296 gil_message = "Backquote expression"
1298 def calculate_constant_result(self):
1299 self.constant_result = repr(self.arg.constant_result)
1301 def generate_result_code(self, code):
1302 code.putln(
1303 "%s = PyObject_Repr(%s); %s" % (
1304 self.result(),
1305 self.arg.py_result(),
1306 code.error_goto_if_null(self.result(), self.pos)))
1307 code.put_gotref(self.py_result())
1311 class ImportNode(ExprNode):
1312 # Used as part of import statement implementation.
1313 # Implements result =
1314 # __import__(module_name, globals(), None, name_list)
1315 #
1316 # module_name IdentifierStringNode dotted name of module
1317 # name_list ListNode or None list of names to be imported
1319 subexprs = ['module_name', 'name_list']
1321 def analyse_types(self, env):
1322 self.module_name.analyse_types(env)
1323 self.module_name = self.module_name.coerce_to_pyobject(env)
1324 if self.name_list:
1325 self.name_list.analyse_types(env)
1326 self.name_list.coerce_to_pyobject(env)
1327 self.type = py_object_type
1328 self.is_temp = 1
1329 env.use_utility_code(import_utility_code)
1331 gil_message = "Python import"
1333 def generate_result_code(self, code):
1334 if self.name_list:
1335 name_list_code = self.name_list.py_result()
1336 else:
1337 name_list_code = "0"
1338 code.putln(
1339 "%s = __Pyx_Import(%s, %s); %s" % (
1340 self.result(),
1341 self.module_name.py_result(),
1342 name_list_code,
1343 code.error_goto_if_null(self.result(), self.pos)))
1344 code.put_gotref(self.py_result())
1347 class IteratorNode(ExprNode):
1348 # Used as part of for statement implementation.
1349 #
1350 # allocate_counter_temp/release_counter_temp needs to be called
1351 # by parent (ForInStatNode)
1352 #
1353 # Implements result = iter(sequence)
1354 #
1355 # sequence ExprNode
1357 subexprs = ['sequence']
1359 def analyse_types(self, env):
1360 self.sequence.analyse_types(env)
1361 self.sequence = self.sequence.coerce_to_pyobject(env)
1362 self.type = py_object_type
1363 self.is_temp = 1
1365 gil_message = "Iterating over Python object"
1367 def allocate_counter_temp(self, code):
1368 self.counter_cname = code.funcstate.allocate_temp(
1369 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1371 def release_counter_temp(self, code):
1372 code.funcstate.release_temp(self.counter_cname)
1374 def generate_result_code(self, code):
1375 is_builtin_sequence = self.sequence.type is list_type or \
1376 self.sequence.type is tuple_type
1377 if is_builtin_sequence:
1378 code.putln(
1379 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1380 else:
1381 code.putln(
1382 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1383 self.sequence.py_result(),
1384 self.sequence.py_result()))
1385 code.putln(
1386 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
1387 self.counter_cname,
1388 self.result(),
1389 self.sequence.py_result(),
1390 self.result()))
1391 code.putln("} else {")
1392 if is_builtin_sequence:
1393 code.putln(
1394 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1395 code.error_goto(self.pos))
1396 else:
1397 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1398 self.counter_cname,
1399 self.result(),
1400 self.sequence.py_result(),
1401 code.error_goto_if_null(self.result(), self.pos)))
1402 code.put_gotref(self.py_result())
1403 code.putln("}")
1406 class NextNode(AtomicExprNode):
1407 # Used as part of for statement implementation.
1408 # Implements result = iterator.next()
1409 # Created during analyse_types phase.
1410 # The iterator is not owned by this node.
1411 #
1412 # iterator ExprNode
1414 def __init__(self, iterator, env):
1415 self.pos = iterator.pos
1416 self.iterator = iterator
1417 self.type = py_object_type
1418 self.is_temp = 1
1420 def generate_result_code(self, code):
1421 if self.iterator.sequence.type is list_type:
1422 type_checks = [(list_type, "List")]
1423 elif self.iterator.sequence.type is tuple_type:
1424 type_checks = [(tuple_type, "Tuple")]
1425 else:
1426 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1428 for py_type, prefix in type_checks:
1429 if len(type_checks) > 1:
1430 code.putln(
1431 "if (likely(Py%s_CheckExact(%s))) {" % (
1432 prefix, self.iterator.py_result()))
1433 code.putln(
1434 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1435 self.iterator.counter_cname,
1436 prefix,
1437 self.iterator.py_result()))
1438 code.putln(
1439 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1440 self.result(),
1441 prefix,
1442 self.iterator.py_result(),
1443 self.iterator.counter_cname,
1444 self.result(),
1445 self.iterator.counter_cname))
1446 if len(type_checks) > 1:
1447 code.put("} else ")
1448 if len(type_checks) == 1:
1449 return
1450 code.putln("{")
1451 code.putln(
1452 "%s = PyIter_Next(%s);" % (
1453 self.result(),
1454 self.iterator.py_result()))
1455 code.putln(
1456 "if (!%s) {" %
1457 self.result())
1458 code.putln(code.error_goto_if_PyErr(self.pos))
1459 code.putln("break;")
1460 code.putln("}")
1461 code.put_gotref(self.py_result())
1462 code.putln("}")
1465 class ExcValueNode(AtomicExprNode):
1466 # Node created during analyse_types phase
1467 # of an ExceptClauseNode to fetch the current
1468 # exception value.
1470 def __init__(self, pos, env):
1471 ExprNode.__init__(self, pos)
1472 self.type = py_object_type
1474 def set_var(self, var):
1475 self.var = var
1477 def calculate_result_code(self):
1478 return self.var
1480 def generate_result_code(self, code):
1481 pass
1483 def analyse_types(self, env):
1484 pass
1487 class TempNode(ExprNode):
1488 # Node created during analyse_types phase
1489 # of some nodes to hold a temporary value.
1490 #
1491 # Note: One must call "allocate" and "release" on
1492 # the node during code generation to get/release the temp.
1493 # This is because the temp result is often used outside of
1494 # the regular cycle.
1496 subexprs = []
1498 def __init__(self, pos, type, env):
1499 ExprNode.__init__(self, pos)
1500 self.type = type
1501 if type.is_pyobject:
1502 self.result_ctype = py_object_type
1503 self.is_temp = 1
1505 def analyse_types(self, env):
1506 return self.type
1508 def generate_result_code(self, code):
1509 pass
1511 def allocate(self, code):
1512 self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=True)
1514 def release(self, code):
1515 code.funcstate.release_temp(self.temp_cname)
1516 self.temp_cname = None
1518 def result(self):
1519 try:
1520 return self.temp_cname
1521 except:
1522 assert False, "Remember to call allocate/release on TempNode"
1523 raise
1525 # Do not participate in normal temp alloc/dealloc:
1526 def allocate_temp_result(self, code):
1527 pass
1529 def release_temp_result(self, code):
1530 pass
1532 class PyTempNode(TempNode):
1533 # TempNode holding a Python value.
1535 def __init__(self, pos, env):
1536 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1539 #-------------------------------------------------------------------
1540 #
1541 # Trailer nodes
1542 #
1543 #-------------------------------------------------------------------
1545 class IndexNode(ExprNode):
1546 # Sequence indexing.
1547 #
1548 # base ExprNode
1549 # index ExprNode
1550 # indices [ExprNode]
1551 # is_buffer_access boolean Whether this is a buffer access.
1552 #
1553 # indices is used on buffer access, index on non-buffer access.
1554 # The former contains a clean list of index parameters, the
1555 # latter whatever Python object is needed for index access.
1557 subexprs = ['base', 'index', 'indices']
1558 indices = None
1560 def __init__(self, pos, index, *args, **kw):
1561 ExprNode.__init__(self, pos, index=index, *args, **kw)
1562 self._index = index
1564 def calculate_constant_result(self):
1565 self.constant_result = \
1566 self.base.constant_result[self.index.constant_result]
1568 def compile_time_value(self, denv):
1569 base = self.base.compile_time_value(denv)
1570 index = self.index.compile_time_value(denv)
1571 try:
1572 return base[index]
1573 except Exception, e:
1574 self.compile_time_value_error(e)
1576 def is_ephemeral(self):
1577 return self.base.is_ephemeral()
1579 def analyse_target_declaration(self, env):
1580 pass
1582 def analyse_as_type(self, env):
1583 base_type = self.base.analyse_as_type(env)
1584 if base_type and not base_type.is_pyobject:
1585 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1586 return None
1588 def analyse_types(self, env):
1589 self.analyse_base_and_index_types(env, getting = 1)
1591 def analyse_target_types(self, env):
1592 self.analyse_base_and_index_types(env, setting = 1)
1594 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1595 # Note: This might be cleaned up by having IndexNode
1596 # parsed in a saner way and only construct the tuple if
1597 # needed.
1599 # Note that this function must leave IndexNode in a cloneable state.
1600 # For buffers, self.index is packed out on the initial analysis, and
1601 # when cloning self.indices is copied.
1602 self.is_buffer_access = False
1604 self.base.analyse_types(env)
1605 # Handle the case where base is a literal char* (and we expect a string, not an int)
1606 if isinstance(self.base, StringNode):
1607 self.base = self.base.coerce_to_pyobject(env)
1609 skip_child_analysis = False
1610 buffer_access = False
1611 if self.base.type.is_buffer:
1612 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1613 if self.indices:
1614 indices = self.indices
1615 else:
1616 if isinstance(self.index, TupleNode):
1617 indices = self.index.args
1618 else:
1619 indices = [self.index]
1620 if len(indices) == self.base.type.ndim:
1621 buffer_access = True
1622 skip_child_analysis = True
1623 for x in indices:
1624 x.analyse_types(env)
1625 if not x.type.is_int:
1626 buffer_access = False
1628 # On cloning, indices is cloned. Otherwise, unpack index into indices
1629 assert not (buffer_access and isinstance(self.index, CloneNode))
1631 if buffer_access:
1632 self.indices = indices
1633 self.index = None
1634 self.type = self.base.type.dtype
1635 self.is_buffer_access = True
1636 self.buffer_type = self.base.entry.type
1638 if getting and self.type.is_pyobject:
1639 self.is_temp = True
1640 if setting:
1641 if not self.base.entry.type.writable:
1642 error(self.pos, "Writing to readonly buffer")
1643 else:
1644 self.base.entry.buffer_aux.writable_needed = True
1645 else:
1646 if isinstance(self.index, TupleNode):
1647 self.index.analyse_types(env, skip_children=skip_child_analysis)
1648 elif not skip_child_analysis:
1649 self.index.analyse_types(env)
1650 self.original_index_type = self.index.type
1651 if self.base.type.is_pyobject:
1652 if self.index.type.is_int:
1653 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1654 else:
1655 self.index = self.index.coerce_to_pyobject(env)
1656 self.type = py_object_type
1657 self.is_temp = 1
1658 else:
1659 if self.base.type.is_ptr or self.base.type.is_array:
1660 self.type = self.base.type.base_type
1661 else:
1662 error(self.pos,
1663 "Attempting to index non-array type '%s'" %
1664 self.base.type)
1665 self.type = PyrexTypes.error_type
1666 if self.index.type.is_pyobject:
1667 self.index = self.index.coerce_to(
1668 PyrexTypes.c_py_ssize_t_type, env)
1669 if not self.index.type.is_int:
1670 error(self.pos,
1671 "Invalid index type '%s'" %
1672 self.index.type)
1673 gil_message = "Indexing Python object"
1675 def nogil_check(self, env):
1676 if self.is_buffer_access:
1677 if env.directives['boundscheck']:
1678 error(self.pos, "Cannot check buffer index bounds without gil; use boundscheck(False) directive")
1679 return
1680 elif self.type.is_pyobject:
1681 error(self.pos, "Cannot access buffer with object dtype without gil")
1682 return
1683 super(IndexNode, self).nogil_check(env)
1686 def check_const_addr(self):
1687 self.base.check_const_addr()
1688 self.index.check_const()
1690 def is_lvalue(self):
1691 return 1
1693 def calculate_result_code(self):
1694 if self.is_buffer_access:
1695 return "(*%s)" % self.buffer_ptr_code
1696 else:
1697 return "(%s[%s])" % (
1698 self.base.result(), self.index.result())
1700 def extra_index_params(self):
1701 if self.index.type.is_int:
1702 if self.original_index_type.signed:
1703 size_adjustment = ""
1704 else:
1705 size_adjustment = "+1"
1706 return ", sizeof(%s)%s, %s" % (self.original_index_type.declaration_code(""), size_adjustment, self.original_index_type.to_py_function)
1707 else:
1708 return ""
1710 def generate_subexpr_evaluation_code(self, code):
1711 self.base.generate_evaluation_code(code)
1712 if not self.indices:
1713 self.index.generate_evaluation_code(code)
1714 else:
1715 for i in self.indices:
1716 i.generate_evaluation_code(code)
1718 def generate_subexpr_disposal_code(self, code):
1719 self.base.generate_disposal_code(code)
1720 if not self.indices:
1721 self.index.generate_disposal_code(code)
1722 else:
1723 for i in self.indices:
1724 i.generate_disposal_code(code)
1726 def free_subexpr_temps(self, code):
1727 self.base.free_temps(code)
1728 if not self.indices:
1729 self.index.free_temps(code)
1730 else:
1731 for i in self.indices:
1732 i.free_temps(code)
1734 def generate_result_code(self, code):
1735 if self.is_buffer_access:
1736 if code.globalstate.directives['nonecheck']:
1737 self.put_nonecheck(code)
1738 self.buffer_ptr_code = self.buffer_lookup_code(code)
1739 if self.type.is_pyobject:
1740 # is_temp is True, so must pull out value and incref it.
1741 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1742 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
1743 elif self.type.is_pyobject:
1744 if self.index.type.is_int:
1745 index_code = self.index.result()
1746 if self.base.type is list_type:
1747 function = "__Pyx_GetItemInt_List"
1748 elif self.base.type is tuple_type:
1749 function = "__Pyx_GetItemInt_Tuple"
1750 else:
1751 function = "__Pyx_GetItemInt"
1752 code.globalstate.use_utility_code(getitem_int_utility_code)
1753 else:
1754 function = "PyObject_GetItem"
1755 index_code = self.index.py_result()
1756 sign_code = ""
1757 code.putln(
1758 "%s = %s(%s, %s%s); if (!%s) %s" % (
1759 self.result(),
1760 function,
1761 self.base.py_result(),
1762 index_code,
1763 self.extra_index_params(),
1764 self.result(),
1765 code.error_goto(self.pos)))
1766 code.put_gotref(self.py_result())
1768 def generate_setitem_code(self, value_code, code):
1769 if self.index.type.is_int:
1770 function = "__Pyx_SetItemInt"
1771 index_code = self.index.result()
1772 code.globalstate.use_utility_code(setitem_int_utility_code)
1773 else:
1774 index_code = self.index.py_result()
1775 if self.base.type is dict_type:
1776 function = "PyDict_SetItem"
1777 # It would seem that we could specalized lists/tuples, but that
1778 # shouldn't happen here.
1779 # Both PyList_SetItem PyTuple_SetItem and a Py_ssize_t as input,
1780 # not a PyObject*, and bad conversion here would give the wrong
1781 # exception. Also, tuples are supposed to be immutable, and raise
1782 # TypeErrors when trying to set their entries (PyTuple_SetItem
1783 # is for creating new tuples from).
1784 else:
1785 function = "PyObject_SetItem"
1786 code.putln(
1787 "if (%s(%s, %s, %s%s) < 0) %s" % (
1788 function,
1789 self.base.py_result(),
1790 index_code,
1791 value_code,
1792 self.extra_index_params(),
1793 code.error_goto(self.pos)))
1795 def generate_buffer_setitem_code(self, rhs, code, op=""):
1796 # Used from generate_assignment_code and InPlaceAssignmentNode
1797 if code.globalstate.directives['nonecheck']:
1798 self.put_nonecheck(code)
1799 ptrexpr = self.buffer_lookup_code(code)
1800 if self.buffer_type.dtype.is_pyobject:
1801 # Must manage refcounts. Decref what is already there
1802 # and incref what we put in.
1803 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
1804 rhs_code = rhs.result()
1805 code.putln("%s = %s;" % (ptr, ptrexpr))
1806 code.put_gotref("*%s" % ptr)
1807 code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
1808 ptr, rhs_code
1809 ))
1810 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1811 code.put_giveref("*%s" % ptr)
1812 code.funcstate.release_temp(ptr)
1813 else:
1814 # Simple case
1815 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1817 def generate_assignment_code(self, rhs, code):
1818 self.generate_subexpr_evaluation_code(code)
1819 if self.is_buffer_access:
1820 self.generate_buffer_setitem_code(rhs, code)
1821 elif self.type.is_pyobject:
1822 self.generate_setitem_code(rhs.py_result(), code)
1823 else:
1824 code.putln(
1825 "%s = %s;" % (
1826 self.result(), rhs.result()))
1827 self.generate_subexpr_disposal_code(code)
1828 self.free_subexpr_temps(code)
1829 rhs.generate_disposal_code(code)
1830 rhs.free_temps(code)
1832 def generate_deletion_code(self, code):
1833 self.generate_subexpr_evaluation_code(code)
1834 #if self.type.is_pyobject:
1835 if self.index.type.is_int:
1836 function = "__Pyx_DelItemInt"
1837 index_code = self.index.result()
1838 code.globalstate.use_utility_code(delitem_int_utility_code)
1839 else:
1840 index_code = self.index.py_result()
1841 if self.base.type is dict_type:
1842 function = "PyDict_DelItem"
1843 else:
1844 function = "PyObject_DelItem"
1845 code.putln(
1846 "if (%s(%s, %s%s) < 0) %s" % (
1847 function,
1848 self.base.py_result(),
1849 index_code,
1850 self.extra_index_params(),
1851 code.error_goto(self.pos)))
1852 self.generate_subexpr_disposal_code(code)
1853 self.free_subexpr_temps(code)
1855 def buffer_lookup_code(self, code):
1856 # Assign indices to temps
1857 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
1858 for temp, index in zip(index_temps, self.indices):
1859 code.putln("%s = %s;" % (temp, index.result()))
1860 # Generate buffer access code using these temps
1861 import Buffer
1862 # The above could happen because child_attrs is wrong somewhere so that
1863 # options are not propagated.
1864 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1865 index_signeds=[i.type.signed for i in self.indices],
1866 index_cnames=index_temps,
1867 directives=code.globalstate.directives,
1868 pos=self.pos, code=code)
1870 def put_nonecheck(self, code):
1871 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
1872 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
1873 code.putln("__Pyx_RaiseNoneIndexingError();")
1874 code.putln(code.error_goto(self.pos))
1875 code.putln("}")
1877 class SliceIndexNode(ExprNode):
1878 # 2-element slice indexing
1879 #
1880 # base ExprNode
1881 # start ExprNode or None
1882 # stop ExprNode or None
1884 subexprs = ['base', 'start', 'stop']
1886 def calculate_constant_result(self):
1887 self.constant_result = self.base.constant_result[
1888 self.start.constant_result : self.stop.constant_result]
1890 def compile_time_value(self, denv):
1891 base = self.base.compile_time_value(denv)
1892 if self.start is None:
1893 start = 0
1894 else:
1895 start = self.start.compile_time_value(denv)
1896 if self.stop is None:
1897 stop = None
1898 else:
1899 stop = self.stop.compile_time_value(denv)
1900 try:
1901 return base[start:stop]
1902 except Exception, e:
1903 self.compile_time_value_error(e)
1905 def analyse_target_declaration(self, env):
1906 pass
1908 def analyse_target_types(self, env):
1909 self.analyse_types(env)
1910 # when assigning, we must accept any Python type
1911 if self.type.is_pyobject:
1912 self.type = py_object_type
1914 def analyse_types(self, env):
1915 self.base.analyse_types(env)
1916 if self.start:
1917 self.start.analyse_types(env)
1918 if self.stop:
1919 self.stop.analyse_types(env)
1920 base_type = self.base.type
1921 if base_type.is_string:
1922 self.type = bytes_type
1923 elif base_type.is_array or base_type.is_ptr:
1924 # we need a ptr type here instead of an array type, as
1925 # array types can result in invalid type casts in the C
1926 # code
1927 self.type = PyrexTypes.CPtrType(base_type.base_type)
1928 else:
1929 self.base = self.base.coerce_to_pyobject(env)
1930 self.type = py_object_type
1931 if base_type.is_builtin_type:
1932 # slicing builtin types returns something of the same type
1933 self.type = base_type
1934 c_int = PyrexTypes.c_py_ssize_t_type
1935 if self.start:
1936 self.start = self.start.coerce_to(c_int, env)
1937 if self.stop:
1938 self.stop = self.stop.coerce_to(c_int, env)
1939 self.is_temp = 1
1941 nogil_check = Node.gil_error
1942 gil_message = "Slicing Python object"
1944 def generate_result_code(self, code):
1945 if not self.type.is_pyobject:
1946 error(self.pos,
1947 "Slicing is not currently supported for '%s'." % self.type)
1948 return
1949 if self.base.type.is_string:
1950 if self.stop is None:
1951 code.putln(
1952 "%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
1953 self.result(),
1954 self.base.result(),
1955 self.start_code(),
1956 code.error_goto_if_null(self.result(), self.pos)))
1957 else:
1958 code.putln(
1959 "%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
1960 self.result(),
1961 self.base.result(),
1962 self.start_code(),
1963 self.stop_code(),
1964 self.start_code(),
1965 code.error_goto_if_null(self.result(), self.pos)))
1966 else:
1967 code.putln(
1968 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1969 self.result(),
1970 self.base.py_result(),
1971 self.start_code(),
1972 self.stop_code(),
1973 code.error_goto_if_null(self.result(), self.pos)))
1974 code.put_gotref(self.py_result())
1976 def generate_assignment_code(self, rhs, code):
1977 self.generate_subexpr_evaluation_code(code)
1978 if self.type.is_pyobject:
1979 code.put_error_if_neg(self.pos,
1980 "PySequence_SetSlice(%s, %s, %s, %s)" % (
1981 self.base.py_result(),
1982 self.start_code(),
1983 self.stop_code(),
1984 rhs.result()))
1985 else:
1986 start_offset = ''
1987 if self.start:
1988 start_offset = self.start_code()
1989 if start_offset == '0':
1990 start_offset = ''
1991 else:
1992 start_offset += '+'
1993 if rhs.type.is_array:
1994 array_length = rhs.type.size
1995 self.generate_slice_guard_code(code, array_length)
1996 else:
1997 error(self.pos,
1998 "Slice assignments from pointers are not yet supported.")
1999 # FIXME: fix the array size according to start/stop
2000 array_length = self.base.type.size
2001 for i in range(array_length):
2002 code.putln("%s[%s%s] = %s[%d];" % (
2003 self.base.result(), start_offset, i,
2004 rhs.result(), i))
2005 self.generate_subexpr_disposal_code(code)
2006 self.free_subexpr_temps(code)
2007 rhs.generate_disposal_code(code)
2008 rhs.free_temps(code)
2010 def generate_deletion_code(self, code):
2011 if not self.base.type.is_pyobject:
2012 error(self.pos,
2013 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2014 return
2015 self.generate_subexpr_evaluation_code(code)
2016 code.put_error_if_neg(self.pos,
2017 "PySequence_DelSlice(%s, %s, %s)" % (
2018 self.base.py_result(),
2019 self.start_code(),
2020 self.stop_code()))
2021 self.generate_subexpr_disposal_code(code)
2023 def generate_slice_guard_code(self, code, target_size):
2024 if not self.base.type.is_array:
2025 return
2026 slice_size = self.base.type.size
2027 start = stop = None
2028 if self.stop:
2029 stop = self.stop.result()
2030 try:
2031 stop = int(stop)
2032 if stop < 0:
2033 slice_size = self.base.type.size + stop
2034 else:
2035 slice_size = stop
2036 stop = None
2037 except ValueError:
2038 pass
2039 if self.start:
2040 start = self.start.result()
2041 try:
2042 start = int(start)
2043 if start < 0:
2044 start = self.base.type.size + start
2045 slice_size -= start
2046 start = None
2047 except ValueError:
2048 pass
2049 check = None
2050 if slice_size < 0:
2051 if target_size > 0:
2052 error(self.pos, "Assignment to empty slice.")
2053 elif start is None and stop is None:
2054 # we know the exact slice length
2055 if target_size != slice_size:
2056 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2057 slice_size, target_size))
2058 elif start is not None:
2059 if stop is None:
2060 stop = slice_size
2061 check = "(%s)-(%s)" % (stop, start)
2062 else: # stop is not None:
2063 check = stop
2064 if check:
2065 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2066 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%"PY_FORMAT_SIZE_T"d, got %%"PY_FORMAT_SIZE_T"d", (Py_ssize_t)%d, (Py_ssize_t)(%s));' % (
2067 target_size, check))
2068 code.putln(code.error_goto(self.pos))
2069 code.putln("}")
2071 def start_code(self):
2072 if self.start:
2073 return self.start.result()
2074 else:
2075 return "0"
2077 def stop_code(self):
2078 if self.stop:
2079 return self.stop.result()
2080 elif self.base.type.is_array:
2081 return self.base.type.size
2082 else:
2083 return "PY_SSIZE_T_MAX"
2085 def calculate_result_code(self):
2086 # self.result() is not used, but this method must exist
2087 return "<unused>"
2090 class SliceNode(ExprNode):
2091 # start:stop:step in subscript list
2092 #
2093 # start ExprNode
2094 # stop ExprNode
2095 # step ExprNode
2097 def calculate_constant_result(self):
2098 self.constant_result = self.base.constant_result[
2099 self.start.constant_result : \
2100 self.stop.constant_result : \
2101 self.step.constant_result]
2103 def compile_time_value(self, denv):
2104 start = self.start.compile_time_value(denv)
2105 if self.stop is None:
2106 stop = None
2107 else:
2108 stop = self.stop.compile_time_value(denv)
2109 if self.step is None:
2110 step = None
2111 else:
2112 step = self.step.compile_time_value(denv)
2113 try:
2114 return slice(start, stop, step)
2115 except Exception, e:
2116 self.compile_time_value_error(e)
2118 subexprs = ['start', 'stop', 'step']
2120 def analyse_types(self, env):
2121 self.start.analyse_types(env)
2122 self.stop.analyse_types(env)
2123 self.step.analyse_types(env)
2124 self.start = self.start.coerce_to_pyobject(env)
2125 self.stop = self.stop.coerce_to_pyobject(env)
2126 self.step = self.step.coerce_to_pyobject(env)
2127 self.type = py_object_type
2128 self.is_temp = 1
2130 gil_message = "Constructing Python slice object"
2132 def generate_result_code(self, code):
2133 code.putln(
2134 "%s = PySlice_New(%s, %s, %s); %s" % (
2135 self.result(),
2136 self.start.py_result(),
2137 self.stop.py_result(),
2138 self.step.py_result(),
2139 code.error_goto_if_null(self.result(), self.pos)))
2140 code.put_gotref(self.py_result())
2143 class CallNode(ExprNode):
2144 def analyse_as_type_constructor(self, env):
2145 type = self.function.analyse_as_type(env)
2146 if type and type.is_struct_or_union:
2147 args, kwds = self.explicit_args_kwds()
2148 items = []
2149 for arg, member in zip(args, type.scope.var_entries):
2150 items.append(DictItemNode(pos=arg.pos, key=IdentifierStringNode(pos=arg.pos, value=member.name), value=arg))
2151 if kwds:
2152 items += kwds.key_value_pairs
2153 self.key_value_pairs = items
2154 self.__class__ = DictNode
2155 self.analyse_types(env)
2156 self.coerce_to(type, env)
2157 return True
2159 def nogil_check(self, env):
2160 func_type = self.function_type()
2161 if func_type.is_pyobject:
2162 self.gil_error()
2163 elif not getattr(func_type, 'nogil', False):
2164 self.gil_error()
2166 gil_message = "Calling gil-requiring function"
2169 class SimpleCallNode(CallNode):
2170 # Function call without keyword, * or ** args.
2171 #
2172 # function ExprNode
2173 # args [ExprNode]
2174 # arg_tuple ExprNode or None used internally
2175 # self ExprNode or None used internally
2176 # coerced_self ExprNode or None used internally
2177 # wrapper_call bool used internally
2178 # has_optional_args bool used internally
2180 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2182 self = None
2183 coerced_self = None
2184 arg_tuple = None
2185 wrapper_call = False
2186 has_optional_args = False
2188 def compile_time_value(self, denv):
2189 function = self.function.compile_time_value(denv)
2190 args = [arg.compile_time_value(denv) for arg in self.args]
2191 try:
2192 return function(*args)
2193 except Exception, e:
2194 self.compile_time_value_error(e)
2196 def analyse_as_type(self, env):
2197 attr = self.function.as_cython_attribute()
2198 if attr == 'pointer':
2199 if len(self.args) != 1:
2200 error(self.args.pos, "only one type allowed.")
2201 else:
2202 type = self.args[0].analyse_as_type(env)
2203 if not type:
2204 error(self.args[0].pos, "Unknown type")
2205 else:
2206 return PyrexTypes.CPtrType(type)
2208 def explicit_args_kwds(self):
2209 return self.args, None
2211 def analyse_types(self, env):
2212 if self.analyse_as_type_constructor(env):
2213 return
2214 function = self.function
2215 function.is_called = 1
2216 self.function.analyse_types(env)
2217 if function.is_attribute and function.entry and function.entry.is_cmethod:
2218 # Take ownership of the object from which the attribute
2219 # was obtained, because we need to pass it as 'self'.
2220 self.self = function.obj
2221 function.obj = CloneNode(self.self)
2222 func_type = self.function_type()
2223 if func_type.is_pyobject:
2224 self.arg_tuple = TupleNode(self.pos, args = self.args)
2225 self.arg_tuple.analyse_types(env)
2226 self.args = None
2227 if function.is_name and function.type_entry:
2228 # We are calling an extension type constructor. As
2229 # long as we do not support __new__(), the result type
2230 # is clear
2231 self.type = function.type_entry.type
2232 self.result_ctype = py_object_type
2233 else:
2234 self.type = py_object_type
2235 self.is_temp = 1
2236 else:
2237 for arg in self.args:
2238 arg.analyse_types(env)
2239 if self.self and func_type.args:
2240 # Coerce 'self' to the type expected by the method.
2241 expected_type = func_type.args[0].type
2242 self.coerced_self = CloneNode(self.self).coerce_to(
2243 expected_type, env)
2244 # Insert coerced 'self' argument into argument list.
2245 self.args.insert(0, self.coerced_self)
2246 self.analyse_c_function_call(env)
2248 def function_type(self):
2249 # Return the type of the function being called, coercing a function
2250 # pointer to a function if necessary.
2251 func_type = self.function.type
2252 if func_type.is_ptr:
2253 func_type = func_type.base_type
2254 return func_type
2256 def analyse_c_function_call(self, env):
2257 func_type = self.function_type()
2258 # Check function type
2259 if not func_type.is_cfunction:
2260 if not func_type.is_error:
2261 error(self.pos, "Calling non-function type '%s'" %
2262 func_type)
2263 self.type = PyrexTypes.error_type
2264 self.result_code = "<error>"
2265 return
2266 # Check no. of args
2267 max_nargs = len(func_type.args)
2268 expected_nargs = max_nargs - func_type.optional_arg_count
2269 actual_nargs = len(self.args)
2270 if actual_nargs < expected_nargs \
2271 or (not func_type.has_varargs and actual_nargs > max_nargs):
2272 expected_str = str(expected_nargs)
2273 if func_type.has_varargs:
2274 expected_str = "at least " + expected_str
2275 elif func_type.optional_arg_count:
2276 if actual_nargs < max_nargs:
2277 expected_str = "at least " + expected_str
2278 else:
2279 expected_str = "at most " + str(max_nargs)
2280 error(self.pos,
2281 "Call with wrong number of arguments (expected %s, got %s)"
2282 % (expected_str, actual_nargs))
2283 self.args = None
2284 self.type = PyrexTypes.error_type
2285 self.result_code = "<error>"
2286 return
2287 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2288 self.has_optional_args = 1
2289 self.is_temp = 1
2290 # Coerce arguments
2291 for i in range(min(max_nargs, actual_nargs)):
2292 formal_type = func_type.args[i].type
2293 self.args[i] = self.args[i].coerce_to(formal_type, env)
2294 for i in range(max_nargs, actual_nargs):
2295 if self.args[i].type.is_pyobject:
2296 error(self.args[i].pos,
2297 "Python object cannot be passed as a varargs parameter")
2298 # Calc result type and code fragment
2299 self.type = func_type.return_type
2300 if self.type.is_pyobject:
2301 self.result_ctype = py_object_type
2302 self.is_temp = 1
2303 elif func_type.exception_value is not None \
2304 or func_type.exception_check:
2305 self.is_temp = 1
2306 # C++ exception handler
2307 if func_type.exception_check == '+':
2308 if func_type.exception_value is None:
2309 env.use_utility_code(cpp_exception_utility_code)
2311 def calculate_result_code(self):
2312 return self.c_call_code()
2314 def c_call_code(self):
2315 func_type = self.function_type()
2316 if self.args is None or not func_type.is_cfunction:
2317 return "<error>"
2318 formal_args = func_type.args
2319 arg_list_code = []
2320 args = zip(formal_args, self.args)
2321 max_nargs = len(func_type.args)
2322 expected_nargs = max_nargs - func_type.optional_arg_count
2323 actual_nargs = len(self.args)
2324 for formal_arg, actual_arg in args[:expected_nargs]:
2325 arg_code = actual_arg.result_as(formal_arg.type)
2326 arg_list_code.append(arg_code)
2328 if func_type.is_overridable:
2329 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2331 if func_type.optional_arg_count:
2332 if expected_nargs == actual_nargs:
2333 optional_args = 'NULL'
2334 else:
2335 optional_args = "&%s" % self.opt_arg_struct
2336 arg_list_code.append(optional_args)
2338 for actual_arg in self.args[len(formal_args):]:
2339 arg_list_code.append(actual_arg.result())
2340 result = "%s(%s)" % (self.function.result(),
2341 ', '.join(arg_list_code))
2342 # if self.wrapper_call or \
2343 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
2344 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
2345 return result
2347 def generate_result_code(self, code):
2348 func_type = self.function_type()
2349 if func_type.is_pyobject:
2350 arg_code = self.arg_tuple.py_result()
2351 code.putln(
2352 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2353 self.result(),
2354 self.function.py_result(),
2355 arg_code,
2356 code.error_goto_if_null(self.result(), self.pos)))
2357 code.put_gotref(self.py_result())
2358 elif func_type.is_cfunction:
2359 if self.has_optional_args:
2360 actual_nargs = len(self.args)
2361 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2362 self.opt_arg_struct = code.funcstate.allocate_temp(
2363 func_type.op_arg_struct.base_type, manage_ref=True)
2364 code.putln("%s.%s = %s;" % (
2365 self.opt_arg_struct,
2366 Naming.pyrex_prefix + "n",
2367 len(self.args) - expected_nargs))
2368 args = zip(func_type.args, self.args)
2369 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2370 code.putln("%s.%s = %s;" % (
2371 self.opt_arg_struct,
2372 formal_arg.name,
2373 actual_arg.result_as(formal_arg.type)))
2374 exc_checks = []
2375 if self.type.is_pyobject:
2376 exc_checks.append("!%s" % self.result())
2377 else:
2378 exc_val = func_type.exception_value
2379 exc_check = func_type.exception_check
2380 if exc_val is not None:
2381 exc_checks.append("%s == %s" % (self.result(), exc_val))
2382 if exc_check:
2383 exc_checks.append("PyErr_Occurred()")
2384 if self.is_temp or exc_checks:
2385 rhs = self.c_call_code()
2386 if self.result():
2387 lhs = "%s = " % self.result()
2388 if self.is_temp and self.type.is_pyobject:
2389 #return_type = self.type # func_type.return_type
2390 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2391 # "from", return_type, "to pyobject" ###
2392 rhs = typecast(py_object_type, self.type, rhs)
2393 else:
2394 lhs = ""
2395 if func_type.exception_check == '+':
2396 if func_type.exception_value is None:
2397 raise_py_exception = "__Pyx_CppExn2PyErr()"
2398 elif func_type.exception_value.type.is_pyobject:
2399 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2400 else:
2401 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2402 code.putln(
2403 "try {%s%s;} catch(...) {%s; %s}" % (
2404 lhs,
2405 rhs,
2406 raise_py_exception,
2407 code.error_goto(self.pos)))
2408 else:
2409 if exc_checks:
2410 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2411 else:
2412 goto_error = ""
2413 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2414 if self.type.is_pyobject and self.result():
2415 code.put_gotref(self.py_result())
2416 if self.has_optional_args:
2417 code.funcstate.release_temp(self.opt_arg_struct)
2420 class PythonCapiFunctionNode(ExprNode):
2421 subexprs = []
2422 def __init__(self, pos, name, func_type, utility_code = None):
2423 self.pos = pos
2424 self.name = name
2425 self.type = func_type
2426 self.utility_code = utility_code
2428 def generate_result_code(self, code):
2429 if self.utility_code:
2430 code.globalstate.use_utility_code(self.utility_code)
2432 def calculate_result_code(self):
2433 return self.name
2435 class PythonCapiCallNode(SimpleCallNode):
2436 # Python C-API Function call (only created in transforms)
2438 def __init__(self, pos, function_name, func_type,
2439 utility_code = None, **kwargs):
2440 self.type = func_type.return_type
2441 self.result_ctype = self.type
2442 self.function = PythonCapiFunctionNode(
2443 pos, function_name, func_type,
2444 utility_code = utility_code)
2445 # call this last so that we can override the constructed
2446 # attributes above with explicit keyword arguments if required
2447 SimpleCallNode.__init__(self, pos, **kwargs)
2450 class GeneralCallNode(CallNode):
2451 # General Python function call, including keyword,
2452 # * and ** arguments.
2453 #
2454 # function ExprNode
2455 # positional_args ExprNode Tuple of positional arguments
2456 # keyword_args ExprNode or None Dict of keyword arguments
2457 # starstar_arg ExprNode or None Dict of extra keyword args
2459 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2461 nogil_check = Node.gil_error
2463 def compile_time_value(self, denv):
2464 function = self.function.compile_time_value(denv)
2465 positional_args = self.positional_args.compile_time_value(denv)
2466 keyword_args = self.keyword_args.compile_time_value(denv)
2467 starstar_arg = self.starstar_arg.compile_time_value(denv)
2468 try:
2469 keyword_args.update(starstar_arg)
2470 return function(*positional_args, **keyword_args)
2471 except Exception, e:
2472 self.compile_time_value_error(e)
2474 def explicit_args_kwds(self):
2475 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2476 raise PostParseError(self.pos,
2477 'Compile-time keyword arguments must be explicit.')
2478 return self.positional_args.args, self.keyword_args
2480 def analyse_types(self, env):
2481 if self.analyse_as_type_constructor(env):
2482 return
2483 self.function.analyse_types(env)
2484 self.positional_args.analyse_types(env)
2485 if self.keyword_args:
2486 self.keyword_args.analyse_types(env)
2487 if self.starstar_arg:
2488 self.starstar_arg.analyse_types(env)
2489 if not self.function.type.is_pyobject:
2490 if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
2491 error(self.pos, "Keyword arguments not allowed in cdef functions.")
2492 else:
2493 self.function = self.function.coerce_to_pyobject(env)
2494 self.positional_args = \
2495 self.positional_args.coerce_to_pyobject(env)
2496 if self.starstar_arg:
2497 self.starstar_arg = \
2498 self.starstar_arg.coerce_to_pyobject(env)
2499 function = self.function
2500 if function.is_name and function.type_entry:
2501 # We are calling an extension type constructor. As long
2502 # as we do not support __new__(), the result type is clear
2503 self.type = function.type_entry.type
2504 self.result_ctype = py_object_type
2505 else:
2506 self.type = py_object_type
2507 self.is_temp = 1
2509 def generate_result_code(self, code):
2510 if self.keyword_args and self.starstar_arg:
2511 code.put_error_if_neg(self.pos,
2512 "PyDict_Update(%s, %s)" % (
2513 self.keyword_args.py_result(),
2514 self.starstar_arg.py_result()))
2515 keyword_code = self.keyword_args.py_result()
2516 elif self.keyword_args:
2517 keyword_code = self.keyword_args.py_result()
2518 elif self.starstar_arg:
2519 keyword_code = self.starstar_arg.py_result()
2520 else:
2521 keyword_code = None
2522 if not keyword_code:
2523 call_code = "PyObject_Call(%s, %s, NULL)" % (
2524 self.function.py_result(),
2525 self.positional_args.py_result())
2526 else:
2527 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2528 self.function.py_result(),
2529 self.positional_args.py_result(),
2530 keyword_code)
2531 code.putln(
2532 "%s = %s; %s" % (
2533 self.result(),
2534 call_code,
2535 code.error_goto_if_null(self.result(), self.pos)))
2536 code.put_gotref(self.py_result())
2539 class AsTupleNode(ExprNode):
2540 # Convert argument to tuple. Used for normalising
2541 # the * argument of a function call.
2542 #
2543 # arg ExprNode
2545 subexprs = ['arg']
2547 def calculate_constant_result(self):
2548 self.constant_result = tuple(self.base.constant_result)
2550 def compile_time_value(self, denv):
2551 arg = self.arg.compile_time_value(denv)
2552 try:
2553 return tuple(arg)
2554 except Exception, e:
2555 self.compile_time_value_error(e)
2557 def analyse_types(self, env):
2558 self.arg.analyse_types(env)
2559 self.arg = self.arg.coerce_to_pyobject(env)
2560 self.type = tuple_type
2561 self.is_temp = 1
2563 nogil_check = Node.gil_error
2564 gil_message = "Constructing Python tuple"
2566 def generate_result_code(self, code):
2567 code.putln(
2568 "%s = PySequence_Tuple(%s); %s" % (
2569 self.result(),
2570 self.arg.py_result(),
2571 code.error_goto_if_null(self.result(), self.pos)))
2572 code.put_gotref(self.py_result())
2575 class AttributeNode(ExprNode):
2576 # obj.attribute
2577 #
2578 # obj ExprNode
2579 # attribute string
2580 # needs_none_check boolean Used if obj is an extension type.
2581 # If set to True, it is known that the type is not None.
2582 #
2583 # Used internally:
2584 #
2585 # is_py_attr boolean Is a Python getattr operation
2586 # member string C name of struct member
2587 # is_called boolean Function call is being done on result
2588 # entry Entry Symbol table entry of attribute
2590 is_attribute = 1
2591 subexprs = ['obj']
2593 type = PyrexTypes.error_type
2594 entry = None
2595 is_called = 0
2596 needs_none_check = True
2598 def as_cython_attribute(self):
2599 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2600 return self.attribute
2602 def coerce_to(self, dst_type, env):
2603 # If coercing to a generic pyobject and this is a cpdef function
2604 # we can create the corresponding attribute
2605 if dst_type is py_object_type:
2606 entry = self.entry
2607 if entry and entry.is_cfunction and entry.as_variable:
2608 # must be a cpdef function
2609 self.is_temp = 1
2610 self.entry = entry.as_variable
2611 self.analyse_as_python_attribute(env)
2612 return self
2613 return ExprNode.coerce_to(self, dst_type, env)
2615 def calculate_constant_result(self):
2616 attr = self.attribute
2617 if attr.startswith("__") and attr.endswith("__"):
2618 return
2619 self.constant_result = getattr(self.obj.constant_result, attr)
2621 def compile_time_value(self, denv):
2622 attr = self.attribute
2623 if attr.startswith("__") and attr.endswith("__"):
2624 error(self.pos,
2625 "Invalid attribute name '%s' in compile-time expression" % attr)
2626 return None
2627 obj = self.obj.compile_time_value(denv)
2628 try:
2629 return getattr(obj, attr)
2630 except Exception, e:
2631 self.compile_time_value_error(e)
2633 def analyse_target_declaration(self, env):
2634 pass
2636 def analyse_target_types(self, env):
2637 self.analyse_types(env, target = 1)
2639 def analyse_types(self, env, target = 0):
2640 if self.analyse_as_cimported_attribute(env, target):
2641 return
2642 if not target and self.analyse_as_unbound_cmethod(env):
2643 return
2644 self.analyse_as_ordinary_attribute(env, target)
2646 def analyse_as_cimported_attribute(self, env, target):
2647 # Try to interpret this as a reference to an imported
2648 # C const, type, var or function. If successful, mutates
2649 # this node into a NameNode and returns 1, otherwise
2650 # returns 0.
2651 module_scope = self.obj.analyse_as_module(env)
2652 if module_scope:
2653 entry = module_scope.lookup_here(self.attribute)
2654 if entry and (
2655 entry.is_cglobal or entry.is_cfunction
2656 or entry.is_type or entry.is_const):
2657 self.mutate_into_name_node(env, entry, target)
2658 return 1
2659 return 0
2661 def analyse_as_unbound_cmethod(self, env):
2662 # Try to interpret this as a reference to an unbound
2663 # C method of an extension type. If successful, mutates
2664 # this node into a NameNode and returns 1, otherwise
2665 # returns 0.
2666 type = self.obj.analyse_as_extension_type(env)
2667 if type:
2668 entry = type.scope.lookup_here(self.attribute)
2669 if entry and entry.is_cmethod:
2670 # Create a temporary entry describing the C method
2671 # as an ordinary function.
2672 ubcm_entry = Symtab.Entry(entry.name,
2673 "%s->%s" % (type.vtabptr_cname, entry.cname),
2674 entry.type)
2675 ubcm_entry.is_cfunction = 1
2676 ubcm_entry.func_cname = entry.func_cname
2677 ubcm_entry.is_unbound_cmethod = 1
2678 self.mutate_into_name_node(env, ubcm_entry, None)
2679 return 1
2680 return 0
2682 def analyse_as_type(self, env):
2683 module_scope = self.obj.analyse_as_module(env)
2684 if module_scope:
2685 return module_scope.lookup_type(self.attribute)
2686 return None
2688 def analyse_as_extension_type(self, env):
2689 # Try to interpret this as a reference to an extension type
2690 # in a cimported module. Returns the extension type, or None.
2691 module_scope = self.obj.analyse_as_module(env)
2692 if module_scope:
2693 entry = module_scope.lookup_here(self.attribute)
2694 if entry and entry.is_type and entry.type.is_extension_type:
2695 return entry.type
2696 return None
2698 def analyse_as_module(self, env):
2699 # Try to interpret this as a reference to a cimported module
2700 # in another cimported module. Returns the module scope, or None.
2701 module_scope = self.obj.analyse_as_module(env)
2702 if module_scope:
2703 entry = module_scope.lookup_here(self.attribute)
2704 if entry and entry.as_module:
2705 return entry.as_module
2706 return None
2708 def mutate_into_name_node(self, env, entry, target):
2709 # Mutate this node into a NameNode and complete the
2710 # analyse_types phase.
2711 self.__class__ = NameNode
2712 self.name = self.attribute
2713 self.entry = entry
2714 del self.obj
2715 del self.attribute
2716 if target:
2717 NameNode.analyse_target_types(self, env)
2718 else:
2719 NameNode.analyse_rvalue_entry(self, env)
2721 def analyse_as_ordinary_attribute(self, env, target):
2722 self.obj.analyse_types(env)
2723 self.analyse_attribute(env)
2724 if self.entry and self.entry.is_cmethod and not self.is_called:
2725 # error(self.pos, "C method can only be called")
2726 pass
2727 ## Reference to C array turns into pointer to first element.
2728 #while self.type.is_array:
2729 # self.type = self.type.element_ptr_type()
2730 if self.is_py_attr:
2731 if not target:
2732 self.is_temp = 1
2733 self.result_ctype = py_object_type
2735 def analyse_attribute(self, env):
2736 # Look up attribute and set self.type and self.member.
2737 self.is_py_attr = 0
2738 self.member = self.attribute
2739 if self.obj.type.is_string:
2740 self.obj = self.obj.coerce_to_pyobject(env)
2741 obj_type = self.obj.type
2742 if obj_type.is_ptr or obj_type.is_array:
2743 obj_type = obj_type.base_type
2744 self.op = "->"
2745 elif obj_type.is_extension_type:
2746 self.op = "->"
2747 else:
2748 self.op = "."
2749 if obj_type.has_attributes:
2750 entry = None
2751 if obj_type.attributes_known():
2752 entry = obj_type.scope.lookup_here(self.attribute)
2753 if entry and entry.is_member:
2754 entry = None
2755 else:
2756 error(self.pos,
2757 "Cannot select attribute of incomplete type '%s'"
2758 % obj_type)
2759 self.type = PyrexTypes.error_type
2760 return
2761 self.entry = entry
2762 if entry:
2763 if obj_type.is_extension_type and entry.name == "__weakref__":
2764 error(self.pos, "Illegal use of special attribute __weakref__")
2765 # methods need the normal attribute lookup
2766 # because they do not have struct entries
2767 if entry.is_variable or entry.is_cmethod:
2768 self.type = entry.type
2769 self.member = entry.cname
2770 return
2771 else:
2772 # If it's not a variable or C method, it must be a Python
2773 # method of an extension type, so we treat it like a Python
2774 # attribute.
2775 pass
2776 # If we get here, the base object is not a struct/union/extension
2777 # type, or it is an extension type and the attribute is either not
2778 # declared or is declared as a Python method. Treat it as a Python
2779 # attribute reference.
2780 self.analyse_as_python_attribute(env)
2782 def analyse_as_python_attribute(self, env):
2783 obj_type = self.obj.type
2784 self.member = self.attribute
2785 if obj_type.is_pyobject:
2786 self.type = py_object_type
2787 self.is_py_attr = 1
2788 else:
2789 if not obj_type.is_error:
2790 error(self.pos,
2791 "Object of type '%s' has no attribute '%s'" %
2792 (obj_type, self.attribute))
2794 def nogil_check(self, env):
2795 if self.is_py_attr:
2796 self.gil_error()
2798 gil_message = "Accessing Python attribute"
2800 def is_simple(self):
2801 if self.obj:
2802 return self.result_in_temp() or self.obj.is_simple()
2803 else:
2804 return NameNode.is_simple(self)
2806 def is_lvalue(self):
2807 if self.obj:
2808 return 1
2809 else:
2810 return NameNode.is_lvalue(self)
2812 def is_ephemeral(self):
2813 if self.obj:
2814 return self.obj.is_ephemeral()
2815 else:
2816 return NameNode.is_ephemeral(self)
2818 def calculate_result_code(self):
2819 #print "AttributeNode.calculate_result_code:", self.member ###
2820 #print "...obj node =", self.obj, "code", self.obj.result() ###
2821 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2822 obj = self.obj
2823 obj_code = obj.result_as(obj.type)
2824 #print "...obj_code =", obj_code ###
2825 if self.entry and self.entry.is_cmethod:
2826 if obj.type.is_extension_type:
2827 return "((struct %s *)%s%s%s)->%s" % (
2828 obj.type.vtabstruct_cname, obj_code, self.op,
2829 obj.type.vtabslot_cname, self.member)
2830 else:
2831 return self.member
2832 elif obj.type.is_complex:
2833 return "__Pyx_%s_PART(%s)" % (self.member.upper(), obj_code)
2834 else:
2835 return "%s%s%s" % (obj_code, self.op, self.member)
2837 def generate_result_code(self, code):
2838 interned_attr_cname = code.intern_identifier(self.attribute)
2839 if self.is_py_attr:
2840 code.putln(
2841 '%s = PyObject_GetAttr(%s, %s); %s' % (
2842 self.result(),
2843 self.obj.py_result(),
2844 interned_attr_cname,
2845 code.error_goto_if_null(self.result(), self.pos)))
2846 code.put_gotref(self.py_result())
2847 else:
2848 # result_code contains what is needed, but we may need to insert
2849 # a check and raise an exception
2850 if (self.obj.type.is_extension_type
2851 and self.needs_none_check
2852 and code.globalstate.directives['nonecheck']):
2853 self.put_nonecheck(code)
2855 def generate_assignment_code(self, rhs, code):
2856 interned_attr_cname = code.intern_identifier(self.attribute)
2857 self.obj.generate_evaluation_code(code)
2858 if self.is_py_attr:
2859 code.put_error_if_neg(self.pos,
2860 'PyObject_SetAttr(%s, %s, %s)' % (
2861 self.obj.py_result(),
2862 interned_attr_cname,
2863 rhs.py_result()))
2864 rhs.generate_disposal_code(code)
2865 rhs.free_temps(code)
2866 else:
2867 if (self.obj.type.is_extension_type
2868 and self.needs_none_check
2869 and code.globalstate.directives['nonecheck']):
2870 self.put_nonecheck(code)
2872 select_code = self.result()
2873 if self.type.is_pyobject:
2874 rhs.make_owned_reference(code)
2875 code.put_giveref(rhs.py_result())
2876 code.put_gotref(select_code)
2877 code.put_decref(select_code, self.ctype())
2878 code.putln(
2879 "%s = %s;" % (
2880 select_code,
2881 rhs.result_as(self.ctype())))
2882 #rhs.result()))
2883 rhs.generate_post_assignment_code(code)
2884 rhs.free_temps(code)
2885 self.obj.generate_disposal_code(code)
2886 self.obj.free_temps(code)
2888 def generate_deletion_code(self, code):
2889 interned_attr_cname = code.intern_identifier(self.attribute)
2890 self.obj.generate_evaluation_code(code)
2891 if self.is_py_attr:
2892 code.put_error_if_neg(self.pos,
2893 'PyObject_DelAttr(%s, %s)' % (
2894 self.obj.py_result(),
2895 interned_attr_cname))
2896 else:
2897 error(self.pos, "Cannot delete C attribute of extension type")
2898 self.obj.generate_disposal_code(code)
2899 self.obj.free_temps(code)
2901 def annotate(self, code):
2902 if self.is_py_attr:
2903 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2904 else:
2905 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2907 def put_nonecheck(self, code):
2908 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
2909 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
2910 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
2911 code.putln(code.error_goto(self.pos))
2912 code.putln("}")
2915 #-------------------------------------------------------------------
2916 #
2917 # Constructor nodes
2918 #
2919 #-------------------------------------------------------------------
2921 class StarredTargetNode(ExprNode):
2922 # A starred expression like "*a"
2923 #
2924 # This is only allowed in sequence assignment targets such as
2925 #
2926 # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4]
2927 #
2928 # and will be removed during type analysis (or generate an error
2929 # if it's found at unexpected places).
2930 #
2931 # target ExprNode
2933 subexprs = ['target']
2934 is_starred = 1
2935 type = py_object_type
2937 def __init__(self, pos, target):
2938 self.pos = pos
2939 self.target = target
2941 def analyse_declarations(self, env):
2942 error(self.pos, "can use starred expression only as assignment target")
2943 self.target.analyse_declarations(env)
2945 def analyse_types(self, env):
2946 error(self.pos, "can use starred expression only as assignment target")
2947 self.target.analyse_types(env)
2948 self.type = self.target.type
2950 def analyse_target_declaration(self, env):
2951 self.target.analyse_target_declaration(env)
2953 def analyse_target_types(self, env):
2954 self.target.analyse_target_types(env)
2955 self.type = self.target.type
2957 def calculate_result_code(self):
2958 return ""
2960 def generate_result_code(self, code):
2961 pass
2964 class SequenceNode(ExprNode):
2965 # Base class for list and tuple constructor nodes.
2966 # Contains common code for performing sequence unpacking.
2967 #
2968 # args [ExprNode]
2969 # iterator ExprNode
2970 # unpacked_items [ExprNode] or None
2971 # coerced_unpacked_items [ExprNode] or None
2973 subexprs = ['args']
2975 is_sequence_constructor = 1
2976 unpacked_items = None
2978 def compile_time_value_list(self, denv):
2979 return [arg.compile_time_value(denv) for arg in self.args]
2981 def replace_starred_target_node(self):
2982 # replace a starred node in the targets by the contained expression
2983 self.starred_assignment = False
2984 args = []
2985 for arg in self.args:
2986 if arg.is_starred:
2987 if self.starred_assignment:
2988 error(arg.pos, "more than 1 starred expression in assignment")
2989 self.starred_assignment = True
2990 arg = arg.target
2991 arg.is_starred = True
2992 args.append(arg)
2993 self.args = args
2995 def analyse_target_declaration(self, env):
2996 self.replace_starred_target_node()
2997 for arg in self.args:
2998 arg.analyse_target_declaration(env)
3000 def analyse_types(self, env, skip_children=False):
3001 for i in range(len(self.args)):
3002 arg = self.args[i]
3003 if not skip_children: arg.analyse_types(env)
3004 self.args[i] = arg.coerce_to_pyobject(env)
3005 self.type = py_object_type
3006 self.is_temp = 1
3008 def analyse_target_types(self, env):
3009 self.iterator = PyTempNode(self.pos, env)
3010 self.unpacked_items = []
3011 self.coerced_unpacked_items = []
3012 for arg in self.args:
3013 arg.analyse_target_types(env)
3014 if arg.is_starred:
3015 if not arg.type.assignable_from(Builtin.list_type):
3016 error(arg.pos,
3017 "starred target must have Python object (list) type")
3018 if arg.type is py_object_type:
3019 arg.type = Builtin.list_type
3020 unpacked_item = PyTempNode(self.pos, env)
3021 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
3022 self.unpacked_items.append(unpacked_item)
3023 self.coerced_unpacked_items.append(coerced_unpacked_item)
3024 self.type = py_object_type
3026 def generate_result_code(self, code):
3027 self.generate_operation_code(code)
3029 def generate_assignment_code(self, rhs, code):
3030 if self.starred_assignment:
3031 self.generate_starred_assignment_code(rhs, code)
3032 else:
3033 self.generate_parallel_assignment_code(rhs, code)
3035 for item in self.unpacked_items:
3036 item.release(code)
3037 rhs.free_temps(code)
3039 def generate_parallel_assignment_code(self, rhs, code):
3040 # Need to work around the fact that generate_evaluation_code
3041 # allocates the temps in a rather hacky way -- the assignment
3042 # is evaluated twice, within each if-block.
3044 code.globalstate.use_utility_code(unpacking_utility_code)
3046 if rhs.type is tuple_type:
3047 tuple_check = "likely(%s != Py_None)"
3048 else:
3049 tuple_check = "PyTuple_CheckExact(%s)"
3050 code.putln(
3051 "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
3052 tuple_check % rhs.py_result(),
3053 rhs.py_result(),
3054 len(self.args)))
3055 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3056 for item in self.unpacked_items:
3057 item.allocate(code)
3058 for i in range(len(self.args)):
3059 item = self.unpacked_items[i]
3060 code.put(
3061 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3062 item.result(),
3063 i))
3064 code.put_incref(item.result(), item.ctype())
3065 value_node = self.coerced_unpacked_items[i]
3066 value_node.generate_evaluation_code(code)
3067 rhs.generate_disposal_code(code)
3069 for i in range(len(self.args)):
3070 self.args[i].generate_assignment_code(
3071 self.coerced_unpacked_items[i], code)
3073 code.putln("} else {")
3075 if rhs.type is tuple_type:
3076 code.globalstate.use_utility_code(tuple_unpacking_error_code)
3077 code.putln("__Pyx_UnpackTupleError(%s, %s);" % (
3078 rhs.py_result(), len(self.args)))
3079 code.putln(code.error_goto(self.pos))
3080 else:
3081 self.iterator.allocate(code)
3082 code.putln(
3083 "%s = PyObject_GetIter(%s); %s" % (
3084 self.iterator.result(),
3085 rhs.py_result(),
3086 code.error_goto_if_null(self.iterator.result(), self.pos)))
3087 code.put_gotref(self.iterator.py_result())
3088 rhs.generate_disposal_code(code)
3089 for i in range(len(self.args)):
3090 item = self.unpacked_items[i]
3091 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3092 self.iterator.py_result(), i)
3093 code.putln(
3094 "%s = %s; %s" % (
3095 item.result(),
3096 typecast(item.ctype(), py_object_type, unpack_code),
3097 code.error_goto_if_null(item.result(), self.pos)))
3098 code.put_gotref(item.py_result())
3099 value_node = self.coerced_unpacked_items[i]
3100 value_node.generate_evaluation_code(code)
3101 code.put_error_if_neg(self.pos,
3102 "__Pyx_EndUnpack(%s)" % (
3103 self.iterator.py_result()))
3104 if debug_disposal_code:
3105 print("UnpackNode.generate_assignment_code:")
3106 print("...generating disposal code for %s" % self.iterator)
3107 self.iterator.generate_disposal_code(code)
3108 self.iterator.free_temps(code)
3109 self.iterator.release(code)
3111 for i in range(len(self.args)):
3112 self.args[i].generate_assignment_code(
3113 self.coerced_unpacked_items[i], code)
3115 code.putln("}")
3117 def generate_starred_assignment_code(self, rhs, code):
3118 code.globalstate.use_utility_code(unpacking_utility_code)
3120 for i, arg in enumerate(self.args):
3121 if arg.is_starred:
3122 starred_target = self.unpacked_items[i]
3123 fixed_args_left = self.args[:i]
3124 fixed_args_right = self.args[i+1:]
3125 break
3127 self.iterator.allocate(code)
3128 code.putln(
3129 "%s = PyObject_GetIter(%s); %s" % (
3130 self.iterator.result(),
3131 rhs.py_result(),
3132 code.error_goto_if_null(self.iterator.result(), self.pos)))
3133 code.put_gotref(self.iterator.py_result())
3134 rhs.generate_disposal_code(code)
3136 for item in self.unpacked_items:
3137 item.allocate(code)
3138 for i in range(len(fixed_args_left)):
3139 item = self.unpacked_items[i]
3140 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3141 self.iterator.py_result(), i)
3142 code.putln(
3143 "%s = %s; %s" % (
3144 item.result(),
3145 typecast(item.ctype(), py_object_type, unpack_code),
3146 code.error_goto_if_null(item.result(), self.pos)))
3147 code.put_gotref(item.py_result())
3148 value_node = self.coerced_unpacked_items[i]
3149 value_node.generate_evaluation_code(code)
3151 target_list = starred_target.result()
3152 code.putln("%s = PySequence_List(%s); %s" % (
3153 target_list, self.iterator.py_result(),
3154 code.error_goto_if_null(target_list, self.pos)))
3155 code.put_gotref(target_list)
3156 if fixed_args_right:
3157 code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
3158 unpacked_right_args = self.unpacked_items[-len(fixed_args_right):]
3159 code.putln("if (unlikely(PyList_GET_SIZE(%s) < %d)) {" % (
3160 (target_list, len(unpacked_right_args))))
3161 code.put("__Pyx_RaiseNeedMoreValuesError(%d+PyList_GET_SIZE(%s)); %s" % (
3162 len(fixed_args_left), target_list,
3163 code.error_goto(self.pos)))
3164 code.putln('}')
3165 for i, (arg, coerced_arg) in enumerate(zip(unpacked_right_args[::-1],
3166 self.coerced_unpacked_items[::-1])):
3167 code.putln(
3168 "%s = PyList_GET_ITEM(%s, PyList_GET_SIZE(%s)-1); " % (
3169 arg.py_result(),
3170 target_list, target_list))
3171 # resize the list the hard way
3172 code.putln("((PyVarObject*)%s)->ob_size--;" % target_list)
3173 code.put_gotref(arg.py_result())
3174 coerced_arg.generate_evaluation_code(code)
3176 self.iterator.generate_disposal_code(code)
3177 self.iterator.free_temps(code)
3178 self.iterator.release(code)
3180 for i in range(len(self.args)):
3181 self.args[i].generate_assignment_code(
3182 self.coerced_unpacked_items[i], code)
3184 def annotate(self, code):
3185 for arg in self.args:
3186 arg.annotate(code)
3187 if self.unpacked_items:
3188 for arg in self.unpacked_items:
3189 arg.annotate(code)
3190 for arg in self.coerced_unpacked_items:
3191 arg.annotate(code)
3194 class TupleNode(SequenceNode):
3195 # Tuple constructor.
3197 gil_message = "Constructing Python tuple"
3199 def analyse_types(self, env, skip_children=False):
3200 if len(self.args) == 0:
3201 self.is_temp = 0
3202 self.is_literal = 1
3203 else:
3204 SequenceNode.analyse_types(self, env, skip_children)
3205 self.type = tuple_type
3207 def calculate_result_code(self):
3208 if len(self.args) > 0:
3209 error(self.pos, "Positive length tuples must be constructed.")
3210 else:
3211 return Naming.empty_tuple
3213 def calculate_constant_result(self):
3214 self.constant_result = tuple([
3215 arg.constant_result for arg in self.args])
3217 def compile_time_value(self, denv):
3218 values = self.compile_time_value_list(denv)
3219 try:
3220 return tuple(values)
3221 except Exception, e:
3222 self.compile_time_value_error(e)
3224 def generate_operation_code(self, code):
3225 if len(self.args) == 0:
3226 # result_code is Naming.empty_tuple
3227 return
3228 code.putln(
3229 "%s = PyTuple_New(%s); %s" % (
3230 self.result(),
3231 len(self.args),
3232 code.error_goto_if_null(self.result(), self.pos)))
3233 code.put_gotref(self.py_result())
3234 for i in range(len(self.args)):
3235 arg = self.args[i]
3236 if not arg.result_in_temp():
3237 code.put_incref(arg.result(), arg.ctype())
3238 code.putln(
3239 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3240 self.result(),
3241 i,
3242 arg.py_result()))
3243 code.put_giveref(arg.py_result())
3245 def generate_subexpr_disposal_code(self, code):
3246 # We call generate_post_assignment_code here instead
3247 # of generate_disposal_code, because values were stored
3248 # in the tuple using a reference-stealing operation.
3249 for arg in self.args:
3250 arg.generate_post_assignment_code(code)
3251 # Should NOT call free_temps -- this is invoked by the default
3252 # generate_evaluation_code which will do that.
3255 class ListNode(SequenceNode):
3256 # List constructor.
3258 # obj_conversion_errors [PyrexError] used internally
3259 # orignial_args [ExprNode] used internally
3261 gil_message = "Constructing Python list"
3263 def analyse_expressions(self, env):
3264 SequenceNode.analyse_expressions(self, env)
3265 self.coerce_to_pyobject(env)
3267 def analyse_types(self, env):
3268 hold_errors()
3269 self.original_args = list(self.args)
3270 SequenceNode.analyse_types(self, env)
3271 self.type = list_type
3272 self.obj_conversion_errors = held_errors()
3273 release_errors(ignore=True)
3275 def coerce_to(self, dst_type, env):
3276 if dst_type.is_pyobject:
3277 for err in self.obj_conversion_errors:
3278 report_error(err)
3279 self.obj_conversion_errors = []
3280 if not self.type.subtype_of(dst_type):
3281 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3282 elif dst_type.is_ptr:
3283 base_type = dst_type.base_type
3284 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3285 for i in range(len(self.original_args)):
3286 arg = self.args[i]
3287 if isinstance(arg, CoerceToPyTypeNode):
3288 arg = arg.arg
3289 self.args[i] = arg.coerce_to(base_type, env)
3290 elif dst_type.is_struct:
3291 if len(self.args) > len(dst_type.scope.var_entries):
3292 error(self.pos, "Too may members for '%s'" % dst_type)
3293 else:
3294 if len(self.args) < len(dst_type.scope.var_entries):
3295 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3296 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3297 if isinstance(arg, CoerceToPyTypeNode):
3298 arg = arg.arg
3299 self.args[i] = arg.coerce_to(member.type, env)
3300 self.type = dst_type
3301 else:
3302 self.type = error_type
3303 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3304 return self
3306 def release_temp(self, env):
3307 if self.type.is_array:
3308 # To be valid C++, we must allocate the memory on the stack
3309 # manually and be sure not to reuse it for something else.
3310 pass
3311 else:
3312 SequenceNode.release_temp(self, env)
3314 def calculate_constant_result(self):
3315 self.constant_result = [
3316 arg.constant_result for arg in self.args]
3318 def compile_time_value(self, denv):
3319 return self.compile_time_value_list(denv)
3321 def generate_operation_code(self, code):
3322 if self.type.is_pyobject:
3323 for err in self.obj_conversion_errors:
3324 report_error(err)
3325 code.putln("%s = PyList_New(%s); %s" %
3326 (self.result(),
3327 len(self.args),
3328 code.error_goto_if_null(self.result(), self.pos)))
3329 code.put_gotref(self.py_result())
3330 for i in range(len(self.args)):
3331 arg = self.args[i]
3332 #if not arg.is_temp:
3333 if not arg.result_in_temp():
3334 code.put_incref(arg.result(), arg.ctype())
3335 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3336 (self.result(),
3337 i,
3338 arg.py_result()))
3339 code.put_giveref(arg.py_result())
3340 elif self.type.is_array:
3341 for i, arg in enumerate(self.args):
3342 code.putln("%s[%s] = %s;" % (
3343 self.result(),
3344 i,
3345 arg.result()))
3346 elif self.type.is_struct:
3347 for arg, member in zip(self.args, self.type.scope.var_entries):
3348 code.putln("%s.%s = %s;" % (
3349 self.result(),
3350 member.cname,
3351 arg.result()))
3352 else:
3353 raise InternalError("List type never specified")
3355 def generate_subexpr_disposal_code(self, code):
3356 # We call generate_post_assignment_code here instead
3357 # of generate_disposal_code, because values were stored
3358 # in the list using a reference-stealing operation.
3359 for arg in self.args:
3360 arg.generate_post_assignment_code(code)
3361 # Should NOT call free_temps -- this is invoked by the default
3362 # generate_evaluation_code which will do that.
3365 class ComprehensionNode(ExprNode):
3366 subexprs = ["target"]
3367 child_attrs = ["loop", "append"]
3369 def analyse_types(self, env):
3370 self.target.analyse_expressions(env)
3371 self.type = self.target.type
3372 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3373 self.loop.analyse_declarations(env)
3374 self.loop.analyse_expressions(env)
3376 def calculate_result_code(self):
3377 return self.target.result()
3379 def generate_result_code(self, code):
3380 self.generate_operation_code(code)
3382 def generate_operation_code(self, code):
3383 self.loop.generate_execution_code(code)
3385 def annotate(self, code):
3386 self.loop.annotate(code)
3389 class ComprehensionAppendNode(ExprNode):
3390 # Need to be careful to avoid infinite recursion:
3391 # target must not be in child_attrs/subexprs
3392 subexprs = ['expr']
3394 def analyse_types(self, env):
3395 self.expr.analyse_types(env)
3396 if not self.expr.type.is_pyobject:
3397 self.expr = self.expr.coerce_to_pyobject(env)
3398 self.type = PyrexTypes.c_int_type
3399 self.is_temp = 1
3401 def generate_result_code(self, code):
3402 if self.target.type is list_type:
3403 function = "PyList_Append"
3404 elif self.target.type is set_type:
3405 function = "PySet_Add"
3406 else:
3407 raise InternalError(
3408 "Invalid type for comprehension node: %s" % self.target.type)
3410 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3411 (self.result(),
3412 function,
3413 self.target.result(),
3414 self.expr.result(),
3415 code.error_goto_if(self.result(), self.pos)))
3417 class DictComprehensionAppendNode(ComprehensionAppendNode):
3418 subexprs = ['key_expr', 'value_expr']
3420 def analyse_types(self, env):
3421 self.key_expr.analyse_types(env)
3422 if not self.key_expr.type.is_pyobject:
3423 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3424 self.value_expr.analyse_types(env)
3425 if not self.value_expr.type.is_pyobject:
3426 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3427 self.type = PyrexTypes.c_int_type
3428 self.is_temp = 1
3430 def generate_result_code(self, code):
3431 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3432 (self.result(),
3433 self.target.result(),
3434 self.key_expr.result(),
3435 self.value_expr.result(),
3436 code.error_goto_if(self.result(), self.pos)))
3439 class SetNode(ExprNode):
3440 # Set constructor.
3442 subexprs = ['args']
3444 gil_message = "Constructing Python set"
3446 def analyse_types(self, env):
3447 for i in range(len(self.args)):
3448 arg = self.args[i]
3449 arg.analyse_types(env)
3450 self.args[i] = arg.coerce_to_pyobject(env)
3451 self.type = set_type
3452 self.is_temp = 1
3454 def calculate_constant_result(self):
3455 self.constant_result = set([
3456 arg.constant_result for arg in self.args])
3458 def compile_time_value(self, denv):
3459 values = [arg.compile_time_value(denv) for arg in self.args]
3460 try:
3461 return set(values)
3462 except Exception, e:
3463 self.compile_time_value_error(e)
3465 def generate_evaluation_code(self, code):
3466 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3467 self.allocate_temp_result(code)
3468 code.putln(
3469 "%s = PySet_New(0); %s" % (
3470 self.result(),
3471 code.error_goto_if_null(self.result(), self.pos)))
3472 code.put_gotref(self.py_result())
3473 for arg in self.args:
3474 arg.generate_evaluation_code(code)
3475 code.putln(
3476 code.error_goto_if_neg(
3477 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3478 self.pos))
3479 arg.generate_disposal_code(code)
3480 arg.free_temps(code)
3483 class DictNode(ExprNode):
3484 # Dictionary constructor.
3485 #
3486 # key_value_pairs [DictItemNode]
3487 #
3488 # obj_conversion_errors [PyrexError] used internally
3490 subexprs = ['key_value_pairs']
3492 def calculate_constant_result(self):
3493 self.constant_result = dict([
3494 item.constant_result for item in self.key_value_pairs])
3496 def compile_time_value(self, denv):
3497 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3498 for item in self.key_value_pairs]
3499 try:
3500 return dict(pairs)
3501 except Exception, e:
3502 self.compile_time_value_error(e)
3504 def analyse_types(self, env):
3505 hold_errors()
3506 self.type = dict_type
3507 for item in self.key_value_pairs:
3508 item.analyse_types(env)
3509 self.obj_conversion_errors = held_errors()
3510 release_errors(ignore=True)
3511 self.is_temp = 1
3513 def coerce_to(self, dst_type, env):
3514 if dst_type.is_pyobject:
3515 self.release_errors()
3516 if not self.type.subtype_of(dst_type):
3517 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3518 elif dst_type.is_struct_or_union:
3519 self.type = dst_type
3520 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3521 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3522 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3523 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3524 for item in self.key_value_pairs:
3525 if isinstance(item.key, CoerceToPyTypeNode):
3526 item.key = item.key.arg
3527 if not isinstance(item.key, (StringNode, IdentifierStringNode)):
3528 error(item.key.pos, "Invalid struct field identifier")
3529 item.key = IdentifierStringNode(item.key.pos, value="<error>")
3530 else:
3531 member = dst_type.scope.lookup_here(item.key.value)
3532 if not member:
3533 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, item.key.value))
3534 else:
3535 value = item.value
3536 if isinstance(value, CoerceToPyTypeNode):
3537 value = value.arg
3538 item.value = value.coerce_to(member.type, env)
3539 else:
3540 self.type = error_type
3541 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3542 return self
3544 def release_errors(self):
3545 for err in self.obj_conversion_errors:
3546 report_error(err)
3547 self.obj_conversion_errors = []
3549 gil_message = "Constructing Python dict"
3551 def generate_evaluation_code(self, code):
3552 # Custom method used here because key-value
3553 # pairs are evaluated and used one at a time.
3554 code.mark_pos(self.pos)
3555 self.allocate_temp_result(code)
3556 if self.type.is_pyobject:
3557 self.release_errors()
3558 code.putln(
3559 "%s = PyDict_New(); %s" % (
3560 self.result(),
3561 code.error_goto_if_null(self.result(), self.pos)))
3562 code.put_gotref(self.py_result())
3563 for item in self.key_value_pairs:
3564 item.generate_evaluation_code(code)
3565 if self.type.is_pyobject:
3566 code.put_error_if_neg(self.pos,
3567 "PyDict_SetItem(%s, %s, %s)" % (
3568 self.result(),
3569 item.key.py_result(),
3570 item.value.py_result()))
3571 else:
3572 code.putln("%s.%s = %s;" % (
3573 self.result(),
3574 item.key.value,
3575 item.value.result()))
3576 item.generate_disposal_code(code)
3577 item.free_temps(code)
3579 def annotate(self, code):
3580 for item in self.key_value_pairs:
3581 item.annotate(code)
3583 class DictItemNode(ExprNode):
3584 # Represents a single item in a DictNode
3585 #
3586 # key ExprNode
3587 # value ExprNode
3588 subexprs = ['key', 'value']
3590 nogil_check = None # Parent DictNode takes care of it
3592 def calculate_constant_result(self):
3593 self.constant_result = (
3594 self.key.constant_result, self.value.constant_result)
3596 def analyse_types(self, env):
3597 self.key.analyse_types(env)
3598 self.value.analyse_types(env)
3599 self.key = self.key.coerce_to_pyobject(env)
3600 self.value = self.value.coerce_to_pyobject(env)
3602 def generate_evaluation_code(self, code):
3603 self.key.generate_evaluation_code(code)
3604 self.value.generate_evaluation_code(code)
3606 def generate_disposal_code(self, code):
3607 self.key.generate_disposal_code(code)
3608 self.value.generate_disposal_code(code)
3610 def free_temps(self, code):
3611 self.key.free_temps(code)
3612 self.value.free_temps(code)
3614 def __iter__(self):
3615 return iter([self.key, self.value])
3618 class ClassNode(ExprNode):
3619 # Helper class used in the implementation of Python
3620 # class definitions. Constructs a class object given
3621 # a name, tuple of bases and class dictionary.
3622 #
3623 # name EncodedString Name of the class
3624 # bases ExprNode Base class tuple
3625 # dict ExprNode Class dict (not owned by this node)
3626 # doc ExprNode or None Doc string
3627 # module_name string Name of defining module
3629 subexprs = ['bases', 'doc']
3631 def analyse_types(self, env):
3632 self.bases.analyse_types(env)
3633 if self.doc:
3634 self.doc.analyse_types(env)
3635 self.doc = self.doc.coerce_to_pyobject(env)
3636 self.module_name = env.global_scope().qualified_name
3637 self.type = py_object_type
3638 self.is_temp = 1
3639 env.use_utility_code(create_class_utility_code);
3641 gil_message = "Constructing Python class"
3643 def generate_result_code(self, code):
3644 cname = code.intern_identifier(self.name)
3645 if self.doc:
3646 code.put_error_if_neg(self.pos,
3647 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3648 self.dict.py_result(),
3649 self.doc.py_result()))
3650 code.putln(
3651 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3652 self.result(),
3653 self.bases.py_result(),
3654 self.dict.py_result(),
3655 cname,
3656 self.module_name,
3657 code.error_goto_if_null(self.result(), self.pos)))
3658 code.put_gotref(self.py_result())
3661 class UnboundMethodNode(ExprNode):
3662 # Helper class used in the implementation of Python
3663 # class definitions. Constructs an unbound method
3664 # object from a class and a function.
3665 #
3666 # function ExprNode Function object
3668 subexprs = ['function']
3670 def analyse_types(self, env):
3671 self.function.analyse_types(env)
3672 self.type = py_object_type
3673 self.is_temp = 1
3675 gil_message = "Constructing an unbound method"
3677 def generate_result_code(self, code):
3678 class_cname = code.pyclass_stack[-1].classobj.result()
3679 code.putln(
3680 "%s = PyMethod_New(%s, 0, %s); %s" % (
3681 self.result(),
3682 self.function.py_result(),
3683 class_cname,
3684 code.error_goto_if_null(self.result(), self.pos)))
3685 code.put_gotref(self.py_result())
3687 class PyCFunctionNode(AtomicExprNode):
3688 # Helper class used in the implementation of Python
3689 # class definitions. Constructs a PyCFunction object
3690 # from a PyMethodDef struct.
3691 #
3692 # pymethdef_cname string PyMethodDef structure
3694 def analyse_types(self, env):
3695 self.type = py_object_type
3696 self.is_temp = 1
3698 gil_message = "Constructing Python function"
3700 def generate_result_code(self, code):
3701 code.putln(
3702 "%s = PyCFunction_New(&%s, 0); %s" % (
3703 self.result(),
3704 self.pymethdef_cname,
3705 code.error_goto_if_null(self.result(), self.pos)))
3706 code.put_gotref(self.py_result())
3708 #-------------------------------------------------------------------
3709 #
3710 # Unary operator nodes
3711 #
3712 #-------------------------------------------------------------------
3714 compile_time_unary_operators = {
3715 'not': operator.not_,
3716 '~': operator.inv,
3717 '-': operator.neg,
3718 '+': operator.pos,
3719 }
3721 class UnopNode(ExprNode):
3722 # operator string
3723 # operand ExprNode
3724 #
3725 # Processing during analyse_expressions phase:
3726 #
3727 # analyse_c_operation
3728 # Called when the operand is not a pyobject.
3729 # - Check operand type and coerce if needed.
3730 # - Determine result type and result code fragment.
3731 # - Allocate temporary for result if needed.
3733 subexprs = ['operand']
3734 infix = True
3736 def calculate_constant_result(self):
3737 func = compile_time_unary_operators[self.operator]
3738 self.constant_result = func(self.operand.constant_result)
3740 def compile_time_value(self, denv):
3741 func = compile_time_unary_operators.get(self.operator)
3742 if not func:
3743 error(self.pos,
3744 "Unary '%s' not supported in compile-time expression"
3745 % self.operator)
3746 operand = self.operand.compile_time_value(denv)
3747 try:
3748 return func(operand)
3749 except Exception, e:
3750 self.compile_time_value_error(e)
3752 def analyse_types(self, env):
3753 self.operand.analyse_types(env)
3754 if self.is_py_operation():
3755 self.coerce_operand_to_pyobject(env)
3756 self.type = py_object_type
3757 self.is_temp = 1
3758 else:
3759 self.analyse_c_operation(env)
3761 def check_const(self):
3762 self.operand.check_const()
3764 def is_py_operation(self):
3765 return self.operand.type.is_pyobject
3767 def nogil_check(self, env):
3768 if self.is_py_operation():
3769 self.gil_error()
3771 def coerce_operand_to_pyobject(self, env):
3772 self.operand = self.operand.coerce_to_pyobject(env)
3774 def generate_result_code(self, code):
3775 if self.operand.type.is_pyobject:
3776 self.generate_py_operation_code(code)
3778 def generate_py_operation_code(self, code):
3779 function = self.py_operation_function()
3780 code.putln(
3781 "%s = %s(%s); %s" % (
3782 self.result(),
3783 function,
3784 self.operand.py_result(),
3785 code.error_goto_if_null(self.result(), self.pos)))
3786 code.put_gotref(self.py_result())
3788 def type_error(self):
3789 if not self.operand.type.is_error:
3790 error(self.pos, "Invalid operand type for '%s' (%s)" %
3791 (self.operator, self.operand.type))
3792 self.type = PyrexTypes.error_type
3795 class NotNode(ExprNode):
3796 # 'not' operator
3797 #
3798 # operand ExprNode
3800 def calculate_constant_result(self):
3801 self.constant_result = not self.operand.constant_result
3803 def compile_time_value(self, denv):
3804 operand = self.operand.compile_time_value(denv)
3805 try:
3806 return not operand
3807 except Exception, e:
3808 self.compile_time_value_error(e)
3810 subexprs = ['operand']
3812 def analyse_types(self, env):
3813 self.operand.analyse_types(env)
3814 self.operand = self.operand.coerce_to_boolean(env)
3815 self.type = PyrexTypes.c_bint_type
3817 def calculate_result_code(self):
3818 return "(!%s)" % self.operand.result()
3820 def generate_result_code(self, code):
3821 pass
3824 class UnaryPlusNode(UnopNode):
3825 # unary '+' operator
3827 operator = '+'
3829 def analyse_c_operation(self, env):
3830 self.type = self.operand.type
3832 def py_operation_function(self):
3833 return "PyNumber_Positive"
3835 def calculate_result_code(self):
3836 return self.operand.result()
3839 class UnaryMinusNode(UnopNode):
3840 # unary '-' operator
3842 operator = '-'
3844 def analyse_c_operation(self, env):
3845 if self.operand.type.is_numeric:
3846 self.type = self.operand.type
3847 else:
3848 self.type_error()
3849 if self.type.is_complex:
3850 self.infix = env.directives['c99_complex']
3852 def py_operation_function(self):
3853 return "PyNumber_Negative"
3855 def calculate_result_code(self):
3856 if self.infix:
3857 return "(-%s)" % self.operand.result()
3858 else:
3859 return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result())
3861 class TildeNode(UnopNode):
3862 # unary '~' operator
3864 def analyse_c_operation(self, env):
3865 if self.operand.type.is_int:
3866 self.type = self.operand.type
3867 else:
3868 self.type_error()
3870 def py_operation_function(self):
3871 return "PyNumber_Invert"
3873 def calculate_result_code(self):
3874 return "(~%s)" % self.operand.result()
3877 class AmpersandNode(ExprNode):
3878 # The C address-of operator.
3879 #
3880 # operand ExprNode
3882 subexprs = ['operand']
3884 def analyse_types(self, env):
3885 self.operand.analyse_types(env)
3886 argtype = self.operand.type
3887 if not (argtype.is_cfunction or self.operand.is_lvalue()):
3888 self.error("Taking address of non-lvalue")
3889 return
3890 if argtype.is_pyobject:
3891 self.error("Cannot take address of Python variable")
3892 return
3893 self.type = PyrexTypes.c_ptr_type(argtype)
3895 def check_const(self):
3896 self.operand.check_const_addr()
3898 def error(self, mess):
3899 error(self.pos, mess)
3900 self.type = PyrexTypes.error_type
3901 self.result_code = "<error>"
3903 def calculate_result_code(self):
3904 return "(&%s)" % self.operand.result()
3906 def generate_result_code(self, code):
3907 pass
3910 unop_node_classes = {
3911 "+": UnaryPlusNode,
3912 "-": UnaryMinusNode,
3913 "~": TildeNode,
3914 }
3916 def unop_node(pos, operator, operand):
3917 # Construct unnop node of appropriate class for
3918 # given operator.
3919 if isinstance(operand, IntNode) and operator == '-':
3920 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3921 elif isinstance(operand, UnopNode) and operand.operator == operator:
3922 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3923 return unop_node_classes[operator](pos,
3924 operator = operator,
3925 operand = operand)
3928 class TypecastNode(ExprNode):
3929 # C type cast
3930 #
3931 # operand ExprNode
3932 # base_type CBaseTypeNode
3933 # declarator CDeclaratorNode
3934 #
3935 # If used from a transform, one can if wanted specify the attribute
3936 # "type" directly and leave base_type and declarator to None
3938 subexprs = ['operand']
3939 base_type = declarator = type = None
3941 def analyse_types(self, env):
3942 if self.type is None:
3943 base_type = self.base_type.analyse(env)
3944 _, self.type = self.declarator.analyse(base_type, env)
3945 if self.type.is_cfunction:
3946 error(self.pos,
3947 "Cannot cast to a function type")
3948 self.type = PyrexTypes.error_type
3949 self.operand.analyse_types(env)
3950 to_py = self.type.is_pyobject
3951 from_py = self.operand.type.is_pyobject
3952 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3953 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3954 if to_py and not from_py:
3955 if (self.operand.type.to_py_function and
3956 self.operand.type.create_to_py_utility_code(env)):
3957 self.result_ctype = py_object_type
3958 self.operand = self.operand.coerce_to_pyobject(env)
3959 else:
3960 if not (self.operand.type.is_ptr and self.operand.type.base_type.is_void):
3961 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3962 self.operand = self.operand.coerce_to_simple(env)
3963 elif from_py and not to_py:
3964 if self.type.from_py_function:
3965 self.operand = self.operand.coerce_to(self.type, env)
3966 elif self.type.is_ptr and not (self.type.base_type.is_void or self.type.base_type.is_struct):
3967 error(self.pos, "Python objects cannot be casted to pointers of primitive types")
3968 else:
3969 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3970 elif from_py and to_py:
3971 if self.typecheck and self.type.is_extension_type:
3972 self.operand = PyTypeTestNode(self.operand, self.type, env)
3974 def nogil_check(self, env):
3975 if self.type and self.type.is_pyobject and self.is_temp:
3976 self.gil_error()
3978 def check_const(self):
3979 self.operand.check_const()
3981 def calculate_constant_result(self):
3982 # we usually do not know the result of a type cast at code
3983 # generation time
3984 pass
3986 def calculate_result_code(self):
3987 opnd = self.operand
3988 return self.type.cast_code(opnd.result())
3990 def result_as(self, type):
3991 if self.type.is_pyobject and not self.is_temp:
3992 # Optimise away some unnecessary casting
3993 return self.operand.result_as(type)
3994 else:
3995 return ExprNode.result_as(self, type)
3997 def generate_result_code(self, code):
3998 if self.is_temp:
3999 code.putln(
4000 "%s = (PyObject *)%s;" % (
4001 self.result(),
4002 self.operand.result()))
4003 code.put_incref(self.result(), self.ctype())
4006 class SizeofNode(ExprNode):
4007 # Abstract base class for sizeof(x) expression nodes.
4009 type = PyrexTypes.c_size_t_type
4011 def check_const(self):
4012 pass
4014 def generate_result_code(self, code):
4015 pass
4018 class SizeofTypeNode(SizeofNode):
4019 # C sizeof function applied to a type
4020 #
4021 # base_type CBaseTypeNode
4022 # declarator CDeclaratorNode
4024 subexprs = []
4025 arg_type = None
4027 def analyse_types(self, env):
4028 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
4029 # this could be better handled by more uniformly treating types as runtime-available objects
4030 if 0 and self.base_type.module_path:
4031 path = self.base_type.module_path
4032 obj = env.lookup(path[0])
4033 if obj.as_module is None:
4034 operand = NameNode(pos=self.pos, name=path[0])
4035 for attr in path[1:]:
4036 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
4037 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
4038 self.operand = operand
4039 self.__class__ = SizeofVarNode
4040 self.analyse_types(env)
4041 return
4042 if self.arg_type is None:
4043 base_type = self.base_type.analyse(env)
4044 _, arg_type = self.declarator.analyse(base_type, env)
4045 self.arg_type = arg_type
4046 self.check_type()
4048 def check_type(self):
4049 arg_type = self.arg_type
4050 if arg_type.is_pyobject and not arg_type.is_extension_type:
4051 error(self.pos, "Cannot take sizeof Python object")
4052 elif arg_type.is_void:
4053 error(self.pos, "Cannot take sizeof void")
4054 elif not arg_type.is_complete():
4055 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
4057 def calculate_result_code(self):
4058 if self.arg_type.is_extension_type:
4059 # the size of the pointer is boring
4060 # we want the size of the actual struct
4061 arg_code = self.arg_type.declaration_code("", deref=1)
4062 else:
4063 arg_code = self.arg_type.declaration_code("")
4064 return "(sizeof(%s))" % arg_code
4067 class SizeofVarNode(SizeofNode):
4068 # C sizeof function applied to a variable
4069 #
4070 # operand ExprNode
4072 subexprs = ['operand']
4074 def analyse_types(self, env):
4075 # We may actually be looking at a type rather than a variable...
4076 # If we are, traditional analysis would fail...
4077 operand_as_type = self.operand.analyse_as_type(env)
4078 if operand_as_type:
4079 self.arg_type = operand_as_type
4080 self.__class__ = SizeofTypeNode
4081 self.check_type()
4082 else:
4083 self.operand.analyse_types(env)
4085 def calculate_result_code(self):
4086 return "(sizeof(%s))" % self.operand.result()
4088 def generate_result_code(self, code):
4089 pass
4092 #-------------------------------------------------------------------
4093 #
4094 # Binary operator nodes
4095 #
4096 #-------------------------------------------------------------------
4098 def _not_in(x, seq):
4099 return x not in seq
4101 compile_time_binary_operators = {
4102 '<': operator.lt,
4103 '<=': operator.le,
4104 '==': operator.eq,
4105 '!=': operator.ne,
4106 '>=': operator.ge,
4107 '>': operator.gt,
4108 'is': operator.is_,
4109 'is_not': operator.is_not,
4110 '+': operator.add,
4111 '&': operator.and_,
4112 '/': operator.truediv,
4113 '//': operator.floordiv,
4114 '<<': operator.lshift,
4115 '%': operator.mod,
4116 '*': operator.mul,
4117 '|': operator.or_,
4118 '**': operator.pow,
4119 '>>': operator.rshift,
4120 '-': operator.sub,
4121 '^': operator.xor,
4122 'in': operator.contains,
4123 'not_in': _not_in,
4124 }
4126 def get_compile_time_binop(node):
4127 func = compile_time_binary_operators.get(node.operator)
4128 if not func:
4129 error(node.pos,
4130 "Binary '%s' not supported in compile-time expression"
4131 % node.operator)
4132 return func
4134 class BinopNode(ExprNode):
4135 # operator string
4136 # operand1 ExprNode
4137 # operand2 ExprNode
4138 #
4139 # Processing during analyse_expressions phase:
4140 #
4141 # analyse_c_operation
4142 # Called when neither operand is a pyobject.
4143 # - Check operand types and coerce if needed.
4144 # - Determine result type and result code fragment.
4145 # - Allocate temporary for result if needed.
4147 subexprs = ['operand1', 'operand2']
4149 def calculate_constant_result(self):
4150 func = compile_time_binary_operators[self.operator]
4151 self.constant_result = func(
4152 self.operand1.constant_result,
4153 self.operand2.constant_result)
4155 def compile_time_value(self, denv):
4156 func = get_compile_time_binop(self)
4157 operand1 = self.operand1.compile_time_value(denv)
4158 operand2 = self.operand2.compile_time_value(denv)
4159 try:
4160 return func(operand1, operand2)
4161 except Exception, e:
4162 self.compile_time_value_error(e)
4164 def analyse_types(self, env):
4165 self.operand1.analyse_types(env)
4166 self.operand2.analyse_types(env)
4167 if self.is_py_operation():
4168 self.coerce_operands_to_pyobjects(env)
4169 self.type = py_object_type
4170 self.is_temp = 1
4171 if Options.incref_local_binop and self.operand1.type.is_pyobject:
4172 self.operand1 = self.operand1.coerce_to_temp(env)
4173 else:
4174 self.analyse_c_operation(env)
4176 def is_py_operation(self):
4177 return (self.operand1.type.is_pyobject
4178 or self.operand2.type.is_pyobject)
4180 def nogil_check(self, env):
4181 if self.is_py_operation():
4182 self.gil_error()
4184 def coerce_operands_to_pyobjects(self, env):
4185 self.operand1 = self.operand1.coerce_to_pyobject(env)
4186 self.operand2 = self.operand2.coerce_to_pyobject(env)
4188 def check_const(self):
4189 self.operand1.check_const()
4190 self.operand2.check_const()
4192 def generate_result_code(self, code):
4193 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4194 if self.operand1.type.is_pyobject:
4195 function = self.py_operation_function()
4196 if function == "PyNumber_Power":
4197 extra_args = ", Py_None"
4198 else:
4199 extra_args = ""
4200 code.putln(
4201 "%s = %s(%s, %s%s); %s" % (
4202 self.result(),
4203 function,
4204 self.operand1.py_result(),
4205 self.operand2.py_result(),
4206 extra_args,
4207 code.error_goto_if_null(self.result(), self.pos)))
4208 code.put_gotref(self.py_result())
4210 def type_error(self):
4211 if not (self.operand1.type.is_error
4212 or self.operand2.type.is_error):
4213 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4214 (self.operator, self.operand1.type,
4215 self.operand2.type))
4216 self.type = PyrexTypes.error_type
4219 class NumBinopNode(BinopNode):
4220 # Binary operation taking numeric arguments.
4222 infix = True
4224 def analyse_c_operation(self, env):
4225 type1 = self.operand1.type
4226 type2 = self.operand2.type
4227 self.type = self.compute_c_result_type(type1, type2)
4228 if not self.type:
4229 self.type_error()
4230 return
4231 if self.type.is_complex and not env.directives['c99_complex']:
4232 self.infix = False
4233 if not self.infix:
4234 self.operand1 = self.operand1.coerce_to(self.type, env)
4235 self.operand2 = self.operand2.coerce_to(self.type, env)
4237 def compute_c_result_type(self, type1, type2):
4238 if self.c_types_okay(type1, type2):
4239 return PyrexTypes.widest_numeric_type(type1, type2)
4240 else:
4241 return None
4243 def get_constant_c_result_code(self):
4244 value1 = self.operand1.get_constant_c_result_code()
4245 value2 = self.operand2.get_constant_c_result_code()
4246 if value1 and value2:
4247 return "(%s %s %s)" % (value1, self.operator, value2)
4248 else:
4249 return None
4251 def c_types_okay(self, type1, type2):
4252 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4253 return (type1.is_numeric or type1.is_enum) \
4254 and (type2.is_numeric or type2.is_enum)
4256 def calculate_result_code(self):
4257 if self.infix:
4258 return "(%s %s %s)" % (
4259 self.operand1.result(),
4260 self.operator,
4261 self.operand2.result())
4262 else:
4263 func = self.type.binary_op(self.operator)
4264 if func is None:
4265 error(self.pos, "binary operator %s not supported for %s" % (self.operator, self.type))
4266 return "%s(%s, %s)" % (
4267 func,
4268 self.operand1.result(),
4269 self.operand2.result())
4271 def py_operation_function(self):
4272 return self.py_functions[self.operator]
4274 py_functions = {
4275 "|": "PyNumber_Or",
4276 "^": "PyNumber_Xor",
4277 "&": "PyNumber_And",
4278 "<<": "PyNumber_Lshift",
4279 ">>": "PyNumber_Rshift",
4280 "+": "PyNumber_Add",
4281 "-": "PyNumber_Subtract",
4282 "*": "PyNumber_Multiply",
4283 "/": "__Pyx_PyNumber_Divide",
4284 "//": "PyNumber_FloorDivide",
4285 "%": "PyNumber_Remainder",
4286 "**": "PyNumber_Power"
4287 }
4290 class IntBinopNode(NumBinopNode):
4291 # Binary operation taking integer arguments.
4293 def c_types_okay(self, type1, type2):
4294 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4295 return (type1.is_int or type1.is_enum) \
4296 and (type2.is_int or type2.is_enum)
4299 class AddNode(NumBinopNode):
4300 # '+' operator.
4302 def is_py_operation(self):
4303 if self.operand1.type.is_string \
4304 and self.operand2.type.is_string:
4305 return 1
4306 else:
4307 return NumBinopNode.is_py_operation(self)
4309 def compute_c_result_type(self, type1, type2):
4310 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4311 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4312 return type1
4313 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4314 return type2
4315 else:
4316 return NumBinopNode.compute_c_result_type(
4317 self, type1, type2)
4320 class SubNode(NumBinopNode):
4321 # '-' operator.
4323 def compute_c_result_type(self, type1, type2):
4324 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4325 return type1
4326 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4327 return PyrexTypes.c_int_type
4328 else:
4329 return NumBinopNode.compute_c_result_type(
4330 self, type1, type2)
4333 class MulNode(NumBinopNode):
4334 # '*' operator.
4336 def is_py_operation(self):
4337 type1 = self.operand1.type
4338 type2 = self.operand2.type
4339 if (type1.is_string and type2.is_int) \
4340 or (type2.is_string and type1.is_int):
4341 return 1
4342 else:
4343 return NumBinopNode.is_py_operation(self)
4346 class DivNode(NumBinopNode):
4347 # '/' or '//' operator.
4349 cdivision = None
4350 truedivision = None # == "unknown" if operator == '/'
4351 ctruedivision = False
4352 cdivision_warnings = False
4353 zerodivision_check = None
4355 def find_compile_time_binary_operator(self, op1, op2):
4356 func = compile_time_binary_operators[self.operator]
4357 if self.operator == '/' and self.truedivision is None:
4358 # => true div for floats, floor div for integers
4359 if isinstance(op1, (int,long)) and isinstance(op2, (int,long)):
4360 func = compile_time_binary_operators['//']
4361 return func
4363 def calculate_constant_result(self):
4364 op1 = self.operand1.constant_result
4365 op2 = self.operand2.constant_result
4366 func = self.find_compile_time_binary_operator(op1, op2)
4367 self.constant_result = func(
4368 self.operand1.constant_result,
4369 self.operand2.constant_result)
4371 def compile_time_value(self, denv):
4372 operand1 = self.operand1.compile_time_value(denv)
4373 operand2 = self.operand2.compile_time_value(denv)
4374 try:
4375 func = self.find_compile_time_binary_operator(
4376 self, operand1, operand2)
4377 return func(operand1, operand2)
4378 except Exception, e:
4379 self.compile_time_value_error(e)
4381 def analyse_types(self, env):
4382 if self.cdivision or env.directives['cdivision']:
4383 self.ctruedivision = False
4384 else:
4385 self.ctruedivision = self.truedivision
4386 NumBinopNode.analyse_types(self, env)
4387 if not self.type.is_pyobject:
4388 self.zerodivision_check = (
4389 self.cdivision is None and not env.directives['cdivision']
4390 and (self.operand2.constant_result is not_a_constant or
4391 self.operand2.constant_result == 0))
4392 if self.zerodivision_check or env.directives['cdivision_warnings']:
4393 # Need to check ahead of time to warn or raise zero division error
4394 self.operand1 = self.operand1.coerce_to_simple(env)
4395 self.operand2 = self.operand2.coerce_to_simple(env)
4396 if env.nogil:
4397 error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
4399 def compute_c_result_type(self, type1, type2):
4400 if self.operator == '/' and self.ctruedivision:
4401 if not type1.is_float and not type2.is_float:
4402 widest_type = PyrexTypes.widest_numeric_type(type1, PyrexTypes.c_double_type)
4403 widest_type = PyrexTypes.widest_numeric_type(type2, widest_type)
4404 return widest_type
4405 return NumBinopNode.compute_c_result_type(self, type1, type2)
4407 def zero_division_message(self):
4408 if self.type.is_int:
4409 return "integer division or modulo by zero"
4410 else:
4411 return "float division"
4413 def generate_evaluation_code(self, code):
4414 if not self.type.is_pyobject and not self.type.is_complex:
4415 if self.cdivision is None:
4416 self.cdivision = (code.globalstate.directives['cdivision']
4417 or not self.type.signed
4418 or self.type.is_float)
4419 if not self.cdivision:
4420 code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
4421 NumBinopNode.generate_evaluation_code(self, code)
4422 self.generate_div_warning_code(code)
4424 def generate_div_warning_code(self, code):
4425 if not self.type.is_pyobject:
4426 if self.zerodivision_check:
4427 if not self.infix:
4428 zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.operand2.result())
4429 else:
4430 zero_test = "%s == 0" % self.operand2.result()
4431 code.putln("if (unlikely(%s)) {" % zero_test)
4432 code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
4433 code.putln(code.error_goto(self.pos))
4434 code.putln("}")
4435 if self.type.is_int and self.type.signed and self.operator != '%':
4436 code.globalstate.use_utility_code(division_overflow_test_code)
4437 code.putln("else if (sizeof(%s) == sizeof(long) && unlikely(%s == -1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % (
4438 self.type.declaration_code(''),
4439 self.operand2.result(),
4440 self.operand1.result()))
4441 code.putln('PyErr_Format(PyExc_OverflowError, "value too large to perform division");')
4442 code.putln(code.error_goto(self.pos))
4443 code.putln("}")
4444 if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
4445 code.globalstate.use_utility_code(cdivision_warning_utility_code)
4446 code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
4447 self.operand1.result(),
4448 self.operand2.result()))
4449 code.putln(code.set_error_info(self.pos));
4450 code.put("if (__Pyx_cdivision_warning()) ")
4451 code.put_goto(code.error_label)
4452 code.putln("}")
4454 def calculate_result_code(self):
4455 if self.type.is_complex:
4456 return NumBinopNode.calculate_result_code(self)
4457 elif self.type.is_float and self.operator == '//':
4458 return "floor(%s / %s)" % (
4459 self.operand1.result(),
4460 self.operand2.result())
4461 elif self.truedivision or self.cdivision:
4462 op1 = self.operand1.result()
4463 op2 = self.operand2.result()
4464 if self.truedivision:
4465 if self.type != self.operand1.type:
4466 op1 = self.type.cast_code(op1)
4467 if self.type != self.operand2.type:
4468 op2 = self.type.cast_code(op2)
4469 return "(%s / %s)" % (op1, op2)
4470 else:
4471 return "__Pyx_div_%s(%s, %s)" % (
4472 self.type.specalization_name(),
4473 self.operand1.result(),
4474 self.operand2.result())
4477 class ModNode(DivNode):
4478 # '%' operator.
4480 def is_py_operation(self):
4481 return (self.operand1.type.is_string
4482 or self.operand2.type.is_string
4483 or NumBinopNode.is_py_operation(self))
4485 def zero_division_message(self):
4486 if self.type.is_int:
4487 return "integer division or modulo by zero"
4488 else:
4489 return "float divmod()"
4491 def generate_evaluation_code(self, code):
4492 if not self.type.is_pyobject:
4493 if self.cdivision is None:
4494 self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
4495 if not self.cdivision:
4496 if self.type.is_int:
4497 code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
4498 else:
4499 code.globalstate.use_utility_code(
4500 mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
4501 NumBinopNode.generate_evaluation_code(self, code)
4502 self.generate_div_warning_code(code)
4504 def calculate_result_code(self):
4505 if self.cdivision:
4506 if self.type.is_float:
4507 return "fmod%s(%s, %s)" % (
4508 self.type.math_h_modifier,
4509 self.operand1.result(),
4510 self.operand2.result())
4511 else:
4512 return "(%s %% %s)" % (
4513 self.operand1.result(),
4514 self.operand2.result())
4515 else:
4516 return "__Pyx_mod_%s(%s, %s)" % (
4517 self.type.specalization_name(),
4518 self.operand1.result(),
4519 self.operand2.result())
4521 class PowNode(NumBinopNode):
4522 # '**' operator.
4524 def analyse_c_operation(self, env):
4525 NumBinopNode.analyse_c_operation(self, env)
4526 if self.type.is_complex:
4527 error(self.pos, "complex powers not yet supported")
4528 self.pow_func = "<error>"
4529 elif self.type.is_float:
4530 self.pow_func = "pow"
4531 else:
4532 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
4533 env.use_utility_code(
4534 int_pow_utility_code.specialize(func_name=self.pow_func,
4535 type=self.type.declaration_code('')))
4537 def calculate_result_code(self):
4538 return "%s(%s, %s)" % (
4539 self.pow_func,
4540 self.operand1.result(),
4541 self.operand2.result())
4544 # Note: This class is temporary "shut down" into an ineffective mode temp
4545 # allocation mode.
4546 #
4547 # More sophisticated temp reuse was going on before,
4548 # one could have a look at adding this again after /all/ classes
4549 # are converted to the new temp scheme. (The temp juggling cannot work
4550 # otherwise).
4551 class BoolBinopNode(ExprNode):
4552 # Short-circuiting boolean operation.
4553 #
4554 # operator string
4555 # operand1 ExprNode
4556 # operand2 ExprNode
4558 subexprs = ['operand1', 'operand2']
4560 def calculate_constant_result(self):
4561 if self.operator == 'and':
4562 self.constant_result = \
4563 self.operand1.constant_result and \
4564 self.operand2.constant_result
4565 else:
4566 self.constant_result = \
4567 self.operand1.constant_result or \
4568 self.operand2.constant_result
4570 def compile_time_value(self, denv):
4571 if self.operator == 'and':
4572 return self.operand1.compile_time_value(denv) \
4573 and self.operand2.compile_time_value(denv)
4574 else:
4575 return self.operand1.compile_time_value(denv) \
4576 or self.operand2.compile_time_value(denv)
4578 def coerce_to_boolean(self, env):
4579 self.operand1 = self.operand1.coerce_to_boolean(env)
4580 self.operand2 = self.operand2.coerce_to_boolean(env)
4581 self.type = PyrexTypes.c_bint_type
4582 return self
4584 def analyse_types(self, env):
4585 self.operand1.analyse_types(env)
4586 self.operand2.analyse_types(env)
4587 if self.operand1.type.is_pyobject or \
4588 self.operand2.type.is_pyobject:
4589 self.operand1 = self.operand1.coerce_to_pyobject(env)
4590 self.operand2 = self.operand2.coerce_to_pyobject(env)
4591 self.type = py_object_type
4592 else:
4593 self.operand1 = self.operand1.coerce_to_boolean(env)
4594 self.operand2 = self.operand2.coerce_to_boolean(env)
4595 self.type = PyrexTypes.c_bint_type
4597 # Below disabled for
4599 # For what we're about to do, it's vital that
4600 # both operands be temp nodes.
4601 # self.operand1 = self.operand1.coerce_to_temp(env) #CTT
4602 # self.operand2 = self.operand2.coerce_to_temp(env)
4603 self.is_temp = 1
4605 gil_message = "Truth-testing Python object"
4607 def check_const(self):
4608 self.operand1.check_const()
4609 self.operand2.check_const()
4611 def calculate_result_code(self):
4612 return "(%s %s %s)" % (
4613 self.operand1.result(),
4614 self.py_to_c_op[self.operator],
4615 self.operand2.result())
4617 py_to_c_op = {'and': "&&", 'or': "||"}
4619 def generate_evaluation_code(self, code):
4620 code.mark_pos(self.pos)
4621 self.operand1.generate_evaluation_code(code)
4622 test_result, uses_temp = self.generate_operand1_test(code)
4623 if self.operator == 'and':
4624 sense = ""
4625 else:
4626 sense = "!"
4627 code.putln(
4628 "if (%s%s) {" % (
4629 sense,
4630 test_result))
4631 if uses_temp:
4632 code.funcstate.release_temp(test_result)
4633 self.operand1.generate_disposal_code(code)
4634 self.operand2.generate_evaluation_code(code)
4635 self.allocate_temp_result(code)
4636 self.operand2.make_owned_reference(code)
4637 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
4638 self.operand2.generate_post_assignment_code(code)
4639 self.operand2.free_temps(code)
4640 code.putln("} else {")
4641 self.operand1.make_owned_reference(code)
4642 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
4643 self.operand1.generate_post_assignment_code(code)
4644 self.operand1.free_temps(code)
4645 code.putln("}")
4647 def generate_operand1_test(self, code):
4648 # Generate code to test the truth of the first operand.
4649 if self.type.is_pyobject:
4650 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
4651 manage_ref=False)
4652 code.putln(
4653 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4654 test_result,
4655 self.operand1.py_result(),
4656 code.error_goto_if_neg(test_result, self.pos)))
4657 else:
4658 test_result = self.operand1.result()
4659 return (test_result, self.type.is_pyobject)
4662 class CondExprNode(ExprNode):
4663 # Short-circuiting conditional expression.
4664 #
4665 # test ExprNode
4666 # true_val ExprNode
4667 # false_val ExprNode
4669 true_val = None
4670 false_val = None
4672 subexprs = ['test', 'true_val', 'false_val']
4674 def calculate_constant_result(self):
4675 if self.test.constant_result:
4676 self.constant_result = self.true_val.constant_result
4677 else:
4678 self.constant_result = self.false_val.constant_result
4680 def analyse_types(self, env):
4681 self.test.analyse_types(env)
4682 self.test = self.test.coerce_to_boolean(env)
4683 self.true_val.analyse_types(env)
4684 self.false_val.analyse_types(env)
4685 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
4686 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
4687 self.true_val = self.true_val.coerce_to(self.type, env)
4688 self.false_val = self.false_val.coerce_to(self.type, env)
4689 self.is_temp = 1
4690 if self.type == PyrexTypes.error_type:
4691 self.type_error()
4693 def compute_result_type(self, type1, type2):
4694 if type1 == type2:
4695 return type1
4696 elif type1.is_numeric and type2.is_numeric:
4697 return PyrexTypes.widest_numeric_type(type1, type2)
4698 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
4699 return type2
4700 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
4701 return type1
4702 elif type1.is_pyobject or type2.is_pyobject:
4703 return py_object_type
4704 elif type1.assignable_from(type2):
4705 return type1
4706 elif type2.assignable_from(type1):
4707 return type2
4708 else:
4709 return PyrexTypes.error_type
4711 def type_error(self):
4712 if not (self.true_val.type.is_error or self.false_val.type.is_error):
4713 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
4714 (self.true_val.type, self.false_val.type))
4715 self.type = PyrexTypes.error_type
4717 def check_const(self):
4718 self.test.check_const()
4719 self.true_val.check_const()
4720 self.false_val.check_const()
4722 def generate_evaluation_code(self, code):
4723 # Because subexprs may not be evaluated we can use a more optimal
4724 # subexpr allocation strategy than the default, so override evaluation_code.
4726 code.mark_pos(self.pos)
4727 self.allocate_temp_result(code)
4728 self.test.generate_evaluation_code(code)
4729 code.putln("if (%s) {" % self.test.result() )
4730 self.eval_and_get(code, self.true_val)
4731 code.putln("} else {")
4732 self.eval_and_get(code, self.false_val)
4733 code.putln("}")
4734 self.test.generate_disposal_code(code)
4735 self.test.free_temps(code)
4737 def eval_and_get(self, code, expr):
4738 expr.generate_evaluation_code(code)
4739 expr.make_owned_reference(code)
4740 code.putln("%s = %s;" % (self.result(), expr.result()))
4741 expr.generate_post_assignment_code(code)
4742 expr.free_temps(code)
4744 richcmp_constants = {
4745 "<" : "Py_LT",
4746 "<=": "Py_LE",
4747 "==": "Py_EQ",
4748 "!=": "Py_NE",
4749 "<>": "Py_NE",
4750 ">" : "Py_GT",
4751 ">=": "Py_GE",
4752 }
4754 class CmpNode(object):
4755 # Mixin class containing code common to PrimaryCmpNodes
4756 # and CascadedCmpNodes.
4758 def calculate_cascaded_constant_result(self, operand1_result):
4759 func = compile_time_binary_operators[self.operator]
4760 operand2_result = self.operand2.constant_result
4761 result = func(operand1_result, operand2_result)
4762 if result and self.cascade:
4763 result = result and \
4764 self.cascade.cascaded_compile_time_value(operand2_result)
4765 self.constant_result = result
4767 def cascaded_compile_time_value(self, operand1, denv):
4768 func = get_compile_time_binop(self)
4769 operand2 = self.operand2.compile_time_value(denv)
4770 try:
4771 result = func(operand1, operand2)
4772 except Exception, e:
4773 self.compile_time_value_error(e)
4774 result = None
4775 if result:
4776 cascade = self.cascade
4777 if cascade:
4778 # FIXME: I bet this must call cascaded_compile_time_value()
4779 result = result and cascade.compile_time_value(operand2, denv)
4780 return result
4782 def is_python_comparison(self):
4783 return (self.has_python_operands()
4784 or (self.cascade and self.cascade.is_python_comparison())
4785 or self.operator in ('in', 'not_in'))
4787 def is_python_result(self):
4788 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
4789 or (self.cascade and self.cascade.is_python_result()))
4791 def check_types(self, env, operand1, op, operand2):
4792 if operand1.type.is_complex or operand2.type.is_complex:
4793 if op not in ('==', '!='):
4794 error(self.pos, "complex types unordered")
4795 common_type = PyrexTypes.widest_numeric_type(operand1.type, operand2.type)
4796 self.operand1 = operand1.coerce_to(common_type, env)
4797 self.operand2 = operand2.coerce_to(common_type, env)
4798 elif not self.types_okay(operand1, op, operand2):
4799 error(self.pos, "Invalid types for '%s' (%s, %s)" %
4800 (self.operator, operand1.type, operand2.type))
4802 def types_okay(self, operand1, op, operand2):
4803 type1 = operand1.type
4804 type2 = operand2.type
4805 if type1.is_error or type2.is_error:
4806 return 1
4807 if type1.is_pyobject: # type2 will be, too
4808 return 1
4809 elif type1.is_ptr or type1.is_array:
4810 return type1.is_null_ptr or type2.is_null_ptr \
4811 or ((type2.is_ptr or type2.is_array)
4812 and type1.base_type.same_as(type2.base_type))
4813 elif ((type1.is_numeric and type2.is_numeric
4814 or type1.is_enum and (type1 is type2 or type2.is_int)
4815 or type1.is_int and type2.is_enum)
4816 and op not in ('is', 'is_not')):
4817 return 1
4818 else:
4819 return type1.is_cfunction and type1.is_cfunction and type1 == type2
4821 def generate_operation_code(self, code, result_code,
4822 operand1, op , operand2):
4823 if self.type is PyrexTypes.py_object_type:
4824 coerce_result = "__Pyx_PyBool_FromLong"
4825 else:
4826 coerce_result = ""
4827 if 'not' in op: negation = "!"
4828 else: negation = ""
4829 if op == 'in' or op == 'not_in':
4830 code.putln(
4831 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
4832 result_code,
4833 coerce_result,
4834 negation,
4835 operand2.py_result(),
4836 operand1.py_result(),
4837 code.error_goto_if_neg(result_code, self.pos)))
4838 elif (operand1.type.is_pyobject
4839 and op not in ('is', 'is_not')):
4840 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
4841 result_code,
4842 operand1.py_result(),
4843 operand2.py_result(),
4844 richcmp_constants[op],
4845 code.error_goto_if_null(result_code, self.pos)))
4846 code.put_gotref(result_code)
4847 elif operand1.type.is_complex and not code.globalstate.directives['c99_complex']:
4848 if op == "!=": negation = "!"
4849 else: negation = ""
4850 code.putln("%s = %s(%s%s(%s, %s));" % (
4851 result_code,
4852 coerce_result,
4853 negation,
4854 operand1.type.unary_op('eq'),
4855 operand1.result(),
4856 operand2.result()))
4857 else:
4858 type1 = operand1.type
4859 type2 = operand2.type
4860 if (type1.is_extension_type or type2.is_extension_type) \
4861 and not type1.same_as(type2):
4862 common_type = py_object_type
4863 elif type1.is_numeric:
4864 common_type = PyrexTypes.widest_numeric_type(type1, type2)
4865 else:
4866 common_type = type1
4867 code1 = operand1.result_as(common_type)
4868 code2 = operand2.result_as(common_type)
4869 code.putln("%s = %s(%s %s %s);" % (
4870 result_code,
4871 coerce_result,
4872 code1,
4873 self.c_operator(op),
4874 code2))
4876 def c_operator(self, op):
4877 if op == 'is':
4878 return "=="
4879 elif op == 'is_not':
4880 return "!="
4881 else:
4882 return op
4885 class PrimaryCmpNode(ExprNode, CmpNode):
4886 # Non-cascaded comparison or first comparison of
4887 # a cascaded sequence.
4888 #
4889 # operator string
4890 # operand1 ExprNode
4891 # operand2 ExprNode
4892 # cascade CascadedCmpNode
4894 # We don't use the subexprs mechanism, because
4895 # things here are too complicated for it to handle.
4896 # Instead, we override all the framework methods
4897 # which use it.
4899 child_attrs = ['operand1', 'operand2', 'cascade']
4901 cascade = None
4903 def calculate_constant_result(self):
4904 self.constant_result = self.calculate_cascaded_constant_result(
4905 self.operand1.constant_result)
4907 def compile_time_value(self, denv):
4908 operand1 = self.operand1.compile_time_value(denv)
4909 return self.cascaded_compile_time_value(operand1, denv)
4911 def analyse_types(self, env):
4912 self.operand1.analyse_types(env)
4913 self.operand2.analyse_types(env)
4914 if self.cascade:
4915 self.cascade.analyse_types(env, self.operand2)
4916 self.is_pycmp = self.is_python_comparison()
4917 if self.is_pycmp:
4918 self.coerce_operands_to_pyobjects(env)
4919 if self.has_int_operands():
4920 self.coerce_chars_to_ints(env)
4921 if self.cascade:
4922 self.operand2 = self.operand2.coerce_to_simple(env)
4923 self.cascade.coerce_cascaded_operands_to_temp(env)
4924 self.check_operand_types(env)
4925 if self.is_python_result():
4926 self.type = PyrexTypes.py_object_type
4927 else:
4928 self.type = PyrexTypes.c_bint_type
4929 cdr = self.cascade
4930 while cdr:
4931 cdr.type = self.type
4932 cdr = cdr.cascade
4933 if self.is_pycmp or self.cascade:
4934 self.is_temp = 1
4936 def check_operand_types(self, env):
4937 self.check_types(env,
4938 self.operand1, self.operator, self.operand2)
4939 if self.cascade:
4940 self.cascade.check_operand_types(env, self.operand2)
4942 def has_python_operands(self):
4943 return (self.operand1.type.is_pyobject
4944 or self.operand2.type.is_pyobject)
4946 def coerce_operands_to_pyobjects(self, env):
4947 self.operand1 = self.operand1.coerce_to_pyobject(env)
4948 self.operand2 = self.operand2.coerce_to_pyobject(env)
4949 if self.cascade:
4950 self.cascade.coerce_operands_to_pyobjects(env)
4952 def has_int_operands(self):
4953 return (self.operand1.type.is_int or self.operand2.type.is_int) \
4954 or (self.cascade and self.cascade.has_int_operands())
4956 def coerce_chars_to_ints(self, env):
4957 # coerce literal single-char strings to c chars
4958 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
4959 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
4960 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4961 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4962 if self.cascade:
4963 self.cascade.coerce_chars_to_ints(env)
4965 def check_const(self):
4966 self.operand1.check_const()
4967 self.operand2.check_const()
4968 if self.cascade:
4969 self.not_const()
4971 def calculate_result_code(self):
4972 if self.operand1.type.is_complex:
4973 if self.operator == "!=":
4974 negation = "!"
4975 else:
4976 negation = ""
4977 return "(%s%s(%s, %s))" % (
4978 negation,
4979 self.operand1.type.binary_op('=='),
4980 self.operand1.result(),
4981 self.operand2.result())
4982 else:
4983 return "(%s %s %s)" % (
4984 self.operand1.result(),
4985 self.c_operator(self.operator),
4986 self.operand2.result())
4988 def generate_evaluation_code(self, code):
4989 self.operand1.generate_evaluation_code(code)
4990 self.operand2.generate_evaluation_code(code)
4991 if self.is_temp:
4992 self.allocate_temp_result(code)
4993 self.generate_operation_code(code, self.result(),
4994 self.operand1, self.operator, self.operand2)
4995 if self.cascade:
4996 self.cascade.generate_evaluation_code(code,
4997 self.result(), self.operand2)
4998 self.operand1.generate_disposal_code(code)
4999 self.operand1.free_temps(code)
5000 self.operand2.generate_disposal_code(code)
5001 self.operand2.free_temps(code)
5003 def generate_subexpr_disposal_code(self, code):
5004 # If this is called, it is a non-cascaded cmp,
5005 # so only need to dispose of the two main operands.
5006 self.operand1.generate_disposal_code(code)
5007 self.operand2.generate_disposal_code(code)
5009 def free_subexpr_temps(self, code):
5010 # If this is called, it is a non-cascaded cmp,
5011 # so only need to dispose of the two main operands.
5012 self.operand1.free_temps(code)
5013 self.operand2.free_temps(code)
5015 def annotate(self, code):
5016 self.operand1.annotate(code)
5017 self.operand2.annotate(code)
5018 if self.cascade:
5019 self.cascade.annotate(code)
5022 class CascadedCmpNode(Node, CmpNode):
5023 # A CascadedCmpNode is not a complete expression node. It
5024 # hangs off the side of another comparison node, shares
5025 # its left operand with that node, and shares its result
5026 # with the PrimaryCmpNode at the head of the chain.
5027 #
5028 # operator string
5029 # operand2 ExprNode
5030 # cascade CascadedCmpNode
5032 child_attrs = ['operand2', 'cascade']
5034 cascade = None
5035 constant_result = constant_value_not_set # FIXME: where to calculate this?
5037 def analyse_types(self, env, operand1):
5038 self.operand2.analyse_types(env)
5039 if self.cascade:
5040 self.cascade.analyse_types(env, self.operand2)
5042 def check_operand_types(self, env, operand1):
5043 self.check_types(env,
5044 operand1, self.operator, self.operand2)
5045 if self.cascade:
5046 self.cascade.check_operand_types(env, self.operand2)
5048 def has_python_operands(self):
5049 return self.operand2.type.is_pyobject
5051 def coerce_operands_to_pyobjects(self, env):
5052 self.operand2 = self.operand2.coerce_to_pyobject(env)
5053 if self.cascade:
5054 self.cascade.coerce_operands_to_pyobjects(env)
5056 def has_int_operands(self):
5057 return self.operand2.type.is_int
5059 def coerce_chars_to_ints(self, env):
5060 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
5061 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
5063 def coerce_cascaded_operands_to_temp(self, env):
5064 if self.cascade:
5065 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
5066 self.operand2 = self.operand2.coerce_to_simple(env)
5067 self.cascade.coerce_cascaded_operands_to_temp(env)
5069 def generate_evaluation_code(self, code, result, operand1):
5070 if self.type.is_pyobject:
5071 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
5072 code.put_decref(result, self.type)
5073 else:
5074 code.putln("if (%s) {" % result)
5075 self.operand2.generate_evaluation_code(code)
5076 self.generate_operation_code(code, result,
5077 operand1, self.operator, self.operand2)
5078 if self.cascade:
5079 self.cascade.generate_evaluation_code(
5080 code, result, self.operand2)
5081 # Cascaded cmp result is always temp
5082 self.operand2.generate_disposal_code(code)
5083 self.operand2.free_temps(code)
5084 code.putln("}")
5086 def annotate(self, code):
5087 self.operand2.annotate(code)
5088 if self.cascade:
5089 self.cascade.annotate(code)
5092 binop_node_classes = {
5093 "or": BoolBinopNode,
5094 "and": BoolBinopNode,
5095 "|": IntBinopNode,
5096 "^": IntBinopNode,
5097 "&": IntBinopNode,
5098 "<<": IntBinopNode,
5099 ">>": IntBinopNode,
5100 "+": AddNode,
5101 "-": SubNode,
5102 "*": MulNode,
5103 "/": DivNode,
5104 "//": DivNode,
5105 "%": ModNode,
5106 "**": PowNode
5107 }
5109 def binop_node(pos, operator, operand1, operand2):
5110 # Construct binop node of appropriate class for
5111 # given operator.
5112 return binop_node_classes[operator](pos,
5113 operator = operator,
5114 operand1 = operand1,
5115 operand2 = operand2)
5117 #-------------------------------------------------------------------
5118 #
5119 # Coercion nodes
5120 #
5121 # Coercion nodes are special in that they are created during
5122 # the analyse_types phase of parse tree processing.
5123 # Their __init__ methods consequently incorporate some aspects
5124 # of that phase.
5125 #
5126 #-------------------------------------------------------------------
5128 class CoercionNode(ExprNode):
5129 # Abstract base class for coercion nodes.
5130 #
5131 # arg ExprNode node being coerced
5133 subexprs = ['arg']
5135 def __init__(self, arg):
5136 self.pos = arg.pos
5137 self.arg = arg
5138 if debug_coercion:
5139 print("%s Coercing %s" % (self, self.arg))
5141 def calculate_constant_result(self):
5142 # constant folding can break type coercion, so this is disabled
5143 pass
5145 def annotate(self, code):
5146 self.arg.annotate(code)
5147 if self.arg.type != self.type:
5148 file, line, col = self.pos
5149 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
5152 class CastNode(CoercionNode):
5153 # Wrap a node in a C type cast.
5155 def __init__(self, arg, new_type):
5156 CoercionNode.__init__(self, arg)
5157 self.type = new_type
5159 def calculate_result_code(self):
5160 return self.arg.result_as(self.type)
5162 def generate_result_code(self, code):
5163 self.arg.generate_result_code(code)
5166 class PyTypeTestNode(CoercionNode):
5167 # This node is used to check that a generic Python
5168 # object is an instance of a particular extension type.
5169 # This node borrows the result of its argument node.
5171 def __init__(self, arg, dst_type, env):
5172 # The arg is know to be a Python object, and
5173 # the dst_type is known to be an extension type.
5174 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
5175 CoercionNode.__init__(self, arg)
5176 self.type = dst_type
5177 self.result_ctype = arg.ctype()
5179 nogil_check = Node.gil_error
5180 gil_message = "Python type test"
5182 def analyse_types(self, env):
5183 pass
5185 def result_in_temp(self):
5186 return self.arg.result_in_temp()
5188 def is_ephemeral(self):
5189 return self.arg.is_ephemeral()
5191 def calculate_constant_result(self):
5192 # FIXME
5193 pass
5195 def calculate_result_code(self):
5196 return self.arg.result()
5198 def generate_result_code(self, code):
5199 if self.type.typeobj_is_available():
5200 if not self.type.is_builtin_type:
5201 code.globalstate.use_utility_code(type_test_utility_code)
5202 code.putln(
5203 "if (!(%s)) %s" % (
5204 self.type.type_test_code(self.arg.py_result()),
5205 code.error_goto(self.pos)))
5206 else:
5207 error(self.pos, "Cannot test type of extern C class "
5208 "without type object name specification")
5210 def generate_post_assignment_code(self, code):
5211 self.arg.generate_post_assignment_code(code)
5213 def free_temps(self, code):
5214 self.arg.free_temps(code)
5217 class NoneCheckNode(CoercionNode):
5218 # This node is used to check that a Python object is not None and
5219 # raises an appropriate exception (as specified by the creating
5220 # transform).
5222 def __init__(self, arg, exception_type_cname, exception_message):
5223 CoercionNode.__init__(self, arg)
5224 self.type = arg.type
5225 self.result_ctype = arg.ctype()
5226 self.exception_type_cname = exception_type_cname
5227 self.exception_message = exception_message
5229 def analyse_types(self, env):
5230 pass
5232 def result_in_temp(self):
5233 return self.arg.result_in_temp()
5235 def calculate_result_code(self):
5236 return self.arg.result()
5238 def generate_result_code(self, code):
5239 code.putln(
5240 "if (unlikely(%s == Py_None)) {" % self.arg.result())
5241 code.putln('PyErr_SetString(%s, "%s"); %s ' % (
5242 self.exception_type_cname,
5243 StringEncoding.escape_byte_string(self.exception_message),
5244 code.error_goto(self.pos)))
5245 code.putln("}")
5247 def generate_post_assignment_code(self, code):
5248 self.arg.generate_post_assignment_code(code)
5250 def free_temps(self, code):
5251 self.arg.free_temps(code)
5254 class CoerceToPyTypeNode(CoercionNode):
5255 # This node is used to convert a C data type
5256 # to a Python object.
5258 def __init__(self, arg, env):
5259 CoercionNode.__init__(self, arg)
5260 self.type = py_object_type
5261 self.is_temp = 1
5262 if not arg.type.create_to_py_utility_code(env):
5263 error(arg.pos,
5264 "Cannot convert '%s' to Python object" % arg.type)
5266 gil_message = "Converting to Python object"
5268 def coerce_to_boolean(self, env):
5269 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
5271 def coerce_to_integer(self, env):
5272 # If not already some C integer type, coerce to longint.
5273 if self.arg.type.is_int:
5274 return self.arg
5275 else:
5276 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
5278 def analyse_types(self, env):
5279 # The arg is always already analysed
5280 pass
5282 def generate_result_code(self, code):
5283 function = self.arg.type.to_py_function
5284 code.putln('%s = %s(%s); %s' % (
5285 self.result(),
5286 function,
5287 self.arg.result(),
5288 code.error_goto_if_null(self.result(), self.pos)))
5289 code.put_gotref(self.py_result())
5292 class CoerceFromPyTypeNode(CoercionNode):
5293 # This node is used to convert a Python object
5294 # to a C data type.
5296 def __init__(self, result_type, arg, env):
5297 CoercionNode.__init__(self, arg)
5298 self.type = result_type
5299 self.is_temp = 1
5300 if not result_type.create_from_py_utility_code(env):
5301 error(arg.pos,
5302 "Cannot convert Python object to '%s'" % result_type)
5303 if self.type.is_string and self.arg.is_ephemeral():
5304 error(arg.pos,
5305 "Obtaining char * from temporary Python value")
5307 def analyse_types(self, env):
5308 # The arg is always already analysed
5309 pass
5311 def generate_result_code(self, code):
5312 function = self.type.from_py_function
5313 operand = self.arg.py_result()
5314 rhs = "%s(%s)" % (function, operand)
5315 if self.type.is_enum:
5316 rhs = typecast(self.type, c_long_type, rhs)
5317 code.putln('%s = %s; %s' % (
5318 self.result(),
5319 rhs,
5320 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
5321 if self.type.is_pyobject:
5322 code.put_gotref(self.py_result())
5325 class CoerceToBooleanNode(CoercionNode):
5326 # This node is used when a result needs to be used
5327 # in a boolean context.
5329 def __init__(self, arg, env):
5330 CoercionNode.__init__(self, arg)
5331 self.type = PyrexTypes.c_bint_type
5332 if arg.type.is_pyobject:
5333 self.is_temp = 1
5335 def nogil_check(self, env):
5336 if self.arg.type.is_pyobject:
5337 self.gil_error()
5339 gil_message = "Truth-testing Python object"
5341 def check_const(self):
5342 if self.is_temp:
5343 self.not_const()
5344 self.arg.check_const()
5346 def calculate_result_code(self):
5347 return "(%s != 0)" % self.arg.result()
5349 def generate_result_code(self, code):
5350 if self.arg.type.is_pyobject:
5351 code.putln(
5352 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5353 self.result(),
5354 self.arg.py_result(),
5355 code.error_goto_if_neg(self.result(), self.pos)))
5357 class CoerceToComplexNode(CoercionNode):
5359 def __init__(self, arg, dst_type, env):
5360 if arg.type.is_complex:
5361 arg = arg.coerce_to_simple(env)
5362 self.type = dst_type
5363 CoercionNode.__init__(self, arg)
5364 dst_type.create_declaration_utility_code(env)
5366 def calculate_result_code(self):
5367 if self.arg.type.is_complex:
5368 real_part = "__Pyx_REAL_PART(%s)" % self.arg.result()
5369 imag_part = "__Pyx_IMAG_PART(%s)" % self.arg.result()
5370 else:
5371 real_part = self.arg.result()
5372 imag_part = "0"
5373 return "%s(%s, %s)" % (
5374 self.type.from_parts,
5375 real_part,
5376 imag_part)
5378 def generate_result_code(self, code):
5379 pass
5381 class CoerceToTempNode(CoercionNode):
5382 # This node is used to force the result of another node
5383 # to be stored in a temporary. It is only used if the
5384 # argument node's result is not already in a temporary.
5386 def __init__(self, arg, env):
5387 CoercionNode.__init__(self, arg)
5388 self.type = self.arg.type
5389 self.is_temp = 1
5390 if self.type.is_pyobject:
5391 self.result_ctype = py_object_type
5393 gil_message = "Creating temporary Python reference"
5395 def analyse_types(self, env):
5396 # The arg is always already analysed
5397 pass
5399 def coerce_to_boolean(self, env):
5400 self.arg = self.arg.coerce_to_boolean(env)
5401 self.type = self.arg.type
5402 self.result_ctype = self.type
5403 return self
5405 def generate_result_code(self, code):
5406 #self.arg.generate_evaluation_code(code) # Already done
5407 # by generic generate_subexpr_evaluation_code!
5408 code.putln("%s = %s;" % (
5409 self.result(), self.arg.result_as(self.ctype())))
5410 if self.type.is_pyobject:
5411 code.put_incref(self.result(), self.ctype())
5414 class CloneNode(CoercionNode):
5415 # This node is employed when the result of another node needs
5416 # to be used multiple times. The argument node's result must
5417 # be in a temporary. This node "borrows" the result from the
5418 # argument node, and does not generate any evaluation or
5419 # disposal code for it. The original owner of the argument
5420 # node is responsible for doing those things.
5422 subexprs = [] # Arg is not considered a subexpr
5423 nogil_check = None
5425 def __init__(self, arg):
5426 CoercionNode.__init__(self, arg)
5427 if hasattr(arg, 'type'):
5428 self.type = arg.type
5429 self.result_ctype = arg.result_ctype
5430 if hasattr(arg, 'entry'):
5431 self.entry = arg.entry
5433 def result(self):
5434 return self.arg.result()
5436 def analyse_types(self, env):
5437 self.type = self.arg.type
5438 self.result_ctype = self.arg.result_ctype
5439 self.is_temp = 1
5440 if hasattr(self.arg, 'entry'):
5441 self.entry = self.arg.entry
5443 def generate_evaluation_code(self, code):
5444 pass
5446 def generate_result_code(self, code):
5447 pass
5449 def generate_disposal_code(self, code):
5450 pass
5452 def free_temps(self, code):
5453 pass
5456 #------------------------------------------------------------------------------------
5457 #
5458 # Runtime support code
5459 #
5460 #------------------------------------------------------------------------------------
5462 get_name_interned_utility_code = UtilityCode(
5463 proto = """
5464 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
5465 """,
5466 impl = """
5467 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
5468 PyObject *result;
5469 result = PyObject_GetAttr(dict, name);
5470 if (!result)
5471 PyErr_SetObject(PyExc_NameError, name);
5472 return result;
5473 }
5474 """)
5476 #------------------------------------------------------------------------------------
5478 import_utility_code = UtilityCode(
5479 proto = """
5480 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
5481 """,
5482 impl = """
5483 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
5484 PyObject *__import__ = 0;
5485 PyObject *empty_list = 0;
5486 PyObject *module = 0;
5487 PyObject *global_dict = 0;
5488 PyObject *empty_dict = 0;
5489 PyObject *list;
5490 __import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
5491 if (!__import__)
5492 goto bad;
5493 if (from_list)
5494 list = from_list;
5495 else {
5496 empty_list = PyList_New(0);
5497 if (!empty_list)
5498 goto bad;
5499 list = empty_list;
5500 }
5501 global_dict = PyModule_GetDict(%(GLOBALS)s);
5502 if (!global_dict)
5503 goto bad;
5504 empty_dict = PyDict_New();
5505 if (!empty_dict)
5506 goto bad;
5507 module = PyObject_CallFunctionObjArgs(__import__,
5508 name, global_dict, empty_dict, list, NULL);
5509 bad:
5510 Py_XDECREF(empty_list);
5511 Py_XDECREF(__import__);
5512 Py_XDECREF(empty_dict);
5513 return module;
5514 }
5515 """ % {
5516 "BUILTINS": Naming.builtins_cname,
5517 "GLOBALS": Naming.module_cname,
5518 })
5520 #------------------------------------------------------------------------------------
5522 get_exception_utility_code = UtilityCode(
5523 proto = """
5524 static PyObject *__Pyx_GetExcValue(void); /*proto*/
5525 """,
5526 impl = """
5527 static PyObject *__Pyx_GetExcValue(void) {
5528 PyObject *type = 0, *value = 0, *tb = 0;
5529 PyObject *tmp_type, *tmp_value, *tmp_tb;
5530 PyObject *result = 0;
5531 PyThreadState *tstate = PyThreadState_Get();
5532 PyErr_Fetch(&type, &value, &tb);
5533 PyErr_NormalizeException(&type, &value, &tb);
5534 if (PyErr_Occurred())
5535 goto bad;
5536 if (!value) {
5537 value = Py_None;
5538 Py_INCREF(value);
5539 }
5540 tmp_type = tstate->exc_type;
5541 tmp_value = tstate->exc_value;
5542 tmp_tb = tstate->exc_traceback;
5543 tstate->exc_type = type;
5544 tstate->exc_value = value;
5545 tstate->exc_traceback = tb;
5546 /* Make sure tstate is in a consistent state when we XDECREF
5547 these objects (XDECREF may run arbitrary code). */
5548 Py_XDECREF(tmp_type);
5549 Py_XDECREF(tmp_value);
5550 Py_XDECREF(tmp_tb);
5551 result = value;
5552 Py_XINCREF(result);
5553 type = 0;
5554 value = 0;
5555 tb = 0;
5556 bad:
5557 Py_XDECREF(type);
5558 Py_XDECREF(value);
5559 Py_XDECREF(tb);
5560 return result;
5561 }
5562 """)
5564 #------------------------------------------------------------------------------------
5566 type_test_utility_code = UtilityCode(
5567 proto = """
5568 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
5569 """,
5570 impl = """
5571 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
5572 if (!type) {
5573 PyErr_Format(PyExc_SystemError, "Missing type object");
5574 return 0;
5575 }
5576 if (obj == Py_None || PyObject_TypeCheck(obj, type))
5577 return 1;
5578 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
5579 Py_TYPE(obj)->tp_name, type->tp_name);
5580 return 0;
5581 }
5582 """)
5584 #------------------------------------------------------------------------------------
5586 create_class_utility_code = UtilityCode(
5587 proto = """
5588 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
5589 """,
5590 impl = """
5591 static PyObject *__Pyx_CreateClass(
5592 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
5593 {
5594 PyObject *py_modname;
5595 PyObject *result = 0;
5597 #if PY_MAJOR_VERSION < 3
5598 py_modname = PyString_FromString(modname);
5599 #else
5600 py_modname = PyUnicode_FromString(modname);
5601 #endif
5602 if (!py_modname)
5603 goto bad;
5604 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
5605 goto bad;
5606 #if PY_MAJOR_VERSION < 3
5607 result = PyClass_New(bases, dict, name);
5608 #else
5609 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
5610 #endif
5611 bad:
5612 Py_XDECREF(py_modname);
5613 return result;
5614 }
5615 """)
5617 #------------------------------------------------------------------------------------
5619 cpp_exception_utility_code = UtilityCode(
5620 proto = """
5621 #ifndef __Pyx_CppExn2PyErr
5622 static void __Pyx_CppExn2PyErr() {
5623 try {
5624 if (PyErr_Occurred())
5625 ; // let the latest Python exn pass through and ignore the current one
5626 else
5627 throw;
5628 } catch (const std::out_of_range& exn) {
5629 // catch out_of_range explicitly so the proper Python exn may be raised
5630 PyErr_SetString(PyExc_IndexError, exn.what());
5631 } catch (const std::exception& exn) {
5632 PyErr_SetString(PyExc_RuntimeError, exn.what());
5633 }
5634 catch (...)
5635 {
5636 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
5637 }
5638 }
5639 #endif
5640 """,
5641 impl = ""
5642 )
5644 #------------------------------------------------------------------------------------
5646 # If the is_unsigned flag is set, we need to do some extra work to make
5647 # sure the index doesn't become negative.
5649 getitem_int_utility_code = UtilityCode(
5650 proto = """
5652 static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
5653 PyObject *r;
5654 if (!j) return NULL;
5655 r = PyObject_GetItem(o, j);
5656 Py_DECREF(j);
5657 return r;
5658 }
5660 """ + ''.join([
5661 """
5662 #define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5663 __Pyx_GetItemInt_%(type)s_Fast(o, i, size <= sizeof(long)) : \\
5664 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
5666 static INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5667 if (likely(o != Py_None)) {
5668 if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
5669 PyObject *r = Py%(type)s_GET_ITEM(o, i);
5670 Py_INCREF(r);
5671 return r;
5672 }
5673 else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
5674 PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
5675 Py_INCREF(r);
5676 return r;
5677 }
5678 }
5679 return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
5680 }
5681 """ % {'type' : type_name} for type_name in ('List', 'Tuple')
5682 ]) + """
5684 #define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5685 __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \\
5686 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
5688 static INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5689 PyObject *r;
5690 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
5691 r = PyList_GET_ITEM(o, i);
5692 Py_INCREF(r);
5693 }
5694 else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
5695 r = PyTuple_GET_ITEM(o, i);
5696 Py_INCREF(r);
5697 }
5698 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
5699 r = PySequence_GetItem(o, i);
5700 }
5701 else {
5702 r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
5703 }
5704 return r;
5705 }
5706 """,
5707 impl = """
5708 """)
5712 #------------------------------------------------------------------------------------
5714 setitem_int_utility_code = UtilityCode(
5715 proto = """
5716 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5717 __Pyx_SetItemInt_Fast(o, i, v, size <= sizeof(long)) : \\
5718 __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
5720 static INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
5721 int r;
5722 if (!j) return -1;
5723 r = PyObject_SetItem(o, j, v);
5724 Py_DECREF(j);
5725 return r;
5726 }
5728 static INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int fits_long) {
5729 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
5730 Py_INCREF(v);
5731 Py_DECREF(PyList_GET_ITEM(o, i));
5732 PyList_SET_ITEM(o, i, v);
5733 return 1;
5734 }
5735 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
5736 return PySequence_SetItem(o, i, v);
5737 else {
5738 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
5739 return __Pyx_SetItemInt_Generic(o, j, v);
5740 }
5741 }
5742 """,
5743 impl = """
5744 """)
5746 #------------------------------------------------------------------------------------
5748 delitem_int_utility_code = UtilityCode(
5749 proto = """
5750 #define __Pyx_DelItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5751 __Pyx_DelItemInt_Fast(o, i, size <= sizeof(long)) : \\
5752 __Pyx_DelItem_Generic(o, to_py_func(i)))
5754 static INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
5755 int r;
5756 if (!j) return -1;
5757 r = PyObject_DelItem(o, j);
5758 Py_DECREF(j);
5759 return r;
5760 }
5762 static INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5763 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
5764 return PySequence_DelItem(o, i);
5765 else {
5766 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
5767 return __Pyx_DelItem_Generic(o, j);
5768 }
5769 }
5770 """,
5771 impl = """
5772 """)
5774 #------------------------------------------------------------------------------------
5776 raise_noneattr_error_utility_code = UtilityCode(
5777 proto = """
5778 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
5779 """,
5780 impl = '''
5781 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
5782 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
5783 }
5784 ''')
5786 raise_noneindex_error_utility_code = UtilityCode(
5787 proto = """
5788 static INLINE void __Pyx_RaiseNoneIndexingError(void);
5789 """,
5790 impl = '''
5791 static INLINE void __Pyx_RaiseNoneIndexingError(void) {
5792 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
5793 }
5794 ''')
5796 raise_none_iter_error_utility_code = UtilityCode(
5797 proto = """
5798 static INLINE void __Pyx_RaiseNoneNotIterableError(void);
5799 """,
5800 impl = '''
5801 static INLINE void __Pyx_RaiseNoneNotIterableError(void) {
5802 PyErr_SetString(PyExc_TypeError, "'NoneType' object is iterable");
5803 }
5804 ''')
5806 raise_too_many_values_to_unpack = UtilityCode(
5807 proto = """
5808 static INLINE void __Pyx_RaiseTooManyValuesError(void);
5809 """,
5810 impl = '''
5811 static INLINE void __Pyx_RaiseTooManyValuesError(void) {
5812 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
5813 }
5814 ''')
5816 raise_need_more_values_to_unpack = UtilityCode(
5817 proto = """
5818 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
5819 """,
5820 impl = '''
5821 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
5822 PyErr_Format(PyExc_ValueError,
5823 #if PY_VERSION_HEX < 0x02050000
5824 "need more than %d value%s to unpack", (int)index,
5825 #else
5826 "need more than %zd value%s to unpack", index,
5827 #endif
5828 (index == 1) ? "" : "s");
5829 }
5830 ''')
5832 #------------------------------------------------------------------------------------
5834 tuple_unpacking_error_code = UtilityCode(
5835 proto = """
5836 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
5837 """,
5838 impl = """
5839 static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
5840 if (t == Py_None) {
5841 __Pyx_RaiseNoneNotIterableError();
5842 } else if (PyTuple_GET_SIZE(t) < index) {
5843 __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
5844 } else {
5845 __Pyx_RaiseTooManyValuesError();
5846 }
5847 }
5848 """,
5849 requires = [raise_none_iter_error_utility_code,
5850 raise_need_more_values_to_unpack,
5851 raise_too_many_values_to_unpack]
5852 )
5854 unpacking_utility_code = UtilityCode(
5855 proto = """
5856 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
5857 static int __Pyx_EndUnpack(PyObject *); /*proto*/
5858 """,
5859 impl = """
5860 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
5861 PyObject *item;
5862 if (!(item = PyIter_Next(iter))) {
5863 if (!PyErr_Occurred()) {
5864 __Pyx_RaiseNeedMoreValuesError(index);
5865 }
5866 }
5867 return item;
5868 }
5870 static int __Pyx_EndUnpack(PyObject *iter) {
5871 PyObject *item;
5872 if ((item = PyIter_Next(iter))) {
5873 Py_DECREF(item);
5874 __Pyx_RaiseTooManyValuesError();
5875 return -1;
5876 }
5877 else if (!PyErr_Occurred())
5878 return 0;
5879 else
5880 return -1;
5881 }
5882 """,
5883 requires = [raise_need_more_values_to_unpack,
5884 raise_too_many_values_to_unpack]
5885 )
5888 #------------------------------------------------------------------------------------
5890 int_pow_utility_code = UtilityCode(
5891 proto="""
5892 static INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
5893 """,
5894 impl="""
5895 static INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
5896 %(type)s t = b;
5897 switch (e) {
5898 case 3:
5899 t *= b;
5900 case 2:
5901 t *= b;
5902 case 1:
5903 return t;
5904 case 0:
5905 return 1;
5906 }
5907 if (unlikely(e<0)) return 0;
5908 t = 1;
5909 while (likely(e)) {
5910 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
5911 b *= b;
5912 e >>= 1;
5913 }
5914 return t;
5915 }
5916 """)
5918 # ------------------------------ Division ------------------------------------
5920 div_int_utility_code = UtilityCode(
5921 proto="""
5922 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
5923 """,
5924 impl="""
5925 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
5926 %(type)s q = a / b;
5927 %(type)s r = a - q*b;
5928 q -= ((r != 0) & ((r ^ b) < 0));
5929 return q;
5930 }
5931 """)
5933 mod_int_utility_code = UtilityCode(
5934 proto="""
5935 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
5936 """,
5937 impl="""
5938 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
5939 %(type)s r = a %% b;
5940 r += ((r != 0) & ((r ^ b) < 0)) * b;
5941 return r;
5942 }
5943 """)
5945 mod_float_utility_code = UtilityCode(
5946 proto="""
5947 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
5948 """,
5949 impl="""
5950 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
5951 %(type)s r = fmod%(math_h_modifier)s(a, b);
5952 r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
5953 return r;
5954 }
5955 """)
5957 cdivision_warning_utility_code = UtilityCode(
5958 proto="""
5959 static int __Pyx_cdivision_warning(void); /* proto */
5960 """,
5961 impl="""
5962 static int __Pyx_cdivision_warning(void) {
5963 return PyErr_WarnExplicit(PyExc_RuntimeWarning,
5964 "division with oppositely signed operands, C and Python semantics differ",
5965 %(FILENAME)s,
5966 %(LINENO)s,
5967 __Pyx_MODULE_NAME,
5968 NULL);
5969 }
5970 """ % {
5971 'FILENAME': Naming.filename_cname,
5972 'LINENO': Naming.lineno_cname,
5973 })
5975 # from intobject.c
5976 division_overflow_test_code = UtilityCode(
5977 proto="""
5978 #define UNARY_NEG_WOULD_OVERFLOW(x) \
5979 (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
5980 """)
