Cython has moved to github.

cython-devel

view Cython/Compiler/ExprNodes.py @ 834:4695bbb3a785

Better integer literal parsing.

Now accepts U and LL suffixes, and large integer literals are longs rather than being truncated as Python objects.
author Robert Bradshaw <robertwb@math.washington.edu>
date Thu Jul 31 00:55:14 2008 -0700 (3 years ago)
parents f1cc08ccb0b3
children 7d24ad4f8a9d
line source
1 #
2 # Pyrex - Parse tree nodes for expressions
3 #
5 import operator
6 from string import join
8 from Errors import error, warning, InternalError
9 import Naming
10 from Nodes import Node
11 import PyrexTypes
12 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
13 from Builtin import list_type, tuple_type, dict_type
14 import Symtab
15 import Options
16 from Annotate import AnnotationItem
18 from Cython.Debugging import print_call_chain
19 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
20 debug_coercion
23 class ExprNode(Node):
24 # subexprs [string] Class var holding names of subexpr node attrs
25 # type PyrexType Type of the result
26 # result_code string Code fragment
27 # result_ctype string C type of result_code if different from type
28 # is_temp boolean Result is in a temporary variable
29 # is_sequence_constructor
30 # boolean Is a list or tuple constructor expression
31 # saved_subexpr_nodes
32 # [ExprNode or [ExprNode or None] or None]
33 # Cached result of subexpr_nodes()
35 result_ctype = None
36 type = None
38 # The Analyse Expressions phase for expressions is split
39 # into two sub-phases:
40 #
41 # Analyse Types
42 # Determines the result type of the expression based
43 # on the types of its sub-expressions, and inserts
44 # coercion nodes into the expression tree where needed.
45 # Marks nodes which will need to have temporary variables
46 # allocated.
47 #
48 # Allocate Temps
49 # Allocates temporary variables where needed, and fills
50 # in the result_code field of each node.
51 #
52 # ExprNode provides some convenience routines which
53 # perform both of the above phases. These should only
54 # be called from statement nodes, and only when no
55 # coercion nodes need to be added around the expression
56 # being analysed. In that case, the above two phases
57 # should be invoked separately.
58 #
59 # Framework code in ExprNode provides much of the common
60 # processing for the various phases. It makes use of the
61 # 'subexprs' class attribute of ExprNodes, which should
62 # contain a list of the names of attributes which can
63 # hold sub-nodes or sequences of sub-nodes.
64 #
65 # The framework makes use of a number of abstract methods.
66 # Their responsibilities are as follows.
67 #
68 # Declaration Analysis phase
69 #
70 # analyse_target_declaration
71 # Called during the Analyse Declarations phase to analyse
72 # the LHS of an assignment or argument of a del statement.
73 # Nodes which cannot be the LHS of an assignment need not
74 # implement it.
75 #
76 # Expression Analysis phase
77 #
78 # analyse_types
79 # - Call analyse_types on all sub-expressions.
80 # - Check operand types, and wrap coercion nodes around
81 # sub-expressions where needed.
82 # - Set the type of this node.
83 # - If a temporary variable will be required for the
84 # result, set the is_temp flag of this node.
85 #
86 # analyse_target_types
87 # Called during the Analyse Types phase to analyse
88 # the LHS of an assignment or argument of a del
89 # statement. Similar responsibilities to analyse_types.
90 #
91 # allocate_temps
92 # - Call allocate_temps for all sub-nodes.
93 # - Call allocate_temp for this node.
94 # - If a temporary was allocated, call release_temp on
95 # all sub-expressions.
96 #
97 # allocate_target_temps
98 # - Call allocate_temps on sub-nodes and allocate any other
99 # temps used during assignment.
100 # - Fill in result_code with a C lvalue if needed.
101 # - If a rhs node is supplied, call release_temp on it.
102 # - Call release_temp on sub-nodes and release any other
103 # temps used during assignment.
104 #
105 # calculate_result_code
106 # - Called during the Allocate Temps phase. Should return a
107 # C code fragment evaluating to the result. This is only
108 # called when the result is not a temporary.
109 #
110 # target_code
111 # Called by the default implementation of allocate_target_temps.
112 # Should return a C lvalue for assigning to the node. The default
113 # implementation calls calculate_result_code.
114 #
115 # check_const
116 # - Check that this node and its subnodes form a
117 # legal constant expression. If so, do nothing,
118 # otherwise call not_const.
119 #
120 # The default implementation of check_const
121 # assumes that the expression is not constant.
122 #
123 # check_const_addr
124 # - Same as check_const, except check that the
125 # expression is a C lvalue whose address is
126 # constant. Otherwise, call addr_not_const.
127 #
128 # The default implementation of calc_const_addr
129 # assumes that the expression is not a constant
130 # lvalue.
131 #
132 # Code Generation phase
133 #
134 # generate_evaluation_code
135 # - Call generate_evaluation_code for sub-expressions.
136 # - Perform the functions of generate_result_code
137 # (see below).
138 # - If result is temporary, call generate_disposal_code
139 # on all sub-expressions.
140 #
141 # A default implementation of generate_evaluation_code
142 # is provided which uses the following abstract method:
143 #
144 # generate_result_code
145 # - Generate any C statements necessary to calculate
146 # the result of this node from the results of its
147 # sub-expressions.
148 #
149 # generate_assignment_code
150 # Called on the LHS of an assignment.
151 # - Call generate_evaluation_code for sub-expressions.
152 # - Generate code to perform the assignment.
153 # - If the assignment absorbed a reference, call
154 # generate_post_assignment_code on the RHS,
155 # otherwise call generate_disposal_code on it.
156 #
157 # generate_deletion_code
158 # Called on an argument of a del statement.
159 # - Call generate_evaluation_code for sub-expressions.
160 # - Generate code to perform the deletion.
161 # - Call generate_disposal_code on all sub-expressions.
162 #
163 #
165 is_sequence_constructor = 0
166 is_attribute = 0
168 saved_subexpr_nodes = None
169 is_temp = 0
171 def get_child_attrs(self):
172 return self.subexprs
173 child_attrs = property(fget=get_child_attrs)
175 def not_implemented(self, method_name):
176 print_call_chain(method_name, "not implemented") ###
177 raise InternalError(
178 "%s.%s not implemented" %
179 (self.__class__.__name__, method_name))
181 def is_lvalue(self):
182 return 0
184 def is_ephemeral(self):
185 # An ephemeral node is one whose result is in
186 # a Python temporary and we suspect there are no
187 # other references to it. Certain operations are
188 # disallowed on such values, since they are
189 # likely to result in a dangling pointer.
190 return self.type.is_pyobject and self.is_temp
192 def subexpr_nodes(self):
193 # Extract a list of subexpression nodes based
194 # on the contents of the subexprs class attribute.
195 if self.saved_subexpr_nodes is None:
196 nodes = []
197 for name in self.subexprs:
198 item = getattr(self, name)
199 if item:
200 if isinstance(item, ExprNode):
201 nodes.append(item)
202 else:
203 nodes.extend(item)
204 self.saved_subexpr_nodes = nodes
205 return self.saved_subexpr_nodes
207 def result_as(self, type = None):
208 # Return the result code cast to the specified C type.
209 return typecast(type, self.ctype(), self.result_code)
211 def py_result(self):
212 # Return the result code cast to PyObject *.
213 return self.result_as(py_object_type)
215 def ctype(self):
216 # Return the native C type of the result (i.e. the
217 # C type of the result_code expression).
218 return self.result_ctype or self.type
220 def compile_time_value(self, denv):
221 # Return value of compile-time expression, or report error.
222 error(self.pos, "Invalid compile-time expression")
224 def compile_time_value_error(self, e):
225 error(self.pos, "Error in compile-time expression: %s: %s" % (
226 e.__class__.__name__, e))
228 # ------------- Declaration Analysis ----------------
230 def analyse_target_declaration(self, env):
231 error(self.pos, "Cannot assign to or delete this")
233 # ------------- Expression Analysis ----------------
235 def analyse_const_expression(self, env):
236 # Called during the analyse_declarations phase of a
237 # constant expression. Analyses the expression's type,
238 # checks whether it is a legal const expression,
239 # and determines its value.
240 self.analyse_types(env)
241 self.allocate_temps(env)
242 self.check_const()
244 def analyse_expressions(self, env):
245 # Convenience routine performing both the Type
246 # Analysis and Temp Allocation phases for a whole
247 # expression.
248 self.analyse_types(env)
249 self.allocate_temps(env)
251 def analyse_target_expression(self, env, rhs):
252 # Convenience routine performing both the Type
253 # Analysis and Temp Allocation phases for the LHS of
254 # an assignment.
255 self.analyse_target_types(env)
256 self.allocate_target_temps(env, rhs)
258 def analyse_boolean_expression(self, env):
259 # Analyse expression and coerce to a boolean.
260 self.analyse_types(env)
261 bool = self.coerce_to_boolean(env)
262 bool.allocate_temps(env)
263 return bool
265 def analyse_temp_boolean_expression(self, env):
266 # Analyse boolean expression and coerce result into
267 # a temporary. This is used when a branch is to be
268 # performed on the result and we won't have an
269 # opportunity to ensure disposal code is executed
270 # afterwards. By forcing the result into a temporary,
271 # we ensure that all disposal has been done by the
272 # time we get the result.
273 self.analyse_types(env)
274 bool = self.coerce_to_boolean(env)
275 temp_bool = bool.coerce_to_temp(env)
276 temp_bool.allocate_temps(env)
277 return temp_bool
279 # --------------- Type Analysis ------------------
281 def analyse_as_module(self, env):
282 # If this node can be interpreted as a reference to a
283 # cimported module, return its scope, else None.
284 return None
286 def analyse_as_extension_type(self, env):
287 # If this node can be interpreted as a reference to an
288 # extension type, return its type, else None.
289 return None
291 def analyse_types(self, env):
292 self.not_implemented("analyse_types")
294 def analyse_target_types(self, env):
295 self.analyse_types(env)
297 def gil_assignment_check(self, env):
298 if env.nogil and self.type.is_pyobject:
299 error(self.pos, "Assignment of Python object not allowed without gil")
301 def check_const(self):
302 self.not_const()
304 def not_const(self):
305 error(self.pos, "Not allowed in a constant expression")
307 def check_const_addr(self):
308 self.addr_not_const()
310 def addr_not_const(self):
311 error(self.pos, "Address is not constant")
313 def gil_check(self, env):
314 if env.nogil and self.type.is_pyobject:
315 self.gil_error()
317 # ----------------- Result Allocation -----------------
319 def result_in_temp(self):
320 # Return true if result is in a temporary owned by
321 # this node or one of its subexpressions. Overridden
322 # by certain nodes which can share the result of
323 # a subnode.
324 return self.is_temp
326 def allocate_target_temps(self, env, rhs):
327 # Perform temp allocation for the LHS of an assignment.
328 if debug_temp_alloc:
329 print("%s Allocating target temps" % self)
330 self.allocate_subexpr_temps(env)
331 self.result_code = self.target_code()
332 if rhs:
333 rhs.release_temp(env)
334 self.release_subexpr_temps(env)
336 def allocate_temps(self, env, result = None):
337 # Allocate temporary variables for this node and
338 # all its sub-expressions. If a result is specified,
339 # this must be a temp node and the specified variable
340 # is used as the result instead of allocating a new
341 # one.
342 if debug_temp_alloc:
343 print("%s Allocating temps" % self)
344 self.allocate_subexpr_temps(env)
345 self.allocate_temp(env, result)
346 if self.is_temp:
347 self.release_subexpr_temps(env)
349 def allocate_subexpr_temps(self, env):
350 # Allocate temporary variables for all sub-expressions
351 # of this node.
352 if debug_temp_alloc:
353 print("%s Allocating temps for: %s" % (self, self.subexprs))
354 for node in self.subexpr_nodes():
355 if node:
356 if debug_temp_alloc:
357 print("%s Allocating temps for %s" % (self, node))
358 node.allocate_temps(env)
360 def allocate_temp(self, env, result = None):
361 # If this node requires a temporary variable for its
362 # result, allocate one, otherwise set the result to
363 # a C code fragment. If a result is specified,
364 # this must be a temp node and the specified variable
365 # is used as the result instead of allocating a new
366 # one.
367 if debug_temp_alloc:
368 print("%s Allocating temp" % self)
369 if result:
370 if not self.is_temp:
371 raise InternalError("Result forced on non-temp node")
372 self.result_code = result
373 elif self.is_temp:
374 type = self.type
375 if not type.is_void:
376 if type.is_pyobject:
377 type = PyrexTypes.py_object_type
378 self.result_code = env.allocate_temp(type)
379 else:
380 self.result_code = None
381 if debug_temp_alloc:
382 print("%s Allocated result %s" % (self, self.result_code))
383 else:
384 self.result_code = self.calculate_result_code()
386 def target_code(self):
387 # Return code fragment for use as LHS of a C assignment.
388 return self.calculate_result_code()
390 def calculate_result_code(self):
391 self.not_implemented("calculate_result_code")
393 # def release_target_temp(self, env):
394 # # Release temporaries used by LHS of an assignment.
395 # self.release_subexpr_temps(env)
397 def release_temp(self, env):
398 # If this node owns a temporary result, release it,
399 # otherwise release results of its sub-expressions.
400 if self.is_temp:
401 if debug_temp_alloc:
402 print("%s Releasing result %s" % (self, self.result_code))
403 env.release_temp(self.result_code)
404 else:
405 self.release_subexpr_temps(env)
407 def release_subexpr_temps(self, env):
408 # Release the results of all sub-expressions of
409 # this node.
410 for node in self.subexpr_nodes():
411 if node:
412 node.release_temp(env)
414 # ---------------- Code Generation -----------------
416 def make_owned_reference(self, code):
417 # If result is a pyobject, make sure we own
418 # a reference to it.
419 if self.type.is_pyobject and not self.result_in_temp():
420 code.put_incref(self.result_code, self.ctype())
422 def generate_evaluation_code(self, code):
423 code.mark_pos(self.pos)
424 # Generate code to evaluate this node and
425 # its sub-expressions, and dispose of any
426 # temporary results of its sub-expressions.
427 self.generate_subexpr_evaluation_code(code)
428 self.generate_result_code(code)
429 if self.is_temp:
430 self.generate_subexpr_disposal_code(code)
432 def generate_subexpr_evaluation_code(self, code):
433 for node in self.subexpr_nodes():
434 node.generate_evaluation_code(code)
436 def generate_result_code(self, code):
437 self.not_implemented("generate_result_code")
439 def generate_disposal_code(self, code):
440 # If necessary, generate code to dispose of
441 # temporary Python reference.
442 if self.is_temp:
443 if self.type.is_pyobject:
444 code.put_decref_clear(self.result_code, self.ctype())
445 else:
446 self.generate_subexpr_disposal_code(code)
448 def generate_subexpr_disposal_code(self, code):
449 # Generate code to dispose of temporary results
450 # of all sub-expressions.
451 for node in self.subexpr_nodes():
452 node.generate_disposal_code(code)
454 def generate_post_assignment_code(self, code):
455 # Same as generate_disposal_code except that
456 # assignment will have absorbed a reference to
457 # the result if it is a Python object.
458 if self.is_temp:
459 if self.type.is_pyobject:
460 code.putln("%s = 0;" % self.result_code)
461 else:
462 self.generate_subexpr_disposal_code(code)
464 def generate_assignment_code(self, rhs, code):
465 # Stub method for nodes which are not legal as
466 # the LHS of an assignment. An error will have
467 # been reported earlier.
468 pass
470 def generate_deletion_code(self, code):
471 # Stub method for nodes that are not legal as
472 # the argument of a del statement. An error
473 # will have been reported earlier.
474 pass
476 # ---------------- Annotation ---------------------
478 def annotate(self, code):
479 for node in self.subexpr_nodes():
480 node.annotate(code)
482 # ----------------- Coercion ----------------------
484 def coerce_to(self, dst_type, env):
485 # Coerce the result so that it can be assigned to
486 # something of type dst_type. If processing is necessary,
487 # wraps this node in a coercion node and returns that.
488 # Otherwise, returns this node unchanged.
489 #
490 # This method is called during the analyse_expressions
491 # phase of the src_node's processing.
492 src = self
493 src_type = self.type
494 src_is_py_type = src_type.is_pyobject
495 dst_is_py_type = dst_type.is_pyobject
497 if dst_type.is_pyobject:
498 if not src.type.is_pyobject:
499 src = CoerceToPyTypeNode(src, env)
500 if not src.type.subtype_of(dst_type):
501 if not isinstance(src, NoneNode):
502 src = PyTypeTestNode(src, dst_type, env)
503 elif src.type.is_pyobject:
504 src = CoerceFromPyTypeNode(dst_type, src, env)
505 else: # neither src nor dst are py types
506 # Added the string comparison, since for c types that
507 # is enough, but Cython gets confused when the types are
508 # in different files.
509 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
510 error(self.pos, "Cannot assign type '%s' to '%s'" %
511 (src.type, dst_type))
512 return src
514 def coerce_to_pyobject(self, env):
515 return self.coerce_to(PyrexTypes.py_object_type, env)
517 def coerce_to_boolean(self, env):
518 # Coerce result to something acceptable as
519 # a boolean value.
520 type = self.type
521 if type.is_pyobject or type.is_ptr or type.is_float:
522 return CoerceToBooleanNode(self, env)
523 else:
524 if not type.is_int and not type.is_error:
525 error(self.pos,
526 "Type '%s' not acceptable as a boolean" % type)
527 return self
529 def coerce_to_integer(self, env):
530 # If not already some C integer type, coerce to longint.
531 if self.type.is_int:
532 return self
533 else:
534 return self.coerce_to(PyrexTypes.c_long_type, env)
536 def coerce_to_temp(self, env):
537 # Ensure that the result is in a temporary.
538 if self.result_in_temp():
539 return self
540 else:
541 return CoerceToTempNode(self, env)
543 def coerce_to_simple(self, env):
544 # Ensure that the result is simple (see is_simple).
545 if self.is_simple():
546 return self
547 else:
548 return self.coerce_to_temp(env)
550 def is_simple(self):
551 # A node is simple if its result is something that can
552 # be referred to without performing any operations, e.g.
553 # a constant, local var, C global var, struct member
554 # reference, or temporary.
555 return self.result_in_temp()
558 class AtomicExprNode(ExprNode):
559 # Abstract base class for expression nodes which have
560 # no sub-expressions.
562 subexprs = []
565 class PyConstNode(AtomicExprNode):
566 # Abstract base class for constant Python values.
568 is_literal = 1
570 def is_simple(self):
571 return 1
573 def analyse_types(self, env):
574 self.type = py_object_type
576 def calculate_result_code(self):
577 return self.value
579 def generate_result_code(self, code):
580 pass
583 class NoneNode(PyConstNode):
584 # The constant value None
586 value = "Py_None"
588 def compile_time_value(self, denv):
589 return None
591 class EllipsisNode(PyConstNode):
592 # '...' in a subscript list.
594 value = "Py_Ellipsis"
596 def compile_time_value(self, denv):
597 return Ellipsis
600 class ConstNode(AtomicExprNode):
601 # Abstract base type for literal constant nodes.
602 #
603 # value string C code fragment
605 is_literal = 1
607 def is_simple(self):
608 return 1
610 def analyse_types(self, env):
611 pass # Types are held in class variables
613 def check_const(self):
614 pass
616 def calculate_result_code(self):
617 return str(self.value)
619 def generate_result_code(self, code):
620 pass
623 class BoolNode(ConstNode):
624 type = PyrexTypes.c_bint_type
625 # The constant value True or False
627 def compile_time_value(self, denv):
628 return self.value
630 def calculate_result_code(self):
631 return int(self.value)
633 class NullNode(ConstNode):
634 type = PyrexTypes.c_null_ptr_type
635 value = "NULL"
638 class CharNode(ConstNode):
639 type = PyrexTypes.c_char_type
641 def compile_time_value(self, denv):
642 return ord(self.value)
644 def calculate_result_code(self):
645 return "'%s'" % self.value
648 class IntNode(ConstNode):
650 # unsigned "" or "U"
651 # longness "" or "L" or "LL"
653 unsigned = ""
654 longness = ""
655 type = PyrexTypes.c_long_type
657 def coerce_to(self, dst_type, env):
658 # Arrange for a Python version of the string to be pre-allocated
659 # when coercing to a Python type.
660 if dst_type.is_pyobject:
661 self.entry = env.get_py_num(self.value, self.longness)
662 self.type = PyrexTypes.py_object_type
663 # We still need to perform normal coerce_to processing on the
664 # result, because we might be coercing to an extension type,
665 # in which case a type test node will be needed.
666 return ConstNode.coerce_to(self, dst_type, env)
668 def calculate_result_code(self):
669 if self.type.is_pyobject:
670 return self.entry.cname
671 else:
672 return str(self.value) + self.unsigned + self.longness
674 def compile_time_value(self, denv):
675 return int(self.value, 0)
678 class FloatNode(ConstNode):
679 type = PyrexTypes.c_double_type
681 def compile_time_value(self, denv):
682 return float(self.value)
684 def calculate_result_code(self):
685 strval = str(self.value)
686 if strval == 'nan':
687 return "(Py_HUGE_VAL * 0)"
688 elif strval == 'inf':
689 return "Py_HUGE_VAL"
690 elif strval == '-inf':
691 return "(-Py_HUGE_VAL)"
692 else:
693 return strval
696 class StringNode(ConstNode):
697 # entry Symtab.Entry
699 type = PyrexTypes.c_char_ptr_type
701 def compile_time_value(self, denv):
702 return self.value
704 def analyse_types(self, env):
705 self.entry = env.add_string_const(self.value)
707 def coerce_to(self, dst_type, env):
708 if dst_type.is_int:
709 if not self.type.is_pyobject and len(self.entry.init) == 1:
710 # we use the *encoded* value here
711 return CharNode(self.pos, value=self.entry.init)
712 else:
713 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
714 return self
715 # Arrange for a Python version of the string to be pre-allocated
716 # when coercing to a Python type.
717 if dst_type.is_pyobject and not self.type.is_pyobject:
718 node = self.as_py_string_node(env)
719 else:
720 node = self
721 # We still need to perform normal coerce_to processing on the
722 # result, because we might be coercing to an extension type,
723 # in which case a type test node will be needed.
724 return ConstNode.coerce_to(node, dst_type, env)
726 def as_py_string_node(self, env):
727 # Return a new StringNode with the same entry as this node
728 # but whose type is a Python type instead of a C type.
729 entry = self.entry
730 env.add_py_string(entry)
731 return StringNode(self.pos, entry = entry, type = py_object_type)
733 def calculate_result_code(self):
734 if self.type.is_pyobject:
735 return self.entry.pystring_cname
736 else:
737 return self.entry.cname
740 class IdentifierStringNode(ConstNode):
741 # A Python string that behaves like an identifier, e.g. for
742 # keyword arguments in a call, or for imported names
743 type = PyrexTypes.py_object_type
745 def analyse_types(self, env):
746 self.cname = env.intern_identifier(self.value)
748 def calculate_result_code(self):
749 return self.cname
752 class LongNode(AtomicExprNode):
753 # Python long integer literal
754 #
755 # value string
757 def compile_time_value(self, denv):
758 return long(self.value)
760 gil_message = "Constructing Python long int"
762 def analyse_types(self, env):
763 self.type = py_object_type
764 self.gil_check(env)
765 self.is_temp = 1
767 gil_message = "Constructing Python long int"
769 def generate_evaluation_code(self, code):
770 code.putln(
771 '%s = PyLong_FromString("%s", 0, 0); %s' % (
772 self.result_code,
773 self.value,
774 code.error_goto_if_null(self.result_code, self.pos)))
777 class ImagNode(AtomicExprNode):
778 # Imaginary number literal
779 #
780 # value float imaginary part
782 def compile_time_value(self, denv):
783 return complex(0.0, self.value)
785 def analyse_types(self, env):
786 self.type = py_object_type
787 self.gil_check(env)
788 self.is_temp = 1
790 gil_message = "Constructing complex number"
792 def generate_evaluation_code(self, code):
793 code.putln(
794 "%s = PyComplex_FromDoubles(0.0, %s); %s" % (
795 self.result_code,
796 self.value,
797 code.error_goto_if_null(self.result_code, self.pos)))
800 class NameNode(AtomicExprNode):
801 # Reference to a local or global variable name.
802 #
803 # name string Python name of the variable
804 #
805 # entry Entry Symbol table entry
806 # interned_cname string
808 is_name = 1
810 def compile_time_value(self, denv):
811 try:
812 return denv.lookup(self.name)
813 except KeyError:
814 error(self.pos, "Compile-time name '%s' not defined" % self.name)
816 def coerce_to(self, dst_type, env):
817 # If coercing to a generic pyobject and this is a builtin
818 # C function with a Python equivalent, manufacture a NameNode
819 # referring to the Python builtin.
820 #print "NameNode.coerce_to:", self.name, dst_type ###
821 if dst_type is py_object_type:
822 entry = self.entry
823 if entry and entry.is_cfunction:
824 var_entry = entry.as_variable
825 if var_entry:
826 if var_entry.is_builtin and Options.cache_builtins:
827 var_entry = env.declare_builtin(var_entry.name, self.pos)
828 node = NameNode(self.pos, name = self.name)
829 node.entry = var_entry
830 node.analyse_rvalue_entry(env)
831 return node
832 return AtomicExprNode.coerce_to(self, dst_type, env)
834 def analyse_as_module(self, env):
835 # Try to interpret this as a reference to a cimported module.
836 # Returns the module scope, or None.
837 entry = env.lookup(self.name)
838 if entry and entry.as_module:
839 return entry.as_module
840 return None
842 def analyse_as_extension_type(self, env):
843 # Try to interpret this as a reference to an extension type.
844 # Returns the extension type, or None.
845 entry = env.lookup(self.name)
846 if entry and entry.is_type and entry.type.is_extension_type:
847 return entry.type
848 else:
849 return None
851 def analyse_target_declaration(self, env):
852 self.entry = env.lookup_here(self.name)
853 if not self.entry:
854 self.entry = env.declare_var(self.name, py_object_type, self.pos)
855 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
856 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
857 if self.entry.is_declared_generic:
858 self.result_ctype = py_object_type
859 if self.entry.is_pyglobal and self.entry.is_member:
860 env.use_utility_code(type_cache_invalidation_code)
862 def analyse_types(self, env):
863 self.entry = env.lookup(self.name)
864 if not self.entry:
865 self.entry = env.declare_builtin(self.name, self.pos)
866 if not self.entry:
867 self.type = PyrexTypes.error_type
868 return
869 self.analyse_rvalue_entry(env)
871 def analyse_target_types(self, env):
872 self.analyse_entry(env)
873 if not self.is_lvalue():
874 error(self.pos, "Assignment to non-lvalue '%s'"
875 % self.name)
876 self.type = PyrexTypes.error_type
877 self.entry.used = 1
879 def analyse_rvalue_entry(self, env):
880 #print "NameNode.analyse_rvalue_entry:", self.name ###
881 #print "Entry:", self.entry.__dict__ ###
882 self.analyse_entry(env)
883 entry = self.entry
884 if entry.is_declared_generic:
885 self.result_ctype = py_object_type
886 if entry.is_pyglobal or entry.is_builtin:
887 if Options.cache_builtins and entry.is_builtin:
888 self.is_temp = 0
889 else:
890 self.is_temp = 1
891 env.use_utility_code(get_name_interned_utility_code)
892 self.gil_check(env)
894 gil_message = "Accessing Python global or builtin"
896 def analyse_entry(self, env):
897 #print "NameNode.analyse_entry:", self.name ###
898 self.check_identifier_kind()
899 entry = self.entry
900 type = entry.type
901 self.type = type
902 if entry.is_pyglobal or entry.is_builtin:
903 assert type.is_pyobject, "Python global or builtin not a Python object"
904 self.interned_cname = self.entry.interned_cname = \
905 env.intern_identifier(self.entry.name)
907 def check_identifier_kind(self):
908 #print "NameNode.check_identifier_kind:", self.entry.name ###
909 #print self.entry.__dict__ ###
910 entry = self.entry
911 #entry.used = 1
912 if not (entry.is_const or entry.is_variable
913 or entry.is_builtin or entry.is_cfunction):
914 if self.entry.as_variable:
915 self.entry = self.entry.as_variable
916 else:
917 error(self.pos,
918 "'%s' is not a constant, variable or function identifier" % self.name)
920 def is_simple(self):
921 # If it's not a C variable, it'll be in a temp.
922 return 1
924 def calculate_target_results(self, env):
925 pass
927 def check_const(self):
928 entry = self.entry
929 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
930 self.not_const()
932 def check_const_addr(self):
933 entry = self.entry
934 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
935 self.addr_not_const()
937 def is_lvalue(self):
938 return self.entry.is_variable and \
939 not self.entry.type.is_array and \
940 not self.entry.is_readonly
942 def is_ephemeral(self):
943 # Name nodes are never ephemeral, even if the
944 # result is in a temporary.
945 return 0
947 def allocate_temp(self, env, result = None):
948 AtomicExprNode.allocate_temp(self, env, result)
949 entry = self.entry
950 if entry:
951 entry.used = 1
952 if entry.utility_code:
953 env.use_utility_code(entry.utility_code)
955 def calculate_result_code(self):
956 entry = self.entry
957 if not entry:
958 return "<error>" # There was an error earlier
959 return entry.cname
961 def generate_result_code(self, code):
962 assert hasattr(self, 'entry')
963 entry = self.entry
964 if entry is None:
965 return # There was an error earlier
966 if entry.is_builtin and Options.cache_builtins:
967 return # Lookup already cached
968 elif entry.is_pyglobal or entry.is_builtin:
969 if entry.is_builtin:
970 namespace = Naming.builtins_cname
971 else: # entry.is_pyglobal
972 namespace = entry.scope.namespace_cname
973 code.putln(
974 '%s = __Pyx_GetName(%s, %s); %s' % (
975 self.result_code,
976 namespace,
977 self.interned_cname,
978 code.error_goto_if_null(self.result_code, self.pos)))
979 elif entry.is_local and False:
980 # control flow not good enough yet
981 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
982 if assigned is False:
983 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
984 elif not Options.init_local_none and assigned is None:
985 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
986 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
988 def generate_assignment_code(self, rhs, code):
989 #print "NameNode.generate_assignment_code:", self.name ###
990 entry = self.entry
991 if entry is None:
992 return # There was an error earlier
994 # is_pyglobal seems to be True for module level-globals only.
995 # We use this to access class->tp_dict if necessary.
996 if entry.is_pyglobal:
997 namespace = self.entry.scope.namespace_cname
998 if entry.is_member:
999 # if the entry is a member we have to cheat: SetAttr does not work
1000 # on types, so we create a descriptor which is then added to tp_dict
1001 code.put_error_if_neg(self.pos,
1002 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1003 namespace,
1004 self.interned_cname,
1005 rhs.py_result()))
1006 # in Py2.6+, we need to invalidate the method cache
1007 code.putln("__Pyx_TypeModified(%s);" %
1008 entry.scope.parent_type.typeptr_cname)
1009 else:
1010 code.put_error_if_neg(self.pos,
1011 'PyObject_SetAttr(%s, %s, %s)' % (
1012 namespace,
1013 self.interned_cname,
1014 rhs.py_result()))
1015 if debug_disposal_code:
1016 print("NameNode.generate_assignment_code:")
1017 print("...generating disposal code for %s" % rhs)
1018 rhs.generate_disposal_code(code)
1020 else:
1021 if self.type.is_pyobject:
1022 #print "NameNode.generate_assignment_code: to", self.name ###
1023 #print "...from", rhs ###
1024 #print "...LHS type", self.type, "ctype", self.ctype() ###
1025 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1026 rhs.make_owned_reference(code)
1027 if entry.is_local and not Options.init_local_none:
1028 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1029 if initalized is True:
1030 code.put_decref(self.result_code, self.ctype())
1031 elif initalized is None:
1032 code.put_xdecref(self.result_code, self.ctype())
1033 else:
1034 code.put_decref(self.result_code, self.ctype())
1035 code.putln('%s = %s;' % (self.result_code, rhs.result_as(self.ctype())))
1036 if debug_disposal_code:
1037 print("NameNode.generate_assignment_code:")
1038 print("...generating post-assignment code for %s" % rhs)
1039 rhs.generate_post_assignment_code(code)
1041 def generate_deletion_code(self, code):
1042 if self.entry is None:
1043 return # There was an error earlier
1044 if not self.entry.is_pyglobal:
1045 error(self.pos, "Deletion of local or C global name not supported")
1046 return
1047 code.put_error_if_neg(self.pos,
1048 'PyObject_DelAttrString(%s, "%s")' % (
1049 Naming.module_cname,
1050 self.entry.name))
1052 def annotate(self, code):
1053 if hasattr(self, 'is_called') and self.is_called:
1054 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1055 if self.type.is_pyobject:
1056 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1057 else:
1058 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1060 class BackquoteNode(ExprNode):
1061 # `expr`
1063 # arg ExprNode
1065 subexprs = ['arg']
1067 def analyse_types(self, env):
1068 self.arg.analyse_types(env)
1069 self.arg = self.arg.coerce_to_pyobject(env)
1070 self.type = py_object_type
1071 self.gil_check(env)
1072 self.is_temp = 1
1074 gil_message = "Backquote expression"
1076 def generate_result_code(self, code):
1077 code.putln(
1078 "%s = PyObject_Repr(%s); %s" % (
1079 self.result_code,
1080 self.arg.py_result(),
1081 code.error_goto_if_null(self.result_code, self.pos)))
1084 class ImportNode(ExprNode):
1085 # Used as part of import statement implementation.
1086 # Implements result =
1087 # __import__(module_name, globals(), None, name_list)
1089 # module_name IdentifierStringNode dotted name of module
1090 # name_list ListNode or None list of names to be imported
1092 subexprs = ['module_name', 'name_list']
1094 def analyse_types(self, env):
1095 self.module_name.analyse_types(env)
1096 self.module_name = self.module_name.coerce_to_pyobject(env)
1097 if self.name_list:
1098 self.name_list.analyse_types(env)
1099 self.type = py_object_type
1100 self.gil_check(env)
1101 self.is_temp = 1
1102 env.use_utility_code(import_utility_code)
1104 gil_message = "Python import"
1106 def generate_result_code(self, code):
1107 if self.name_list:
1108 name_list_code = self.name_list.py_result()
1109 else:
1110 name_list_code = "0"
1111 code.putln(
1112 "%s = __Pyx_Import(%s, %s); %s" % (
1113 self.result_code,
1114 self.module_name.py_result(),
1115 name_list_code,
1116 code.error_goto_if_null(self.result_code, self.pos)))
1119 class IteratorNode(ExprNode):
1120 # Used as part of for statement implementation.
1121 # Implements result = iter(sequence)
1123 # sequence ExprNode
1125 subexprs = ['sequence']
1127 def analyse_types(self, env):
1128 self.sequence.analyse_types(env)
1129 self.sequence = self.sequence.coerce_to_pyobject(env)
1130 self.type = py_object_type
1131 self.gil_check(env)
1132 self.is_temp = 1
1134 self.counter = TempNode(self.pos, PyrexTypes.c_py_ssize_t_type, env)
1135 self.counter.allocate_temp(env)
1137 gil_message = "Iterating over Python object"
1139 def release_temp(self, env):
1140 env.release_temp(self.result_code)
1141 self.counter.release_temp(env)
1143 def generate_result_code(self, code):
1144 code.putln(
1145 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1146 self.sequence.py_result(),
1147 self.sequence.py_result()))
1148 code.putln(
1149 "%s = 0; %s = %s; Py_INCREF(%s);" % (
1150 self.counter.result_code,
1151 self.result_code,
1152 self.sequence.py_result(),
1153 self.result_code))
1154 code.putln("} else {")
1155 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1156 self.counter.result_code,
1157 self.result_code,
1158 self.sequence.py_result(),
1159 code.error_goto_if_null(self.result_code, self.pos)))
1160 code.putln("}")
1163 class NextNode(AtomicExprNode):
1164 # Used as part of for statement implementation.
1165 # Implements result = iterator.next()
1166 # Created during analyse_types phase.
1167 # The iterator is not owned by this node.
1169 # iterator ExprNode
1171 def __init__(self, iterator, env):
1172 self.pos = iterator.pos
1173 self.iterator = iterator
1174 self.type = py_object_type
1175 self.is_temp = 1
1177 def generate_result_code(self, code):
1178 for py_type in ["List", "Tuple"]:
1179 code.putln(
1180 "if (likely(Py%s_CheckExact(%s))) {" % (py_type, self.iterator.py_result()))
1181 code.putln(
1182 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1183 self.iterator.counter.result_code,
1184 py_type,
1185 self.iterator.py_result()))
1186 code.putln(
1187 "%s = Py%s_GET_ITEM(%s, %s); Py_INCREF(%s); %s++;" % (
1188 self.result_code,
1189 py_type,
1190 self.iterator.py_result(),
1191 self.iterator.counter.result_code,
1192 self.result_code,
1193 self.iterator.counter.result_code))
1194 code.put("} else ")
1195 code.putln("{")
1196 code.putln(
1197 "%s = PyIter_Next(%s);" % (
1198 self.result_code,
1199 self.iterator.py_result()))
1200 code.putln(
1201 "if (!%s) {" %
1202 self.result_code)
1203 code.putln(code.error_goto_if_PyErr(self.pos))
1204 code.putln("break;")
1205 code.putln("}")
1206 code.putln("}")
1209 class ExcValueNode(AtomicExprNode):
1210 # Node created during analyse_types phase
1211 # of an ExceptClauseNode to fetch the current
1212 # exception value.
1214 def __init__(self, pos, env, var):
1215 ExprNode.__init__(self, pos)
1216 self.type = py_object_type
1217 self.var = var
1219 def calculate_result_code(self):
1220 return self.var
1222 def generate_result_code(self, code):
1223 pass
1225 def analyse_types(self, env):
1226 pass
1229 class TempNode(AtomicExprNode):
1230 # Node created during analyse_types phase
1231 # of some nodes to hold a temporary value.
1233 def __init__(self, pos, type, env):
1234 ExprNode.__init__(self, pos)
1235 self.type = type
1236 if type.is_pyobject:
1237 self.result_ctype = py_object_type
1238 self.is_temp = 1
1240 def analyse_types(self, env):
1241 return self.type
1243 def generate_result_code(self, code):
1244 pass
1247 class PyTempNode(TempNode):
1248 # TempNode holding a Python value.
1250 def __init__(self, pos, env):
1251 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1254 #-------------------------------------------------------------------
1256 # Trailer nodes
1258 #-------------------------------------------------------------------
1260 class IndexNode(ExprNode):
1261 # Sequence indexing.
1263 # base ExprNode
1264 # index ExprNode
1265 # indices [ExprNode]
1266 # is_buffer_access boolean Whether this is a buffer access.
1268 # indices is used on buffer access, index on non-buffer access.
1269 # The former contains a clean list of index parameters, the
1270 # latter whatever Python object is needed for index access.
1272 subexprs = ['base', 'index', 'indices']
1273 indices = None
1275 def __init__(self, pos, index, *args, **kw):
1276 ExprNode.__init__(self, pos, index=index, *args, **kw)
1277 self._index = index
1279 def compile_time_value(self, denv):
1280 base = self.base.compile_time_value(denv)
1281 index = self.index.compile_time_value(denv)
1282 try:
1283 return base[index]
1284 except Exception, e:
1285 self.compile_time_value_error(e)
1287 def is_ephemeral(self):
1288 return self.base.is_ephemeral()
1290 def analyse_target_declaration(self, env):
1291 pass
1293 def analyse_types(self, env):
1294 self.analyse_base_and_index_types(env, getting = 1)
1296 def analyse_target_types(self, env):
1297 self.analyse_base_and_index_types(env, setting = 1)
1299 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1300 self.is_buffer_access = False
1302 self.base.analyse_types(env)
1304 skip_child_analysis = False
1305 buffer_access = False
1306 if self.base.type.buffer_options is not None:
1307 if isinstance(self.index, TupleNode):
1308 indices = self.index.args
1309 else:
1310 indices = [self.index]
1311 if len(indices) == self.base.type.buffer_options.ndim:
1312 buffer_access = True
1313 skip_child_analysis = True
1314 for x in indices:
1315 x.analyse_types(env)
1316 if not x.type.is_int:
1317 buffer_access = False
1318 if buffer_access:
1319 # self.indices = [
1320 # x.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1321 # for x in indices]
1322 self.indices = indices
1323 self.index = None
1324 self.type = self.base.type.buffer_options.dtype
1325 self.is_temp = 1
1326 self.is_buffer_access = True
1328 # Note: This might be cleaned up by having IndexNode
1329 # parsed in a saner way and only construct the tuple if
1330 # needed.
1332 if not buffer_access:
1333 if isinstance(self.index, TupleNode):
1334 self.index.analyse_types(env, skip_children=skip_child_analysis)
1335 elif not skip_child_analysis:
1336 self.index.analyse_types(env)
1337 if self.base.type.is_pyobject:
1338 if self.index.type.is_int:
1339 self.original_index_type = self.index.type
1340 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1341 if getting:
1342 env.use_utility_code(getitem_int_utility_code)
1343 if setting:
1344 env.use_utility_code(setitem_int_utility_code)
1345 else:
1346 self.index = self.index.coerce_to_pyobject(env)
1347 self.type = py_object_type
1348 self.gil_check(env)
1349 self.is_temp = 1
1350 else:
1351 if self.base.type.is_ptr or self.base.type.is_array:
1352 self.type = self.base.type.base_type
1353 else:
1354 error(self.pos,
1355 "Attempting to index non-array type '%s'" %
1356 self.base.type)
1357 self.type = PyrexTypes.error_type
1358 if self.index.type.is_pyobject:
1359 self.index = self.index.coerce_to(
1360 PyrexTypes.c_py_ssize_t_type, env)
1361 if not self.index.type.is_int:
1362 error(self.pos,
1363 "Invalid index type '%s'" %
1364 self.index.type)
1366 gil_message = "Indexing Python object"
1368 def check_const_addr(self):
1369 self.base.check_const_addr()
1370 self.index.check_const()
1372 def is_lvalue(self):
1373 return 1
1375 def calculate_result_code(self):
1376 if self.is_buffer_access:
1377 return "<not needed>"
1378 else:
1379 return "(%s[%s])" % (
1380 self.base.result_code, self.index.result_code)
1382 def index_unsigned_parameter(self):
1383 if self.index.type.is_int:
1384 if self.original_index_type.signed:
1385 return ", 0"
1386 else:
1387 return ", sizeof(Py_ssize_t) <= sizeof(%s)" % self.original_index_type.declaration_code("")
1388 else:
1389 return ""
1391 def generate_subexpr_evaluation_code(self, code):
1392 self.base.generate_evaluation_code(code)
1393 if self.index is not None:
1394 self.index.generate_evaluation_code(code)
1395 else:
1396 for i in self.indices: i.generate_evaluation_code(code)
1398 def generate_subexpr_disposal_code(self, code):
1399 self.base.generate_disposal_code(code)
1400 if self.index is not None:
1401 self.index.generate_disposal_code(code)
1402 else:
1403 for i in self.indices: i.generate_disposal_code(code)
1405 def generate_result_code(self, code):
1406 if self.type.is_pyobject:
1407 if self.index.type.is_int:
1408 function = "__Pyx_GetItemInt"
1409 index_code = self.index.result_code
1410 else:
1411 function = "PyObject_GetItem"
1412 index_code = self.index.py_result()
1413 sign_code = ""
1414 code.putln(
1415 "%s = %s(%s, %s%s); if (!%s) %s" % (
1416 self.result_code,
1417 function,
1418 self.base.py_result(),
1419 index_code,
1420 self.index_unsigned_parameter(),
1421 self.result_code,
1422 code.error_goto(self.pos)))
1424 def generate_setitem_code(self, value_code, code):
1425 if self.index.type.is_int:
1426 function = "__Pyx_SetItemInt"
1427 index_code = self.index.result_code
1428 else:
1429 function = "PyObject_SetItem"
1430 index_code = self.index.py_result()
1431 code.putln(
1432 "if (%s(%s, %s, %s%s) < 0) %s" % (
1433 function,
1434 self.base.py_result(),
1435 index_code,
1436 value_code,
1437 self.index_unsigned_parameter(),
1438 code.error_goto(self.pos)))
1440 def generate_assignment_code(self, rhs, code):
1441 self.generate_subexpr_evaluation_code(code)
1442 if self.type.is_pyobject:
1443 self.generate_setitem_code(rhs.py_result(), code)
1444 else:
1445 code.putln(
1446 "%s = %s;" % (
1447 self.result_code, rhs.result_code))
1448 self.generate_subexpr_disposal_code(code)
1449 rhs.generate_disposal_code(code)
1451 def generate_deletion_code(self, code):
1452 self.generate_subexpr_evaluation_code(code)
1453 #if self.type.is_pyobject:
1454 if self.index.type.is_int:
1455 function = "PySequence_DelItem"
1456 index_code = self.index.result_code
1457 else:
1458 function = "PyObject_DelItem"
1459 index_code = self.index.py_result()
1460 code.putln(
1461 "if (%s(%s, %s) < 0) %s" % (
1462 function,
1463 self.base.py_result(),
1464 index_code,
1465 code.error_goto(self.pos)))
1466 self.generate_subexpr_disposal_code(code)
1469 class SliceIndexNode(ExprNode):
1470 # 2-element slice indexing
1472 # base ExprNode
1473 # start ExprNode or None
1474 # stop ExprNode or None
1476 subexprs = ['base', 'start', 'stop']
1478 def compile_time_value(self, denv):
1479 base = self.base.compile_time_value(denv)
1480 start = self.start.compile_time_value(denv)
1481 stop = self.stop.compile_time_value(denv)
1482 try:
1483 return base[start:stop]
1484 except Exception, e:
1485 self.compile_time_value_error(e)
1487 def analyse_target_declaration(self, env):
1488 pass
1490 def analyse_types(self, env):
1491 self.base.analyse_types(env)
1492 if self.start:
1493 self.start.analyse_types(env)
1494 if self.stop:
1495 self.stop.analyse_types(env)
1496 self.base = self.base.coerce_to_pyobject(env)
1497 c_int = PyrexTypes.c_py_ssize_t_type
1498 if self.start:
1499 self.start = self.start.coerce_to(c_int, env)
1500 if self.stop:
1501 self.stop = self.stop.coerce_to(c_int, env)
1502 self.type = py_object_type
1503 self.gil_check(env)
1504 self.is_temp = 1
1506 gil_message = "Slicing Python object"
1508 def generate_result_code(self, code):
1509 code.putln(
1510 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1511 self.result_code,
1512 self.base.py_result(),
1513 self.start_code(),
1514 self.stop_code(),
1515 code.error_goto_if_null(self.result_code, self.pos)))
1517 def generate_assignment_code(self, rhs, code):
1518 self.generate_subexpr_evaluation_code(code)
1519 code.put_error_if_neg(self.pos,
1520 "PySequence_SetSlice(%s, %s, %s, %s)" % (
1521 self.base.py_result(),
1522 self.start_code(),
1523 self.stop_code(),
1524 rhs.result_code))
1525 self.generate_subexpr_disposal_code(code)
1526 rhs.generate_disposal_code(code)
1528 def generate_deletion_code(self, code):
1529 self.generate_subexpr_evaluation_code(code)
1530 code.put_error_if_neg(self.pos,
1531 "PySequence_DelSlice(%s, %s, %s)" % (
1532 self.base.py_result(),
1533 self.start_code(),
1534 self.stop_code()))
1535 self.generate_subexpr_disposal_code(code)
1537 def start_code(self):
1538 if self.start:
1539 return self.start.result_code
1540 else:
1541 return "0"
1543 def stop_code(self):
1544 if self.stop:
1545 return self.stop.result_code
1546 else:
1547 return "PY_SSIZE_T_MAX"
1549 def calculate_result_code(self):
1550 # self.result_code is not used, but this method must exist
1551 return "<unused>"
1554 class SliceNode(ExprNode):
1555 # start:stop:step in subscript list
1557 # start ExprNode
1558 # stop ExprNode
1559 # step ExprNode
1561 def compile_time_value(self, denv):
1562 start = self.start.compile_time_value(denv)
1563 stop = self.stop.compile_time_value(denv)
1564 step = step.step.compile_time_value(denv)
1565 try:
1566 return slice(start, stop, step)
1567 except Exception, e:
1568 self.compile_time_value_error(e)
1570 subexprs = ['start', 'stop', 'step']
1572 def analyse_types(self, env):
1573 self.start.analyse_types(env)
1574 self.stop.analyse_types(env)
1575 self.step.analyse_types(env)
1576 self.start = self.start.coerce_to_pyobject(env)
1577 self.stop = self.stop.coerce_to_pyobject(env)
1578 self.step = self.step.coerce_to_pyobject(env)
1579 self.type = py_object_type
1580 self.gil_check(env)
1581 self.is_temp = 1
1583 gil_message = "Constructing Python slice object"
1585 def generate_result_code(self, code):
1586 code.putln(
1587 "%s = PySlice_New(%s, %s, %s); %s" % (
1588 self.result_code,
1589 self.start.py_result(),
1590 self.stop.py_result(),
1591 self.step.py_result(),
1592 code.error_goto_if_null(self.result_code, self.pos)))
1595 class CallNode(ExprNode):
1596 def gil_check(self, env):
1597 # Make sure we're not in a nogil environment
1598 if env.nogil:
1599 error(self.pos, "Calling gil-requiring function without gil")
1602 class SimpleCallNode(CallNode):
1603 # Function call without keyword, * or ** args.
1605 # function ExprNode
1606 # args [ExprNode]
1607 # arg_tuple ExprNode or None used internally
1608 # self ExprNode or None used internally
1609 # coerced_self ExprNode or None used internally
1610 # wrapper_call bool used internally
1612 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
1614 self = None
1615 coerced_self = None
1616 arg_tuple = None
1617 wrapper_call = False
1619 def compile_time_value(self, denv):
1620 function = self.function.compile_time_value(denv)
1621 args = [arg.compile_time_value(denv) for arg in self.args]
1622 try:
1623 return function(*args)
1624 except Exception, e:
1625 self.compile_time_value_error(e)
1627 def analyse_types(self, env):
1628 function = self.function
1629 function.is_called = 1
1630 self.function.analyse_types(env)
1631 if function.is_attribute and function.is_py_attr and \
1632 function.attribute == "append" and len(self.args) == 1:
1633 # L.append(x) is almost always applied to a list
1634 self.py_func = self.function
1635 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
1636 self.function.analyse_types(env)
1637 self.self = self.py_func.obj
1638 function.obj = CloneNode(self.self)
1639 env.use_utility_code(append_utility_code)
1640 if function.is_attribute and function.entry and function.entry.is_cmethod:
1641 # Take ownership of the object from which the attribute
1642 # was obtained, because we need to pass it as 'self'.
1643 self.self = function.obj
1644 function.obj = CloneNode(self.self)
1645 func_type = self.function_type()
1646 if func_type.is_pyobject:
1647 self.arg_tuple = TupleNode(self.pos, args = self.args)
1648 self.arg_tuple.analyse_types(env)
1649 self.args = None
1650 self.type = py_object_type
1651 self.gil_check(env)
1652 self.is_temp = 1
1653 else:
1654 for arg in self.args:
1655 arg.analyse_types(env)
1656 if self.self and func_type.args:
1657 # Coerce 'self' to the type expected by the method.
1658 expected_type = func_type.args[0].type
1659 self.coerced_self = CloneNode(self.self).coerce_to(
1660 expected_type, env)
1661 # Insert coerced 'self' argument into argument list.
1662 self.args.insert(0, self.coerced_self)
1663 self.analyse_c_function_call(env)
1665 def function_type(self):
1666 # Return the type of the function being called, coercing a function
1667 # pointer to a function if necessary.
1668 func_type = self.function.type
1669 if func_type.is_ptr:
1670 func_type = func_type.base_type
1671 return func_type
1673 def analyse_c_function_call(self, env):
1674 func_type = self.function_type()
1675 # Check function type
1676 if not func_type.is_cfunction:
1677 if not func_type.is_error:
1678 error(self.pos, "Calling non-function type '%s'" %
1679 func_type)
1680 self.type = PyrexTypes.error_type
1681 self.result_code = "<error>"
1682 return
1683 # Check no. of args
1684 max_nargs = len(func_type.args)
1685 expected_nargs = max_nargs - func_type.optional_arg_count
1686 actual_nargs = len(self.args)
1687 if actual_nargs < expected_nargs \
1688 or (not func_type.has_varargs and actual_nargs > max_nargs):
1689 expected_str = str(expected_nargs)
1690 if func_type.has_varargs:
1691 expected_str = "at least " + expected_str
1692 elif func_type.optional_arg_count:
1693 if actual_nargs < max_nargs:
1694 expected_str = "at least " + expected_str
1695 else:
1696 expected_str = "at most " + str(max_nargs)
1697 error(self.pos,
1698 "Call with wrong number of arguments (expected %s, got %s)"
1699 % (expected_str, actual_nargs))
1700 self.args = None
1701 self.type = PyrexTypes.error_type
1702 self.result_code = "<error>"
1703 return
1704 # Coerce arguments
1705 for i in range(min(max_nargs, actual_nargs)):
1706 formal_type = func_type.args[i].type
1707 self.args[i] = self.args[i].coerce_to(formal_type, env)
1708 for i in range(max_nargs, actual_nargs):
1709 if self.args[i].type.is_pyobject:
1710 error(self.args[i].pos,
1711 "Python object cannot be passed as a varargs parameter")
1712 # Calc result type and code fragment
1713 self.type = func_type.return_type
1714 if self.type.is_pyobject \
1715 or func_type.exception_value is not None \
1716 or func_type.exception_check:
1717 self.is_temp = 1
1718 if self.type.is_pyobject:
1719 self.result_ctype = py_object_type
1720 # C++ exception handler
1721 if func_type.exception_check == '+':
1722 if func_type.exception_value is None:
1723 env.use_utility_code(cpp_exception_utility_code)
1724 # Check gil
1725 if not func_type.nogil:
1726 self.gil_check(env)
1728 def calculate_result_code(self):
1729 return self.c_call_code()
1731 def c_call_code(self):
1732 func_type = self.function_type()
1733 if self.args is None or not func_type.is_cfunction:
1734 return "<error>"
1735 formal_args = func_type.args
1736 arg_list_code = []
1737 args = zip(formal_args, self.args)
1738 max_nargs = len(func_type.args)
1739 expected_nargs = max_nargs - func_type.optional_arg_count
1740 actual_nargs = len(self.args)
1741 for formal_arg, actual_arg in args[:expected_nargs]:
1742 arg_code = actual_arg.result_as(formal_arg.type)
1743 arg_list_code.append(arg_code)
1745 if func_type.optional_arg_count:
1746 if expected_nargs == actual_nargs:
1747 optional_args = 'NULL'
1748 else:
1749 optional_arg_code = [str(actual_nargs - expected_nargs)]
1750 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
1751 arg_code = actual_arg.result_as(formal_arg.type)
1752 optional_arg_code.append(arg_code)
1753 # for formal_arg in formal_args[actual_nargs:max_nargs]:
1754 # optional_arg_code.append(formal_arg.type.cast_code('0'))
1755 optional_arg_struct = '{%s}' % ','.join(optional_arg_code)
1756 optional_args = PyrexTypes.c_void_ptr_type.cast_code(
1757 '&' + func_type.op_arg_struct.base_type.cast_code(optional_arg_struct))
1758 arg_list_code.append(optional_args)
1760 for actual_arg in self.args[len(formal_args):]:
1761 arg_list_code.append(actual_arg.result_code)
1762 result = "%s(%s)" % (self.function.result_code,
1763 join(arg_list_code, ", "))
1764 if self.wrapper_call or \
1765 self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
1766 result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
1767 return result
1769 def generate_result_code(self, code):
1770 func_type = self.function_type()
1771 if func_type.is_pyobject:
1772 arg_code = self.arg_tuple.py_result()
1773 code.putln(
1774 "%s = PyObject_Call(%s, %s, NULL); %s" % (
1775 self.result_code,
1776 self.function.py_result(),
1777 arg_code,
1778 code.error_goto_if_null(self.result_code, self.pos)))
1779 elif func_type.is_cfunction:
1780 exc_checks = []
1781 if self.type.is_pyobject:
1782 exc_checks.append("!%s" % self.result_code)
1783 else:
1784 exc_val = func_type.exception_value
1785 exc_check = func_type.exception_check
1786 if exc_val is not None:
1787 exc_checks.append("%s == %s" % (self.result_code, exc_val))
1788 if exc_check:
1789 exc_checks.append("PyErr_Occurred()")
1790 if self.is_temp or exc_checks:
1791 rhs = self.c_call_code()
1792 if self.result_code:
1793 lhs = "%s = " % self.result_code
1794 if self.is_temp and self.type.is_pyobject:
1795 #return_type = self.type # func_type.return_type
1796 #print "SimpleCallNode.generate_result_code: casting", rhs, \
1797 # "from", return_type, "to pyobject" ###
1798 rhs = typecast(py_object_type, self.type, rhs)
1799 else:
1800 lhs = ""
1801 if func_type.exception_check == '+':
1802 if func_type.exception_value is None:
1803 raise_py_exception = "__Pyx_CppExn2PyErr()"
1804 elif func_type.exception_value.type.is_pyobject:
1805 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
1806 else:
1807 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
1808 code.putln(
1809 "try {%s%s;} catch(...) {%s; %s}" % (
1810 lhs,
1811 rhs,
1812 raise_py_exception,
1813 code.error_goto(self.pos)))
1814 return
1815 code.putln(
1816 "%s%s; %s" % (
1817 lhs,
1818 rhs,
1819 code.error_goto_if(" && ".join(exc_checks), self.pos)))
1821 class GeneralCallNode(CallNode):
1822 # General Python function call, including keyword,
1823 # * and ** arguments.
1825 # function ExprNode
1826 # positional_args ExprNode Tuple of positional arguments
1827 # keyword_args ExprNode or None Dict of keyword arguments
1828 # starstar_arg ExprNode or None Dict of extra keyword args
1830 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
1832 def compile_time_value(self, denv):
1833 function = self.function.compile_time_value(denv)
1834 positional_args = self.positional_args.compile_time_value(denv)
1835 keyword_args = self.keyword_args.compile_time_value(denv)
1836 starstar_arg = self.starstar_arg.compile_time_value(denv)
1837 try:
1838 keyword_args.update(starstar_arg)
1839 return function(*positional_args, **keyword_args)
1840 except Exception, e:
1841 self.compile_time_value_error(e)
1843 def analyse_types(self, env):
1844 self.function.analyse_types(env)
1845 self.positional_args.analyse_types(env)
1846 if self.keyword_args:
1847 self.keyword_args.analyse_types(env)
1848 if self.starstar_arg:
1849 self.starstar_arg.analyse_types(env)
1850 self.function = self.function.coerce_to_pyobject(env)
1851 self.positional_args = \
1852 self.positional_args.coerce_to_pyobject(env)
1853 if self.starstar_arg:
1854 self.starstar_arg = \
1855 self.starstar_arg.coerce_to_pyobject(env)
1856 self.type = py_object_type
1857 self.gil_check(env)
1858 self.is_temp = 1
1860 def generate_result_code(self, code):
1861 if self.keyword_args and self.starstar_arg:
1862 code.put_error_if_neg(self.pos,
1863 "PyDict_Update(%s, %s)" % (
1864 self.keyword_args.py_result(),
1865 self.starstar_arg.py_result()))
1866 keyword_code = self.keyword_args.py_result()
1867 elif self.keyword_args:
1868 keyword_code = self.keyword_args.py_result()
1869 elif self.starstar_arg:
1870 keyword_code = self.starstar_arg.py_result()
1871 else:
1872 keyword_code = None
1873 if not keyword_code:
1874 call_code = "PyObject_Call(%s, %s, NULL)" % (
1875 self.function.py_result(),
1876 self.positional_args.py_result())
1877 else:
1878 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
1879 self.function.py_result(),
1880 self.positional_args.py_result(),
1881 keyword_code)
1882 code.putln(
1883 "%s = %s; %s" % (
1884 self.result_code,
1885 call_code,
1886 code.error_goto_if_null(self.result_code, self.pos)))
1889 class AsTupleNode(ExprNode):
1890 # Convert argument to tuple. Used for normalising
1891 # the * argument of a function call.
1893 # arg ExprNode
1895 subexprs = ['arg']
1897 def compile_time_value(self, denv):
1898 arg = self.arg.compile_time_value(denv)
1899 try:
1900 return tuple(arg)
1901 except Exception, e:
1902 self.compile_time_value_error(e)
1904 def analyse_types(self, env):
1905 self.arg.analyse_types(env)
1906 self.arg = self.arg.coerce_to_pyobject(env)
1907 self.type = py_object_type
1908 self.gil_check(env)
1909 self.is_temp = 1
1911 gil_message = "Constructing Python tuple"
1913 def generate_result_code(self, code):
1914 code.putln(
1915 "%s = PySequence_Tuple(%s); %s" % (
1916 self.result_code,
1917 self.arg.py_result(),
1918 code.error_goto_if_null(self.result_code, self.pos)))
1921 class AttributeNode(ExprNode):
1922 # obj.attribute
1924 # obj ExprNode
1925 # attribute string
1927 # Used internally:
1929 # is_py_attr boolean Is a Python getattr operation
1930 # member string C name of struct member
1931 # is_called boolean Function call is being done on result
1932 # entry Entry Symbol table entry of attribute
1933 # interned_attr_cname string C name of interned attribute name
1935 is_attribute = 1
1936 subexprs = ['obj']
1938 type = PyrexTypes.error_type
1939 result = "<error>"
1940 entry = None
1941 is_called = 0
1943 def coerce_to(self, dst_type, env):
1944 # If coercing to a generic pyobject and this is a cpdef function
1945 # we can create the corresponding attribute
1946 if dst_type is py_object_type:
1947 entry = self.entry
1948 if entry and entry.is_cfunction and entry.as_variable:
1949 # must be a cpdef function
1950 self.is_temp = 1
1951 self.entry = entry.as_variable
1952 self.analyse_as_python_attribute(env)
1953 return self
1954 return ExprNode.coerce_to(self, dst_type, env)
1956 def compile_time_value(self, denv):
1957 attr = self.attribute
1958 if attr.beginswith("__") and attr.endswith("__"):
1959 self.error("Invalid attribute name '%s' in compile-time expression"
1960 % attr)
1961 return None
1962 obj = self.arg.compile_time_value(denv)
1963 try:
1964 return getattr(obj, attr)
1965 except Exception, e:
1966 self.compile_time_value_error(e)
1968 def analyse_target_declaration(self, env):
1969 pass
1971 def analyse_target_types(self, env):
1972 self.analyse_types(env, target = 1)
1974 def analyse_types(self, env, target = 0):
1975 if self.analyse_as_cimported_attribute(env, target):
1976 return
1977 if not target and self.analyse_as_unbound_cmethod(env):
1978 return
1979 self.analyse_as_ordinary_attribute(env, target)
1981 def analyse_as_cimported_attribute(self, env, target):
1982 # Try to interpret this as a reference to an imported
1983 # C const, type, var or function. If successful, mutates
1984 # this node into a NameNode and returns 1, otherwise
1985 # returns 0.
1986 module_scope = self.obj.analyse_as_module(env)
1987 if module_scope:
1988 entry = module_scope.lookup_here(self.attribute)
1989 if entry and (
1990 entry.is_cglobal or entry.is_cfunction
1991 or entry.is_type or entry.is_const):
1992 self.mutate_into_name_node(env, entry, target)
1993 return 1
1994 return 0
1996 def analyse_as_unbound_cmethod(self, env):
1997 # Try to interpret this as a reference to an unbound
1998 # C method of an extension type. If successful, mutates
1999 # this node into a NameNode and returns 1, otherwise
2000 # returns 0.
2001 type = self.obj.analyse_as_extension_type(env)
2002 if type:
2003 entry = type.scope.lookup_here(self.attribute)
2004 if entry and entry.is_cmethod:
2005 # Create a temporary entry describing the C method
2006 # as an ordinary function.
2007 ubcm_entry = Symtab.Entry(entry.name,
2008 "%s->%s" % (type.vtabptr_cname, entry.cname),
2009 entry.type)
2010 ubcm_entry.is_cfunction = 1
2011 ubcm_entry.func_cname = entry.func_cname
2012 ubcm_entry.is_unbound_cmethod = 1
2013 self.mutate_into_name_node(env, ubcm_entry, None)
2014 return 1
2015 return 0
2017 def analyse_as_extension_type(self, env):
2018 # Try to interpret this as a reference to an extension type
2019 # in a cimported module. Returns the extension type, or None.
2020 module_scope = self.obj.analyse_as_module(env)
2021 if module_scope:
2022 entry = module_scope.lookup_here(self.attribute)
2023 if entry and entry.is_type and entry.type.is_extension_type:
2024 return entry.type
2025 return None
2027 def analyse_as_module(self, env):
2028 # Try to interpret this as a reference to a cimported module
2029 # in another cimported module. Returns the module scope, or None.
2030 module_scope = self.obj.analyse_as_module(env)
2031 if module_scope:
2032 entry = module_scope.lookup_here(self.attribute)
2033 if entry and entry.as_module:
2034 return entry.as_module
2035 return None
2037 def mutate_into_name_node(self, env, entry, target):
2038 # Mutate this node into a NameNode and complete the
2039 # analyse_types phase.
2040 self.__class__ = NameNode
2041 self.name = self.attribute
2042 self.entry = entry
2043 del self.obj
2044 del self.attribute
2045 if target:
2046 NameNode.analyse_target_types(self, env)
2047 else:
2048 NameNode.analyse_rvalue_entry(self, env)
2050 def analyse_as_ordinary_attribute(self, env, target):
2051 self.obj.analyse_types(env)
2052 self.analyse_attribute(env)
2053 if self.entry and self.entry.is_cmethod and not self.is_called:
2054 # error(self.pos, "C method can only be called")
2055 pass
2056 ## Reference to C array turns into pointer to first element.
2057 #while self.type.is_array:
2058 # self.type = self.type.element_ptr_type()
2059 if self.is_py_attr:
2060 if not target:
2061 self.is_temp = 1
2062 self.result_ctype = py_object_type
2064 def analyse_attribute(self, env):
2065 # Look up attribute and set self.type and self.member.
2066 self.is_py_attr = 0
2067 self.member = self.attribute
2068 if self.obj.type.is_string:
2069 self.obj = self.obj.coerce_to_pyobject(env)
2070 obj_type = self.obj.type
2071 if obj_type.is_ptr or obj_type.is_array:
2072 obj_type = obj_type.base_type
2073 self.op = "->"
2074 elif obj_type.is_extension_type:
2075 self.op = "->"
2076 else:
2077 self.op = "."
2078 if obj_type.has_attributes:
2079 entry = None
2080 if obj_type.attributes_known():
2081 entry = obj_type.scope.lookup_here(self.attribute)
2082 if entry and entry.is_member:
2083 entry = None
2084 else:
2085 error(self.pos,
2086 "Cannot select attribute of incomplete type '%s'"
2087 % obj_type)
2088 self.type = PyrexTypes.error_type
2089 return
2090 self.entry = entry
2091 if entry:
2092 if obj_type.is_extension_type and entry.name == "__weakref__":
2093 error(self.pos, "Illegal use of special attribute __weakref__")
2094 # methods need the normal attribute lookup
2095 # because they do not have struct entries
2096 if entry.is_variable or entry.is_cmethod:
2097 self.type = entry.type
2098 self.member = entry.cname
2099 return
2100 else:
2101 # If it's not a variable or C method, it must be a Python
2102 # method of an extension type, so we treat it like a Python
2103 # attribute.
2104 pass
2105 # If we get here, the base object is not a struct/union/extension
2106 # type, or it is an extension type and the attribute is either not
2107 # declared or is declared as a Python method. Treat it as a Python
2108 # attribute reference.
2109 self.analyse_as_python_attribute(env)
2111 def analyse_as_python_attribute(self, env):
2112 obj_type = self.obj.type
2113 self.member = self.attribute
2114 if obj_type.is_pyobject:
2115 self.type = py_object_type
2116 self.is_py_attr = 1
2117 self.interned_attr_cname = env.intern_identifier(self.attribute)
2118 self.gil_check(env)
2119 else:
2120 if not obj_type.is_error:
2121 error(self.pos,
2122 "Object of type '%s' has no attribute '%s'" %
2123 (obj_type, self.attribute))
2125 gil_message = "Accessing Python attribute"
2127 def is_simple(self):
2128 if self.obj:
2129 return self.result_in_temp() or self.obj.is_simple()
2130 else:
2131 return NameNode.is_simple(self)
2133 def is_lvalue(self):
2134 if self.obj:
2135 return 1
2136 else:
2137 return NameNode.is_lvalue(self)
2139 def is_ephemeral(self):
2140 if self.obj:
2141 return self.obj.is_ephemeral()
2142 else:
2143 return NameNode.is_ephemeral(self)
2145 def calculate_result_code(self):
2146 #print "AttributeNode.calculate_result_code:", self.member ###
2147 #print "...obj node =", self.obj, "code", self.obj.result_code ###
2148 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2149 obj = self.obj
2150 obj_code = obj.result_as(obj.type)
2151 #print "...obj_code =", obj_code ###
2152 if self.entry and self.entry.is_cmethod:
2153 if obj.type.is_extension_type:
2154 return "((struct %s *)%s%s%s)->%s" % (
2155 obj.type.vtabstruct_cname, obj_code, self.op,
2156 obj.type.vtabslot_cname, self.member)
2157 else:
2158 return self.member
2159 else:
2160 return "%s%s%s" % (obj_code, self.op, self.member)
2162 def generate_result_code(self, code):
2163 if self.is_py_attr:
2164 code.putln(
2165 '%s = PyObject_GetAttr(%s, %s); %s' % (
2166 self.result_code,
2167 self.obj.py_result(),
2168 self.interned_attr_cname,
2169 code.error_goto_if_null(self.result_code, self.pos)))
2171 def generate_assignment_code(self, rhs, code):
2172 self.obj.generate_evaluation_code(code)
2173 if self.is_py_attr:
2174 code.put_error_if_neg(self.pos,
2175 'PyObject_SetAttr(%s, %s, %s)' % (
2176 self.obj.py_result(),
2177 self.interned_attr_cname,
2178 rhs.py_result()))
2179 rhs.generate_disposal_code(code)
2180 else:
2181 select_code = self.result_code
2182 if self.type.is_pyobject:
2183 rhs.make_owned_reference(code)
2184 code.put_decref(select_code, self.ctype())
2185 code.putln(
2186 "%s = %s;" % (
2187 select_code,
2188 rhs.result_as(self.ctype())))
2189 #rhs.result_code))
2190 rhs.generate_post_assignment_code(code)
2191 self.obj.generate_disposal_code(code)
2193 def generate_deletion_code(self, code):
2194 self.obj.generate_evaluation_code(code)
2195 if self.is_py_attr:
2196 code.put_error_if_neg(self.pos,
2197 'PyObject_DelAttr(%s, %s)' % (
2198 self.obj.py_result(),
2199 self.interned_attr_cname))
2200 else:
2201 error(self.pos, "Cannot delete C attribute of extension type")
2202 self.obj.generate_disposal_code(code)
2204 def annotate(self, code):
2205 if self.is_py_attr:
2206 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2207 else:
2208 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2210 #-------------------------------------------------------------------
2212 # Constructor nodes
2214 #-------------------------------------------------------------------
2216 class SequenceNode(ExprNode):
2217 # Base class for list and tuple constructor nodes.
2218 # Contains common code for performing sequence unpacking.
2220 # args [ExprNode]
2221 # iterator ExprNode
2222 # unpacked_items [ExprNode] or None
2223 # coerced_unpacked_items [ExprNode] or None
2225 subexprs = ['args']
2227 is_sequence_constructor = 1
2228 unpacked_items = None
2230 def compile_time_value_list(self, denv):
2231 return [arg.compile_time_value(denv) for arg in self.args]
2233 def analyse_target_declaration(self, env):
2234 for arg in self.args:
2235 arg.analyse_target_declaration(env)
2237 def analyse_types(self, env, skip_children=False):
2238 for i in range(len(self.args)):
2239 arg = self.args[i]
2240 if not skip_children: arg.analyse_types(env)
2241 self.args[i] = arg.coerce_to_pyobject(env)
2242 self.type = py_object_type
2243 self.gil_check(env)
2244 self.is_temp = 1
2246 def analyse_target_types(self, env):
2247 self.iterator = PyTempNode(self.pos, env)
2248 self.unpacked_items = []
2249 self.coerced_unpacked_items = []
2250 for arg in self.args:
2251 arg.analyse_target_types(env)
2252 unpacked_item = PyTempNode(self.pos, env)
2253 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2254 self.unpacked_items.append(unpacked_item)
2255 self.coerced_unpacked_items.append(coerced_unpacked_item)
2256 self.type = py_object_type
2257 env.use_utility_code(unpacking_utility_code)
2259 def allocate_target_temps(self, env, rhs):
2260 self.iterator.allocate_temps(env)
2261 for arg, node in zip(self.args, self.coerced_unpacked_items):
2262 node.allocate_temps(env)
2263 arg.allocate_target_temps(env, node)
2264 #arg.release_target_temp(env)
2265 #node.release_temp(env)
2266 if rhs:
2267 rhs.release_temp(env)
2268 self.iterator.release_temp(env)
2270 # def release_target_temp(self, env):
2271 # #for arg in self.args:
2272 # # arg.release_target_temp(env)
2273 # #for node in self.coerced_unpacked_items:
2274 # # node.release_temp(env)
2275 # self.iterator.release_temp(env)
2277 def generate_result_code(self, code):
2278 self.generate_operation_code(code)
2280 def generate_assignment_code(self, rhs, code):
2281 code.putln(
2282 "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
2283 rhs.py_result(),
2284 rhs.py_result(),
2285 len(self.args)))
2286 code.putln("PyObject* tuple = %s;" % rhs.py_result())
2287 for i in range(len(self.args)):
2288 item = self.unpacked_items[i]
2289 code.putln(
2290 "%s = PyTuple_GET_ITEM(tuple, %s);" % (
2291 item.result_code,
2292 i))
2293 code.put_incref(item.result_code, item.ctype())
2294 value_node = self.coerced_unpacked_items[i]
2295 value_node.generate_evaluation_code(code)
2296 self.args[i].generate_assignment_code(value_node, code)
2298 rhs.generate_disposal_code(code)
2299 code.putln("}")
2300 code.putln("else {")
2302 code.putln(
2303 "%s = PyObject_GetIter(%s); %s" % (
2304 self.iterator.result_code,
2305 rhs.py_result(),
2306 code.error_goto_if_null(self.iterator.result_code, self.pos)))
2307 rhs.generate_disposal_code(code)
2308 for i in range(len(self.args)):
2309 item = self.unpacked_items[i]
2310 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
2311 self.iterator.py_result(), i)
2312 code.putln(
2313 "%s = %s; %s" % (
2314 item.result_code,
2315 typecast(item.ctype(), py_object_type, unpack_code),
2316 code.error_goto_if_null(item.result_code, self.pos)))
2317 value_node = self.coerced_unpacked_items[i]
2318 value_node.generate_evaluation_code(code)
2319 self.args[i].generate_assignment_code(value_node, code)
2320 code.put_error_if_neg(self.pos,
2321 "__Pyx_EndUnpack(%s)" % (
2322 self.iterator.py_result()))
2323 if debug_disposal_code:
2324 print("UnpackNode.generate_assignment_code:")
2325 print("...generating disposal code for %s" % self.iterator)
2326 self.iterator.generate_disposal_code(code)
2328 code.putln("}")
2330 def annotate(self, code):
2331 for arg in self.args:
2332 arg.annotate(code)
2333 if self.unpacked_items:
2334 for arg in self.unpacked_items:
2335 arg.annotate(code)
2336 for arg in self.coerced_unpacked_items:
2337 arg.annotate(code)
2340 class TupleNode(SequenceNode):
2341 # Tuple constructor.
2343 gil_message = "Constructing Python tuple"
2345 def analyse_types(self, env, skip_children=False):
2346 if len(self.args) == 0:
2347 self.is_temp = 0
2348 self.is_literal = 1
2349 else:
2350 SequenceNode.analyse_types(self, env, skip_children)
2351 self.type = tuple_type
2353 def calculate_result_code(self):
2354 if len(self.args) > 0:
2355 error(self.pos, "Positive length tuples must be constructed.")
2356 else:
2357 return Naming.empty_tuple
2359 def compile_time_value(self, denv):
2360 values = self.compile_time_value_list(denv)
2361 try:
2362 return tuple(values)
2363 except Exception, e:
2364 self.compile_time_value_error(e)
2366 def generate_operation_code(self, code):
2367 if len(self.args) == 0:
2368 # result_code is Naming.empty_tuple
2369 return
2370 code.putln(
2371 "%s = PyTuple_New(%s); %s" % (
2372 self.result_code,
2373 len(self.args),
2374 code.error_goto_if_null(self.result_code, self.pos)))
2375 for i in range(len(self.args)):
2376 arg = self.args[i]
2377 if not arg.result_in_temp():
2378 code.put_incref(arg.result_code, arg.ctype())
2379 code.putln(
2380 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2381 self.result_code,
2382 i,
2383 arg.py_result()))
2385 def generate_subexpr_disposal_code(self, code):
2386 # We call generate_post_assignment_code here instead
2387 # of generate_disposal_code, because values were stored
2388 # in the tuple using a reference-stealing operation.
2389 for arg in self.args:
2390 arg.generate_post_assignment_code(code)
2393 class ListNode(SequenceNode):
2394 # List constructor.
2396 gil_message = "Constructing Python list"
2398 def analyse_types(self, env):
2399 SequenceNode.analyse_types(self, env)
2400 self.type = list_type
2402 def compile_time_value(self, denv):
2403 return self.compile_time_value_list(denv)
2405 def generate_operation_code(self, code):
2406 code.putln("%s = PyList_New(%s); %s" %
2407 (self.result_code,
2408 len(self.args),
2409 code.error_goto_if_null(self.result_code, self.pos)))
2410 for i in range(len(self.args)):
2411 arg = self.args[i]
2412 #if not arg.is_temp:
2413 if not arg.result_in_temp():
2414 code.put_incref(arg.result_code, arg.ctype())
2415 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
2416 (self.result_code,
2417 i,
2418 arg.py_result()))
2420 def generate_subexpr_disposal_code(self, code):
2421 # We call generate_post_assignment_code here instead
2422 # of generate_disposal_code, because values were stored
2423 # in the list using a reference-stealing operation.
2424 for arg in self.args:
2425 arg.generate_post_assignment_code(code)
2428 class ListComprehensionNode(SequenceNode):
2430 subexprs = []
2431 is_sequence_constructor = 0 # not unpackable
2433 def analyse_types(self, env):
2434 self.type = list_type
2435 self.is_temp = 1
2436 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
2438 def allocate_temps(self, env, result = None):
2439 if debug_temp_alloc:
2440 print("%s Allocating temps" % self)
2441 self.allocate_temp(env, result)
2442 self.loop.analyse_declarations(env)
2443 self.loop.analyse_expressions(env)
2445 def generate_operation_code(self, code):
2446 code.putln("%s = PyList_New(%s); %s" %
2447 (self.result_code,
2448 0,
2449 code.error_goto_if_null(self.result_code, self.pos)))
2450 self.loop.generate_execution_code(code)
2452 def annotate(self, code):
2453 self.loop.annotate(code)
2456 class ListComprehensionAppendNode(ExprNode):
2458 subexprs = ['expr']
2460 def analyse_types(self, env):
2461 self.expr.analyse_types(env)
2462 if self.expr.type != py_object_type:
2463 self.expr = self.expr.coerce_to_pyobject(env)
2464 self.type = PyrexTypes.c_int_type
2465 self.is_temp = 1
2467 def generate_result_code(self, code):
2468 code.putln("%s = PyList_Append(%s, %s); %s" %
2469 (self.result_code,
2470 self.target.result_code,
2471 self.expr.result_code,
2472 code.error_goto_if(self.result_code, self.pos)))
2475 class DictNode(ExprNode):
2476 # Dictionary constructor.
2478 # key_value_pairs [DictItemNode]
2480 subexprs = ['key_value_pairs']
2482 def compile_time_value(self, denv):
2483 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
2484 for item in self.key_value_pairs]
2485 try:
2486 return dict(pairs)
2487 except Exception, e:
2488 self.compile_time_value_error(e)
2490 def analyse_types(self, env):
2491 for item in self.key_value_pairs:
2492 item.analyse_types(env)
2493 self.type = dict_type
2494 self.gil_check(env)
2495 self.is_temp = 1
2497 gil_message = "Constructing Python dict"
2499 def allocate_temps(self, env, result = None):
2500 # Custom method used here because key-value
2501 # pairs are evaluated and used one at a time.
2502 self.allocate_temp(env, result)
2503 for item in self.key_value_pairs:
2504 item.key.allocate_temps(env)
2505 item.value.allocate_temps(env)
2506 item.key.release_temp(env)
2507 item.value.release_temp(env)
2509 def generate_evaluation_code(self, code):
2510 # Custom method used here because key-value
2511 # pairs are evaluated and used one at a time.
2512 code.putln(
2513 "%s = PyDict_New(); %s" % (
2514 self.result_code,
2515 code.error_goto_if_null(self.result_code, self.pos)))
2516 for item in self.key_value_pairs:
2517 item.generate_evaluation_code(code)
2518 code.put_error_if_neg(self.pos,
2519 "PyDict_SetItem(%s, %s, %s)" % (
2520 self.result_code,
2521 item.key.py_result(),
2522 item.value.py_result()))
2523 item.generate_disposal_code(code)
2525 def annotate(self, code):
2526 for item in self.key_value_pairs:
2527 item.annotate(code)
2529 class DictItemNode(ExprNode):
2530 # Represents a single item in a DictNode
2532 # key ExprNode
2533 # value ExprNode
2534 subexprs = ['key', 'value']
2536 def analyse_types(self, env):
2537 self.key.analyse_types(env)
2538 self.value.analyse_types(env)
2539 self.key = self.key.coerce_to_pyobject(env)
2540 self.value = self.value.coerce_to_pyobject(env)
2542 def generate_evaluation_code(self, code):
2543 self.key.generate_evaluation_code(code)
2544 self.value.generate_evaluation_code(code)
2546 def generate_disposal_code(self, code):
2547 self.key.generate_disposal_code(code)
2548 self.value.generate_disposal_code(code)
2551 class ClassNode(ExprNode):
2552 # Helper class used in the implementation of Python
2553 # class definitions. Constructs a class object given
2554 # a name, tuple of bases and class dictionary.
2556 # name EncodedString Name of the class
2557 # cname string Class name as a Python string
2558 # bases ExprNode Base class tuple
2559 # dict ExprNode Class dict (not owned by this node)
2560 # doc ExprNode or None Doc string
2561 # module_name string Name of defining module
2563 subexprs = ['bases', 'doc']
2565 def analyse_types(self, env):
2566 self.cname = env.intern_identifier(self.name)
2567 self.bases.analyse_types(env)
2568 if self.doc:
2569 self.doc.analyse_types(env)
2570 self.doc = self.doc.coerce_to_pyobject(env)
2571 self.module_name = env.global_scope().qualified_name
2572 self.type = py_object_type
2573 self.gil_check(env)
2574 self.is_temp = 1
2575 env.use_utility_code(create_class_utility_code);
2577 gil_message = "Constructing Python class"
2579 def generate_result_code(self, code):
2580 if self.doc:
2581 code.put_error_if_neg(self.pos,
2582 'PyDict_SetItemString(%s, "__doc__", %s)' % (
2583 self.dict.py_result(),
2584 self.doc.py_result()))
2585 code.putln(
2586 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
2587 self.result_code,
2588 self.bases.py_result(),
2589 self.dict.py_result(),
2590 self.cname,
2591 self.module_name,
2592 code.error_goto_if_null(self.result_code, self.pos)))
2595 class UnboundMethodNode(ExprNode):
2596 # Helper class used in the implementation of Python
2597 # class definitions. Constructs an unbound method
2598 # object from a class and a function.
2600 # class_cname string C var holding the class object
2601 # function ExprNode Function object
2603 subexprs = ['function']
2605 def analyse_types(self, env):
2606 self.function.analyse_types(env)
2607 self.type = py_object_type
2608 self.gil_check(env)
2609 self.is_temp = 1
2611 gil_message = "Constructing an unbound method"
2613 def generate_result_code(self, code):
2614 code.putln(
2615 "%s = PyMethod_New(%s, 0, %s); %s" % (
2616 self.result_code,
2617 self.function.py_result(),
2618 self.class_cname,
2619 code.error_goto_if_null(self.result_code, self.pos)))
2622 class PyCFunctionNode(AtomicExprNode):
2623 # Helper class used in the implementation of Python
2624 # class definitions. Constructs a PyCFunction object
2625 # from a PyMethodDef struct.
2627 # pymethdef_cname string PyMethodDef structure
2629 def analyse_types(self, env):
2630 self.type = py_object_type
2631 self.gil_check(env)
2632 self.is_temp = 1
2634 gil_message = "Constructing Python function"
2636 def generate_result_code(self, code):
2637 code.putln(
2638 "%s = PyCFunction_New(&%s, 0); %s" % (
2639 self.result_code,
2640 self.pymethdef_cname,
2641 code.error_goto_if_null(self.result_code, self.pos)))
2643 #-------------------------------------------------------------------
2645 # Unary operator nodes
2647 #-------------------------------------------------------------------
2649 compile_time_unary_operators = {
2650 'not': operator.not_,
2651 '~': operator.inv,
2652 '-': operator.neg,
2653 '+': operator.pos,
2656 class UnopNode(ExprNode):
2657 # operator string
2658 # operand ExprNode
2660 # Processing during analyse_expressions phase:
2662 # analyse_c_operation
2663 # Called when the operand is not a pyobject.
2664 # - Check operand type and coerce if needed.
2665 # - Determine result type and result code fragment.
2666 # - Allocate temporary for result if needed.
2668 subexprs = ['operand']
2670 def compile_time_value(self, denv):
2671 func = compile_time_unary_operators.get(self.operator)
2672 if not func:
2673 error(self.pos,
2674 "Unary '%s' not supported in compile-time expression"
2675 % self.operator)
2676 operand = self.operand.compile_time_value(denv)
2677 try:
2678 return func(operand)
2679 except Exception, e:
2680 self.compile_time_value_error(e)
2682 def analyse_types(self, env):
2683 self.operand.analyse_types(env)
2684 if self.is_py_operation():
2685 self.coerce_operand_to_pyobject(env)
2686 self.type = py_object_type
2687 self.gil_check(env)
2688 self.is_temp = 1
2689 else:
2690 self.analyse_c_operation(env)
2692 def check_const(self):
2693 self.operand.check_const()
2695 def is_py_operation(self):
2696 return self.operand.type.is_pyobject
2698 def coerce_operand_to_pyobject(self, env):
2699 self.operand = self.operand.coerce_to_pyobject(env)
2701 def generate_result_code(self, code):
2702 if self.operand.type.is_pyobject:
2703 self.generate_py_operation_code(code)
2704 else:
2705 if self.is_temp:
2706 self.generate_c_operation_code(code)
2708 def generate_py_operation_code(self, code):
2709 function = self.py_operation_function()
2710 code.putln(
2711 "%s = %s(%s); %s" % (
2712 self.result_code,
2713 function,
2714 self.operand.py_result(),
2715 code.error_goto_if_null(self.result_code, self.pos)))
2717 def type_error(self):
2718 if not self.operand.type.is_error:
2719 error(self.pos, "Invalid operand type for '%s' (%s)" %
2720 (self.operator, self.operand.type))
2721 self.type = PyrexTypes.error_type
2724 class NotNode(ExprNode):
2725 # 'not' operator
2727 # operand ExprNode
2729 def compile_time_value(self, denv):
2730 operand = self.operand.compile_time_value(denv)
2731 try:
2732 return not operand
2733 except Exception, e:
2734 self.compile_time_value_error(e)
2736 subexprs = ['operand']
2738 def analyse_types(self, env):
2739 self.operand.analyse_types(env)
2740 self.operand = self.operand.coerce_to_boolean(env)
2741 self.type = PyrexTypes.c_bint_type
2743 def calculate_result_code(self):
2744 return "(!%s)" % self.operand.result_code
2746 def generate_result_code(self, code):
2747 pass
2750 class UnaryPlusNode(UnopNode):
2751 # unary '+' operator
2753 operator = '+'
2755 def analyse_c_operation(self, env):
2756 self.type = self.operand.type
2758 def py_operation_function(self):
2759 return "PyNumber_Positive"
2761 def calculate_result_code(self):
2762 return self.operand.result_code
2765 class UnaryMinusNode(UnopNode):
2766 # unary '-' operator
2768 operator = '-'
2770 def analyse_c_operation(self, env):
2771 if self.operand.type.is_numeric:
2772 self.type = self.operand.type
2773 else:
2774 self.type_error()
2776 def py_operation_function(self):
2777 return "PyNumber_Negative"
2779 def calculate_result_code(self):
2780 return "(-%s)" % self.operand.result_code
2783 class TildeNode(UnopNode):
2784 # unary '~' operator
2786 def analyse_c_operation(self, env):
2787 if self.operand.type.is_int:
2788 self.type = self.operand.type
2789 else:
2790 self.type_error()
2792 def py_operation_function(self):
2793 return "PyNumber_Invert"
2795 def calculate_result_code(self):
2796 return "(~%s)" % self.operand.result_code
2799 class AmpersandNode(ExprNode):
2800 # The C address-of operator.
2802 # operand ExprNode
2804 subexprs = ['operand']
2806 def analyse_types(self, env):
2807 self.operand.analyse_types(env)
2808 argtype = self.operand.type
2809 if not (argtype.is_cfunction or self.operand.is_lvalue()):
2810 self.error("Taking address of non-lvalue")
2811 return
2812 if argtype.is_pyobject:
2813 self.error("Cannot take address of Python variable")
2814 return
2815 self.type = PyrexTypes.c_ptr_type(argtype)
2817 def check_const(self):
2818 self.operand.check_const_addr()
2820 def error(self, mess):
2821 error(self.pos, mess)
2822 self.type = PyrexTypes.error_type
2823 self.result_code = "<error>"
2825 def calculate_result_code(self):
2826 return "(&%s)" % self.operand.result_code
2828 def generate_result_code(self, code):
2829 pass
2832 unop_node_classes = {
2833 "+": UnaryPlusNode,
2834 "-": UnaryMinusNode,
2835 "~": TildeNode,
2838 def unop_node(pos, operator, operand):
2839 # Construct unnop node of appropriate class for
2840 # given operator.
2841 if isinstance(operand, IntNode) and operator == '-':
2842 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
2843 elif isinstance(operand, UnopNode) and operand.operator == operator:
2844 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
2845 return unop_node_classes[operator](pos,
2846 operator = operator,
2847 operand = operand)
2850 class TypecastNode(ExprNode):
2851 # C type cast
2853 # operand ExprNode
2854 # base_type CBaseTypeNode
2855 # declarator CDeclaratorNode
2857 # If used from a transform, one can if wanted specify the attribute
2858 # "type" directly and leave base_type and declarator to None
2860 subexprs = ['operand']
2861 base_type = declarator = type = None
2863 def analyse_types(self, env):
2864 if self.type is None:
2865 base_type = self.base_type.analyse(env)
2866 _, self.type = self.declarator.analyse(base_type, env)
2867 if self.type.is_cfunction:
2868 error(self.pos,
2869 "Cannot cast to a function type")
2870 self.type = PyrexTypes.error_type
2871 self.operand.analyse_types(env)
2872 to_py = self.type.is_pyobject
2873 from_py = self.operand.type.is_pyobject
2874 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
2875 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
2876 if to_py and not from_py:
2877 if self.operand.type.to_py_function:
2878 self.result_ctype = py_object_type
2879 self.operand = self.operand.coerce_to_pyobject(env)
2880 else:
2881 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
2882 elif from_py and not to_py:
2883 if self.type.from_py_function:
2884 self.operand = self.operand.coerce_to(self.type, env)
2885 else:
2886 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
2887 elif from_py and to_py:
2888 if self.typecheck and self.type.is_extension_type:
2889 self.operand = PyTypeTestNode(self.operand, self.type, env)
2891 def check_const(self):
2892 self.operand.check_const()
2894 def calculate_result_code(self):
2895 opnd = self.operand
2896 result_code = self.type.cast_code(opnd.result_code)
2897 return result_code
2899 def result_as(self, type):
2900 if self.type.is_pyobject and not self.is_temp:
2901 # Optimise away some unnecessary casting
2902 return self.operand.result_as(type)
2903 else:
2904 return ExprNode.result_as(self, type)
2906 def generate_result_code(self, code):
2907 if self.is_temp:
2908 code.putln(
2909 "%s = (PyObject *)%s;" % (
2910 self.result_code,
2911 self.operand.result_code))
2912 code.put_incref(self.result_code, self.ctype())
2915 class SizeofNode(ExprNode):
2916 # Abstract base class for sizeof(x) expression nodes.
2918 def check_const(self):
2919 pass
2921 def generate_result_code(self, code):
2922 pass
2925 class SizeofTypeNode(SizeofNode):
2926 # C sizeof function applied to a type
2928 # base_type CBaseTypeNode
2929 # declarator CDeclaratorNode
2931 subexprs = []
2933 def analyse_types(self, env):
2934 base_type = self.base_type.analyse(env)
2935 _, arg_type = self.declarator.analyse(base_type, env)
2936 self.arg_type = arg_type
2937 if arg_type.is_pyobject and not arg_type.is_extension_type:
2938 error(self.pos, "Cannot take sizeof Python object")
2939 elif arg_type.is_void:
2940 error(self.pos, "Cannot take sizeof void")
2941 elif not arg_type.is_complete():
2942 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
2943 self.type = PyrexTypes.c_int_type
2945 def calculate_result_code(self):
2946 if self.arg_type.is_extension_type:
2947 # the size of the pointer is boring
2948 # we want the size of the actual struct
2949 arg_code = self.arg_type.declaration_code("", deref=1)
2950 else:
2951 arg_code = self.arg_type.declaration_code("")
2952 return "(sizeof(%s))" % arg_code
2955 class SizeofVarNode(SizeofNode):
2956 # C sizeof function applied to a variable
2958 # operand ExprNode
2960 subexprs = ['operand']
2962 def analyse_types(self, env):
2963 self.operand.analyse_types(env)
2964 self.type = PyrexTypes.c_int_type
2966 def calculate_result_code(self):
2967 return "(sizeof(%s))" % self.operand.result_code
2969 def generate_result_code(self, code):
2970 pass
2973 #-------------------------------------------------------------------
2975 # Binary operator nodes
2977 #-------------------------------------------------------------------
2979 def _not_in(x, seq):
2980 return x not in seq
2982 compile_time_binary_operators = {
2983 '<': operator.lt,
2984 '<=': operator.le,
2985 '==': operator.eq,
2986 '!=': operator.ne,
2987 '>=': operator.ge,
2988 '>': operator.gt,
2989 'is': operator.is_,
2990 'is_not': operator.is_not,
2991 '+': operator.add,
2992 '&': operator.and_,
2993 '/': operator.div,
2994 '//': operator.floordiv,
2995 '<<': operator.lshift,
2996 '%': operator.mod,
2997 '*': operator.mul,
2998 '|': operator.or_,
2999 '**': operator.pow,
3000 '>>': operator.rshift,
3001 '-': operator.sub,
3002 #'/': operator.truediv,
3003 '^': operator.xor,
3004 'in': operator.contains,
3005 'not_in': _not_in,
3008 def get_compile_time_binop(node):
3009 func = compile_time_binary_operators.get(node.operator)
3010 if not func:
3011 error(node.pos,
3012 "Binary '%s' not supported in compile-time expression"
3013 % node.operator)
3014 return func
3016 class BinopNode(ExprNode):
3017 # operator string
3018 # operand1 ExprNode
3019 # operand2 ExprNode
3021 # Processing during analyse_expressions phase:
3023 # analyse_c_operation
3024 # Called when neither operand is a pyobject.
3025 # - Check operand types and coerce if needed.
3026 # - Determine result type and result code fragment.
3027 # - Allocate temporary for result if needed.
3029 subexprs = ['operand1', 'operand2']
3031 def compile_time_value(self, denv):
3032 func = get_compile_time_binop(self)
3033 operand1 = self.operand1.compile_time_value(denv)
3034 operand2 = self.operand2.compile_time_value(denv)
3035 try:
3036 return func(operand1, operand2)
3037 except Exception, e:
3038 self.compile_time_value_error(e)
3040 def analyse_types(self, env):
3041 self.operand1.analyse_types(env)
3042 self.operand2.analyse_types(env)
3043 if self.is_py_operation():
3044 self.coerce_operands_to_pyobjects(env)
3045 self.type = py_object_type
3046 self.gil_check(env)
3047 self.is_temp = 1
3048 if Options.incref_local_binop and self.operand1.type.is_pyobject:
3049 self.operand1 = self.operand1.coerce_to_temp(env)
3050 else:
3051 self.analyse_c_operation(env)
3053 def is_py_operation(self):
3054 return (self.operand1.type.is_pyobject
3055 or self.operand2.type.is_pyobject)
3057 def coerce_operands_to_pyobjects(self, env):
3058 self.operand1 = self.operand1.coerce_to_pyobject(env)
3059 self.operand2 = self.operand2.coerce_to_pyobject(env)
3061 def check_const(self):
3062 self.operand1.check_const()
3063 self.operand2.check_const()
3065 def generate_result_code(self, code):
3066 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
3067 if self.operand1.type.is_pyobject:
3068 function = self.py_operation_function()
3069 if function == "PyNumber_Power":
3070 extra_args = ", Py_None"
3071 else:
3072 extra_args = ""
3073 code.putln(
3074 "%s = %s(%s, %s%s); %s" % (
3075 self.result_code,
3076 function,
3077 self.operand1.py_result(),
3078 self.operand2.py_result(),
3079 extra_args,
3080 code.error_goto_if_null(self.result_code, self.pos)))
3081 else:
3082 if self.is_temp:
3083 self.generate_c_operation_code(code)
3085 def type_error(self):
3086 if not (self.operand1.type.is_error
3087 or self.operand2.type.is_error):
3088 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
3089 (self.operator, self.operand1.type,
3090 self.operand2.type))
3091 self.type = PyrexTypes.error_type
3094 class NumBinopNode(BinopNode):
3095 # Binary operation taking numeric arguments.
3097 def analyse_c_operation(self, env):
3098 type1 = self.operand1.type
3099 type2 = self.operand2.type
3100 if self.operator == "**" and type1.is_int and type2.is_int:
3101 error(self.pos, "** with two C int types is ambiguous")
3102 self.type = error_type
3103 return
3104 self.type = self.compute_c_result_type(type1, type2)
3105 if not self.type:
3106 self.type_error()
3108 def compute_c_result_type(self, type1, type2):
3109 if self.c_types_okay(type1, type2):
3110 return PyrexTypes.widest_numeric_type(type1, type2)
3111 else:
3112 return None
3114 def c_types_okay(self, type1, type2):
3115 #print "NumBinopNode.c_types_okay:", type1, type2 ###
3116 return (type1.is_numeric or type1.is_enum) \
3117 and (type2.is_numeric or type2.is_enum)
3119 def calculate_result_code(self):
3120 return "(%s %s %s)" % (
3121 self.operand1.result_code,
3122 self.operator,
3123 self.operand2.result_code)
3125 def py_operation_function(self):
3126 return self.py_functions[self.operator]
3128 py_functions = {
3129 "|": "PyNumber_Or",
3130 "^": "PyNumber_Xor",
3131 "&": "PyNumber_And",
3132 "<<": "PyNumber_Lshift",
3133 ">>": "PyNumber_Rshift",
3134 "+": "PyNumber_Add",
3135 "-": "PyNumber_Subtract",
3136 "*": "PyNumber_Multiply",
3137 "/": "__Pyx_PyNumber_Divide",
3138 "//": "PyNumber_FloorDivide",
3139 "%": "PyNumber_Remainder",
3140 "**": "PyNumber_Power"
3144 class IntBinopNode(NumBinopNode):
3145 # Binary operation taking integer arguments.
3147 def c_types_okay(self, type1, type2):
3148 #print "IntBinopNode.c_types_okay:", type1, type2 ###
3149 return (type1.is_int or type1.is_enum) \
3150 and (type2.is_int or type2.is_enum)
3153 class AddNode(NumBinopNode):
3154 # '+' operator.
3156 def is_py_operation(self):
3157 if self.operand1.type.is_string \
3158 and self.operand2.type.is_string:
3159 return 1
3160 else:
3161 return NumBinopNode.is_py_operation(self)
3163 def compute_c_result_type(self, type1, type2):
3164 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
3165 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3166 return type1
3167 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
3168 return type2
3169 else:
3170 return NumBinopNode.compute_c_result_type(
3171 self, type1, type2)
3174 class SubNode(NumBinopNode):
3175 # '-' operator.
3177 def compute_c_result_type(self, type1, type2):
3178 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3179 return type1
3180 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
3181 return PyrexTypes.c_int_type
3182 else:
3183 return NumBinopNode.compute_c_result_type(
3184 self, type1, type2)
3187 class MulNode(NumBinopNode):
3188 # '*' operator.
3190 def is_py_operation(self):
3191 type1 = self.operand1.type
3192 type2 = self.operand2.type
3193 if (type1.is_string and type2.is_int) \
3194 or (type2.is_string and type1.is_int):
3195 return 1
3196 else:
3197 return NumBinopNode.is_py_operation(self)
3200 class FloorDivNode(NumBinopNode):
3201 # '//' operator.
3203 def calculate_result_code(self):
3204 return "(%s %s %s)" % (
3205 self.operand1.result_code,
3206 "/", # c division is by default floor-div
3207 self.operand2.result_code)
3210 class ModNode(IntBinopNode):
3211 # '%' operator.
3213 def is_py_operation(self):
3214 return (self.operand1.type.is_string
3215 or self.operand2.type.is_string
3216 or IntBinopNode.is_py_operation(self))
3219 class PowNode(NumBinopNode):
3220 # '**' operator.
3222 def analyse_types(self, env):
3223 env.pow_function_used = 1
3224 NumBinopNode.analyse_types(self, env)
3226 def compute_c_result_type(self, type1, type2):
3227 if self.c_types_okay(type1, type2):
3228 return PyrexTypes.c_double_type
3229 else:
3230 return None
3232 def c_types_okay(self, type1, type2):
3233 return (type1.is_float or type2.is_float) and \
3234 NumBinopNode.c_types_okay(self, type1, type2)
3236 def type_error(self):
3237 if not (self.operand1.type.is_error or self.operand2.type.is_error):
3238 if self.operand1.type.is_int and self.operand2.type.is_int:
3239 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
3240 (self.operator, self.operand1.type, self.operand2.type))
3241 else:
3242 NumBinopNode.type_error(self)
3243 self.type = PyrexTypes.error_type
3245 def calculate_result_code(self):
3246 return "pow(%s, %s)" % (
3247 self.operand1.result_code, self.operand2.result_code)
3250 class BoolBinopNode(ExprNode):
3251 # Short-circuiting boolean operation.
3253 # operator string
3254 # operand1 ExprNode
3255 # operand2 ExprNode
3256 # temp_bool ExprNode used internally
3258 temp_bool = None
3260 subexprs = ['operand1', 'operand2', 'temp_bool']
3262 def compile_time_value(self, denv):
3263 if self.operator == 'and':
3264 return self.operand1.compile_time_value(denv) \
3265 and self.operand2.compile_time_value(denv)
3266 else:
3267 return self.operand1.compile_time_value(denv) \
3268 or self.operand2.compile_time_value(denv)
3270 def analyse_types(self, env):
3271 self.operand1.analyse_types(env)
3272 self.operand2.analyse_types(env)
3273 if self.operand1.type.is_pyobject or \
3274 self.operand2.type.is_pyobject:
3275 self.operand1 = self.operand1.coerce_to_pyobject(env)
3276 self.operand2 = self.operand2.coerce_to_pyobject(env)
3277 self.temp_bool = TempNode(self.pos, PyrexTypes.c_bint_type, env)
3278 self.type = py_object_type
3279 self.gil_check(env)
3280 else:
3281 self.operand1 = self.operand1.coerce_to_boolean(env)
3282 self.operand2 = self.operand2.coerce_to_boolean(env)
3283 self.type = PyrexTypes.c_bint_type
3284 # For what we're about to do, it's vital that
3285 # both operands be temp nodes.
3286 self.operand1 = self.operand1.coerce_to_temp(env) #CTT
3287 self.operand2 = self.operand2.coerce_to_temp(env)
3288 self.is_temp = 1
3290 gil_message = "Truth-testing Python object"
3292 def allocate_temps(self, env, result_code = None):
3293 # We don't need both operands at the same time, and
3294 # one of the operands will also be our result. So we
3295 # use an allocation strategy here which results in
3296 # this node and both its operands sharing the same
3297 # result variable. This allows us to avoid some
3298 # assignments and increfs/decrefs that would otherwise
3299 # be necessary.
3300 self.allocate_temp(env, result_code)
3301 self.operand1.allocate_temps(env, self.result_code)
3302 if self.temp_bool:
3303 self.temp_bool.allocate_temp(env)
3304 self.temp_bool.release_temp(env)
3305 self.operand2.allocate_temps(env, self.result_code)
3306 # We haven't called release_temp on either operand,
3307 # because although they are temp nodes, they don't own
3308 # their result variable. And because they are temp
3309 # nodes, any temps in their subnodes will have been
3310 # released before their allocate_temps returned.
3311 # Therefore, they contain no temp vars that need to
3312 # be released.
3314 def check_const(self):
3315 self.operand1.check_const()
3316 self.operand2.check_const()
3318 def calculate_result_code(self):
3319 return "(%s %s %s)" % (
3320 self.operand1.result_code,
3321 self.py_to_c_op[self.operator],
3322 self.operand2.result_code)
3324 py_to_c_op = {'and': "&&", 'or': "||"}
3326 def generate_evaluation_code(self, code):
3327 self.operand1.generate_evaluation_code(code)
3328 test_result = self.generate_operand1_test(code)
3329 if self.operator == 'and':
3330 sense = ""
3331 else:
3332 sense = "!"
3333 code.putln(
3334 "if (%s%s) {" % (
3335 sense,
3336 test_result))
3337 self.operand1.generate_disposal_code(code)
3338 self.operand2.generate_evaluation_code(code)
3339 code.putln(
3340 "}")
3342 def generate_operand1_test(self, code):
3343 # Generate code to test the truth of the first operand.
3344 if self.type.is_pyobject:
3345 test_result = self.temp_bool.result_code
3346 code.putln(
3347 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3348 test_result,
3349 self.operand1.py_result(),
3350 code.error_goto_if_neg(test_result, self.pos)))
3351 else:
3352 test_result = self.operand1.result_code
3353 return test_result
3356 class CondExprNode(ExprNode):
3357 # Short-circuiting conditional expression.
3359 # test ExprNode
3360 # true_val ExprNode
3361 # false_val ExprNode
3363 temp_bool = None
3364 true_val = None
3365 false_val = None
3367 subexprs = ['test', 'true_val', 'false_val']
3369 def analyse_types(self, env):
3370 self.test.analyse_types(env)
3371 self.test = self.test.coerce_to_boolean(env)
3372 self.true_val.analyse_types(env)
3373 self.false_val.analyse_types(env)
3374 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
3375 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
3376 self.true_val = self.true_val.coerce_to(self.type, env)
3377 self.false_val = self.false_val.coerce_to(self.type, env)
3378 # must be tmp variables so they can share a result
3379 self.true_val = self.true_val.coerce_to_temp(env)
3380 self.false_val = self.false_val.coerce_to_temp(env)
3381 self.is_temp = 1
3382 if self.type == PyrexTypes.error_type:
3383 self.type_error()
3385 def allocate_temps(self, env, result_code = None):
3386 # We only ever evaluate one side, and this is
3387 # after evaluating the truth value, so we may
3388 # use an allocation strategy here which results in
3389 # this node and both its operands sharing the same
3390 # result variable. This allows us to avoid some
3391 # assignments and increfs/decrefs that would otherwise
3392 # be necessary.
3393 self.allocate_temp(env, result_code)
3394 self.test.allocate_temps(env, result_code)
3395 self.true_val.allocate_temps(env, self.result_code)
3396 self.false_val.allocate_temps(env, self.result_code)
3397 # We haven't called release_temp on either value,
3398 # because although they are temp nodes, they don't own
3399 # their result variable. And because they are temp
3400 # nodes, any temps in their subnodes will have been
3401 # released before their allocate_temps returned.
3402 # Therefore, they contain no temp vars that need to
3403 # be released.
3405 def compute_result_type(self, type1, type2):
3406 if type1 == type2:
3407 return type1
3408 elif type1.is_numeric and type2.is_numeric:
3409 return PyrexTypes.widest_numeric_type(type1, type2)
3410 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
3411 return type2
3412 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
3413 return type1
3414 elif type1.is_pyobject or type2.is_pyobject:
3415 return py_object_type
3416 elif type1.assignable_from(type2):
3417 return type1
3418 elif type2.assignable_from(type1):
3419 return type2
3420 else:
3421 return PyrexTypes.error_type
3423 def type_error(self):
3424 if not (self.true_val.type.is_error or self.false_val.type.is_error):
3425 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
3426 (self.true_val.type, self.false_val.type))
3427 self.type = PyrexTypes.error_type
3429 def check_const(self):
3430 self.test.check_const()
3431 self.true_val.check_const()
3432 self.false_val.check_const()
3434 def generate_evaluation_code(self, code):
3435 self.test.generate_evaluation_code(code)
3436 code.putln("if (%s) {" % self.test.result_code )
3437 self.true_val.generate_evaluation_code(code)
3438 code.putln("} else {")
3439 self.false_val.generate_evaluation_code(code)
3440 code.putln("}")
3441 self.test.generate_disposal_code(code)
3443 richcmp_constants = {
3444 "<" : "Py_LT",
3445 "<=": "Py_LE",
3446 "==": "Py_EQ",
3447 "!=": "Py_NE",
3448 "<>": "Py_NE",
3449 ">" : "Py_GT",
3450 ">=": "Py_GE",
3453 class CmpNode:
3454 # Mixin class containing code common to PrimaryCmpNodes
3455 # and CascadedCmpNodes.
3457 def cascaded_compile_time_value(self, operand1, denv):
3458 func = get_compile_time_binop(self)
3459 operand2 = self.operand2.compile_time_value(denv)
3460 try:
3461 result = func(operand1, operand2)
3462 except Exception, e:
3463 self.compile_time_value_error(e)
3464 result = None
3465 if result:
3466 cascade = self.cascade
3467 if cascade:
3468 result = result and cascade.compile_time_value(operand2, denv)
3469 return result
3471 def is_python_comparison(self):
3472 return (self.has_python_operands()
3473 or (self.cascade and self.cascade.is_python_comparison())
3474 or self.operator in ('in', 'not_in'))
3476 def is_python_result(self):
3477 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
3478 or (self.cascade and self.cascade.is_python_result()))
3480 def check_types(self, env, operand1, op, operand2):
3481 if not self.types_okay(operand1, op, operand2):
3482 error(self.pos, "Invalid types for '%s' (%s, %s)" %
3483 (self.operator, operand1.type, operand2.type))
3485 def types_okay(self, operand1, op, operand2):
3486 type1 = operand1.type
3487 type2 = operand2.type
3488 if type1.is_error or type2.is_error:
3489 return 1
3490 if type1.is_pyobject: # type2 will be, too
3491 return 1
3492 elif type1.is_ptr or type1.is_array:
3493 return type1.is_null_ptr or type2.is_null_ptr \
3494 or ((type2.is_ptr or type2.is_array)
3495 and type1.base_type.same_as(type2.base_type))
3496 elif ((type1.is_numeric and type2.is_numeric
3497 or type1.is_enum and (type1 is type2 or type2.is_int)
3498 or type1.is_int and type2.is_enum)
3499 and op not in ('is', 'is_not')):
3500 return 1
3501 else:
3502 return type1.is_cfunction and type1.is_cfunction and type1 == type2
3504 def generate_operation_code(self, code, result_code,
3505 operand1, op , operand2):
3506 if self.type is PyrexTypes.py_object_type:
3507 coerce_result = "__Pyx_PyBool_FromLong"
3508 else:
3509 coerce_result = ""
3510 if 'not' in op: negation = "!"
3511 else: negation = ""
3512 if op == 'in' or op == 'not_in':
3513 code.putln(
3514 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
3515 result_code,
3516 coerce_result,
3517 negation,
3518 operand2.py_result(),
3519 operand1.py_result(),
3520 code.error_goto_if_neg(result_code, self.pos)))
3521 elif (operand1.type.is_pyobject
3522 and op not in ('is', 'is_not')):
3523 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
3524 result_code,
3525 operand1.py_result(),
3526 operand2.py_result(),
3527 richcmp_constants[op],
3528 code.error_goto_if_null(result_code, self.pos)))
3529 else:
3530 type1 = operand1.type
3531 type2 = operand2.type
3532 if (type1.is_extension_type or type2.is_extension_type) \
3533 and not type1.same_as(type2):
3534 common_type = py_object_type
3535 elif type1.is_numeric:
3536 common_type = PyrexTypes.widest_numeric_type(type1, type2)
3537 else:
3538 common_type = type1
3539 code1 = operand1.result_as(common_type)
3540 code2 = operand2.result_as(common_type)
3541 code.putln("%s = %s(%s %s %s);" % (
3542 result_code,
3543 coerce_result,
3544 code1,
3545 self.c_operator(op),
3546 code2))
3548 def c_operator(self, op):
3549 if op == 'is':
3550 return "=="
3551 elif op == 'is_not':
3552 return "!="
3553 else:
3554 return op
3557 class PrimaryCmpNode(ExprNode, CmpNode):
3558 # Non-cascaded comparison or first comparison of
3559 # a cascaded sequence.
3561 # operator string
3562 # operand1 ExprNode
3563 # operand2 ExprNode
3564 # cascade CascadedCmpNode
3566 # We don't use the subexprs mechanism, because
3567 # things here are too complicated for it to handle.
3568 # Instead, we override all the framework methods
3569 # which use it.
3571 child_attrs = ['operand1', 'operand2', 'cascade']
3573 cascade = None
3575 def compile_time_value(self, denv):
3576 operand1 = self.operand1.compile_time_value(denv)
3577 return self.cascaded_compile_time_value(operand1, denv)
3579 def analyse_types(self, env):
3580 self.operand1.analyse_types(env)
3581 self.operand2.analyse_types(env)
3582 if self.cascade:
3583 self.cascade.analyse_types(env, self.operand2)
3584 self.is_pycmp = self.is_python_comparison()
3585 if self.is_pycmp:
3586 self.coerce_operands_to_pyobjects(env)
3587 if self.has_int_operands():
3588 self.coerce_chars_to_ints(env)
3589 if self.cascade:
3590 self.operand2 = self.operand2.coerce_to_simple(env)
3591 self.cascade.coerce_cascaded_operands_to_temp(env)
3592 self.check_operand_types(env)
3593 if self.is_python_result():
3594 self.type = PyrexTypes.py_object_type
3595 else:
3596 self.type = PyrexTypes.c_bint_type
3597 cdr = self.cascade
3598 while cdr:
3599 cdr.type = self.type
3600 cdr = cdr.cascade
3601 if self.is_pycmp or self.cascade:
3602 self.is_temp = 1
3604 def check_operand_types(self, env):
3605 self.check_types(env,
3606 self.operand1, self.operator, self.operand2)
3607 if self.cascade:
3608 self.cascade.check_operand_types(env, self.operand2)
3610 def has_python_operands(self):
3611 return (self.operand1.type.is_pyobject
3612 or self.operand2.type.is_pyobject)
3614 def coerce_operands_to_pyobjects(self, env):
3615 self.operand1 = self.operand1.coerce_to_pyobject(env)
3616 self.operand2 = self.operand2.coerce_to_pyobject(env)
3617 if self.cascade:
3618 self.cascade.coerce_operands_to_pyobjects(env)
3620 def has_int_operands(self):
3621 return (self.operand1.type.is_int or self.operand2.type.is_int) \
3622 or (self.cascade and self.cascade.has_int_operands())
3624 def coerce_chars_to_ints(self, env):
3625 # coerce literal single-char strings to c chars
3626 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
3627 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
3628 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
3629 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3630 if self.cascade:
3631 self.cascade.coerce_chars_to_ints(env)
3633 def allocate_subexpr_temps(self, env):
3634 self.operand1.allocate_temps(env)
3635 self.operand2.allocate_temps(env)
3636 if self.cascade:
3637 self.cascade.allocate_subexpr_temps(env)
3639 def release_subexpr_temps(self, env):
3640 self.operand1.release_temp(env)
3641 self.operand2.release_temp(env)
3642 if self.cascade:
3643 self.cascade.release_subexpr_temps(env)
3645 def check_const(self):
3646 self.operand1.check_const()
3647 self.operand2.check_const()
3648 if self.cascade:
3649 self.not_const()
3651 def calculate_result_code(self):
3652 return "(%s %s %s)" % (
3653 self.operand1.result_code,
3654 self.c_operator(self.operator),
3655 self.operand2.result_code)
3657 def generate_evaluation_code(self, code):
3658 self.operand1.generate_evaluation_code(code)
3659 self.operand2.generate_evaluation_code(code)
3660 if self.is_temp:
3661 self.generate_operation_code(code, self.result_code,
3662 self.operand1, self.operator, self.operand2)
3663 if self.cascade:
3664 self.cascade.generate_evaluation_code(code,
3665 self.result_code, self.operand2)
3666 self.operand1.generate_disposal_code(code)
3667 self.operand2.generate_disposal_code(code)
3669 def generate_subexpr_disposal_code(self, code):
3670 # If this is called, it is a non-cascaded cmp,
3671 # so only need to dispose of the two main operands.
3672 self.operand1.generate_disposal_code(code)
3673 self.operand2.generate_disposal_code(code)
3675 def annotate(self, code):
3676 self.operand1.annotate(code)
3677 self.operand2.annotate(code)
3678 if self.cascade:
3679 self.cascade.annotate(code)
3682 class CascadedCmpNode(Node, CmpNode):
3683 # A CascadedCmpNode is not a complete expression node. It
3684 # hangs off the side of another comparison node, shares
3685 # its left operand with that node, and shares its result
3686 # with the PrimaryCmpNode at the head of the chain.
3688 # operator string
3689 # operand2 ExprNode
3690 # cascade CascadedCmpNode
3692 child_attrs = ['operand2', 'cascade']
3694 cascade = None
3696 def analyse_types(self, env, operand1):
3697 self.operand2.analyse_types(env)
3698 if self.cascade:
3699 self.cascade.analyse_types(env, self.operand2)
3701 def check_operand_types(self, env, operand1):
3702 self.check_types(env,
3703 operand1, self.operator, self.operand2)
3704 if self.cascade:
3705 self.cascade.check_operand_types(env, self.operand2)
3707 def has_python_operands(self):
3708 return self.operand2.type.is_pyobject
3710 def coerce_operands_to_pyobjects(self, env):
3711 self.operand2 = self.operand2.coerce_to_pyobject(env)
3712 if self.cascade:
3713 self.cascade.coerce_operands_to_pyobjects(env)
3715 def has_int_operands(self):
3716 return self.operand2.type.is_int
3718 def coerce_chars_to_ints(self, env):
3719 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
3720 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3722 def coerce_cascaded_operands_to_temp(self, env):
3723 if self.cascade:
3724 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
3725 self.operand2 = self.operand2.coerce_to_simple(env)
3726 self.cascade.coerce_cascaded_operands_to_temp(env)
3728 def allocate_subexpr_temps(self, env):
3729 self.operand2.allocate_temps(env)
3730 if self.cascade:
3731 self.cascade.allocate_subexpr_temps(env)
3733 def release_subexpr_temps(self, env):
3734 self.operand2.release_temp(env)
3735 if self.cascade:
3736 self.cascade.release_subexpr_temps(env)
3738 def generate_evaluation_code(self, code, result, operand1):
3739 if self.type.is_pyobject:
3740 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
3741 else:
3742 code.putln("if (%s) {" % result)
3743 self.operand2.generate_evaluation_code(code)
3744 self.generate_operation_code(code, result,
3745 operand1, self.operator, self.operand2)
3746 if self.cascade:
3747 self.cascade.generate_evaluation_code(
3748 code, result, self.operand2)
3749 # Cascaded cmp result is always temp
3750 self.operand2.generate_disposal_code(code)
3751 code.putln("}")
3753 def annotate(self, code):
3754 self.operand2.annotate(code)
3755 if self.cascade:
3756 self.cascade.annotate(code)
3759 binop_node_classes = {
3760 "or": BoolBinopNode,
3761 "and": BoolBinopNode,
3762 "|": IntBinopNode,
3763 "^": IntBinopNode,
3764 "&": IntBinopNode,
3765 "<<": IntBinopNode,
3766 ">>": IntBinopNode,
3767 "+": AddNode,
3768 "-": SubNode,
3769 "*": MulNode,
3770 "/": NumBinopNode,
3771 "//": FloorDivNode,
3772 "%": ModNode,
3773 "**": PowNode
3776 def binop_node(pos, operator, operand1, operand2):
3777 # Construct binop node of appropriate class for
3778 # given operator.
3779 return binop_node_classes[operator](pos,
3780 operator = operator,
3781 operand1 = operand1,
3782 operand2 = operand2)
3784 #-------------------------------------------------------------------
3786 # Coercion nodes
3788 # Coercion nodes are special in that they are created during
3789 # the analyse_types phase of parse tree processing.
3790 # Their __init__ methods consequently incorporate some aspects
3791 # of that phase.
3793 #-------------------------------------------------------------------
3795 class CoercionNode(ExprNode):
3796 # Abstract base class for coercion nodes.
3798 # arg ExprNode node being coerced
3800 subexprs = ['arg']
3802 def __init__(self, arg):
3803 self.pos = arg.pos
3804 self.arg = arg
3805 if debug_coercion:
3806 print("%s Coercing %s" % (self, self.arg))
3808 def annotate(self, code):
3809 self.arg.annotate(code)
3810 if self.arg.type != self.type:
3811 file, line, col = self.pos
3812 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
3815 class CastNode(CoercionNode):
3816 # Wrap a node in a C type cast.
3818 def __init__(self, arg, new_type):
3819 CoercionNode.__init__(self, arg)
3820 self.type = new_type
3822 def calculate_result_code(self):
3823 return self.arg.result_as(self.type)
3825 def generate_result_code(self, code):
3826 self.arg.generate_result_code(code)
3829 class PyTypeTestNode(CoercionNode):
3830 # This node is used to check that a generic Python
3831 # object is an instance of a particular extension type.
3832 # This node borrows the result of its argument node.
3834 def __init__(self, arg, dst_type, env):
3835 # The arg is know to be a Python object, and
3836 # the dst_type is known to be an extension type.
3837 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
3838 CoercionNode.__init__(self, arg)
3839 self.type = dst_type
3840 self.gil_check(env)
3841 self.result_ctype = arg.ctype()
3842 env.use_utility_code(type_test_utility_code)
3844 gil_message = "Python type test"
3846 def analyse_types(self, env):
3847 pass
3849 def result_in_temp(self):
3850 return self.arg.result_in_temp()
3852 def is_ephemeral(self):
3853 return self.arg.is_ephemeral()
3855 def calculate_result_code(self):
3856 return self.arg.result_code
3858 def generate_result_code(self, code):
3859 if self.type.typeobj_is_available():
3860 code.putln(
3861 "if (!(%s)) %s" % (
3862 self.type.type_test_code(self.arg.py_result()),
3863 code.error_goto(self.pos)))
3864 else:
3865 error(self.pos, "Cannot test type of extern C class "
3866 "without type object name specification")
3868 def generate_post_assignment_code(self, code):
3869 self.arg.generate_post_assignment_code(code)
3872 class CoerceToPyTypeNode(CoercionNode):
3873 # This node is used to convert a C data type
3874 # to a Python object.
3876 def __init__(self, arg, env):
3877 CoercionNode.__init__(self, arg)
3878 self.type = py_object_type
3879 self.gil_check(env)
3880 self.is_temp = 1
3881 if not arg.type.to_py_function:
3882 error(arg.pos,
3883 "Cannot convert '%s' to Python object" % arg.type)
3885 gil_message = "Converting to Python object"
3887 def analyse_types(self, env):
3888 # The arg is always already analysed
3889 pass
3891 def generate_result_code(self, code):
3892 function = self.arg.type.to_py_function
3893 code.putln('%s = %s(%s); %s' % (
3894 self.result_code,
3895 function,
3896 self.arg.result_code,
3897 code.error_goto_if_null(self.result_code, self.pos)))
3900 class CoerceFromPyTypeNode(CoercionNode):
3901 # This node is used to convert a Python object
3902 # to a C data type.
3904 def __init__(self, result_type, arg, env):
3905 CoercionNode.__init__(self, arg)
3906 self.type = result_type
3907 self.is_temp = 1
3908 if not result_type.from_py_function:
3909 error(arg.pos,
3910 "Cannot convert Python object to '%s'" % result_type)
3911 if self.type.is_string and self.arg.is_ephemeral():
3912 error(arg.pos,
3913 "Obtaining char * from temporary Python value")
3915 def analyse_types(self, env):
3916 # The arg is always already analysed
3917 pass
3919 def generate_result_code(self, code):
3920 function = self.type.from_py_function
3921 operand = self.arg.py_result()
3922 rhs = "%s(%s)" % (function, operand)
3923 if self.type.is_enum:
3924 rhs = typecast(self.type, c_long_type, rhs)
3925 code.putln('%s = %s; %s' % (
3926 self.result_code,
3927 rhs,
3928 code.error_goto_if(self.type.error_condition(self.result_code), self.pos)))
3931 class CoerceToBooleanNode(CoercionNode):
3932 # This node is used when a result needs to be used
3933 # in a boolean context.
3935 def __init__(self, arg, env):
3936 CoercionNode.__init__(self, arg)
3937 self.type = PyrexTypes.c_bint_type
3938 if arg.type.is_pyobject:
3939 if env.nogil:
3940 self.gil_error()
3941 self.is_temp = 1
3943 gil_message = "Truth-testing Python object"
3945 def check_const(self):
3946 if self.is_temp:
3947 self.not_const()
3948 self.arg.check_const()
3950 def calculate_result_code(self):
3951 return "(%s != 0)" % self.arg.result_code
3953 def generate_result_code(self, code):
3954 if self.arg.type.is_pyobject:
3955 code.putln(
3956 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3957 self.result_code,
3958 self.arg.py_result(),
3959 code.error_goto_if_neg(self.result_code, self.pos)))
3962 class CoerceToTempNode(CoercionNode):
3963 # This node is used to force the result of another node
3964 # to be stored in a temporary. It is only used if the
3965 # argument node's result is not already in a temporary.
3967 def __init__(self, arg, env):
3968 CoercionNode.__init__(self, arg)
3969 self.type = self.arg.type
3970 self.is_temp = 1
3971 if self.type.is_pyobject:
3972 self.gil_check(env)
3973 self.result_ctype = py_object_type
3975 gil_message = "Creating temporary Python reference"
3977 def analyse_types(self, env):
3978 # The arg is always already analysed
3979 pass
3981 def generate_result_code(self, code):
3982 #self.arg.generate_evaluation_code(code) # Already done
3983 # by generic generate_subexpr_evaluation_code!
3984 code.putln("%s = %s;" % (
3985 self.result_code, self.arg.result_as(self.ctype())))
3986 if self.type.is_pyobject:
3987 code.put_incref(self.result_code, self.ctype())
3990 class CloneNode(CoercionNode):
3991 # This node is employed when the result of another node needs
3992 # to be used multiple times. The argument node's result must
3993 # be in a temporary. This node "borrows" the result from the
3994 # argument node, and does not generate any evaluation or
3995 # disposal code for it. The original owner of the argument
3996 # node is responsible for doing those things.
3998 subexprs = [] # Arg is not considered a subexpr
4000 def __init__(self, arg):
4001 CoercionNode.__init__(self, arg)
4002 if hasattr(arg, 'type'):
4003 self.type = arg.type
4004 self.result_ctype = arg.result_ctype
4005 if hasattr(arg, 'entry'):
4006 self.entry = arg.entry
4008 def calculate_result_code(self):
4009 return self.arg.result_code
4011 def analyse_types(self, env):
4012 self.type = self.arg.type
4013 self.result_ctype = self.arg.result_ctype
4014 self.is_temp = 1
4015 if hasattr(self.arg, 'entry'):
4016 self.entry = self.arg.entry
4018 def generate_evaluation_code(self, code):
4019 pass
4021 def generate_result_code(self, code):
4022 pass
4024 def generate_disposal_code(self, code):
4025 pass
4027 def allocate_temps(self, env):
4028 self.result_code = self.calculate_result_code()
4030 def release_temp(self, env):
4031 pass
4033 class PersistentNode(ExprNode):
4034 # A PersistentNode is like a CloneNode except it handles the temporary
4035 # allocation itself by keeping track of the number of times it has been
4036 # used.
4038 subexprs = ["arg"]
4039 temp_counter = 0
4040 generate_counter = 0
4041 analyse_counter = 0
4042 result_code = None
4044 def __init__(self, arg, uses):
4045 self.pos = arg.pos
4046 self.arg = arg
4047 self.uses = uses
4049 def analyse_types(self, env):
4050 if self.analyse_counter == 0:
4051 self.arg.analyse_types(env)
4052 self.type = self.arg.type
4053 self.result_ctype = self.arg.result_ctype
4054 self.is_temp = 1
4055 self.analyse_counter += 1
4057 def calculate_result_code(self):
4058 return self.result_code
4060 def generate_evaluation_code(self, code):
4061 if self.generate_counter == 0:
4062 self.arg.generate_evaluation_code(code)
4063 code.putln("%s = %s;" % (
4064 self.result_code, self.arg.result_as(self.ctype())))
4065 if self.type.is_pyobject:
4066 code.put_incref(self.result_code, self.ctype())
4067 self.arg.generate_disposal_code(code)
4068 self.generate_counter += 1
4070 def generate_disposal_code(self, code):
4071 if self.generate_counter == self.uses:
4072 if self.type.is_pyobject:
4073 code.put_decref_clear(self.result_code, self.ctype())
4075 def allocate_temps(self, env, result=None):
4076 if self.temp_counter == 0:
4077 self.arg.allocate_temps(env)
4078 self.allocate_temp(env, result)
4079 self.arg.release_temp(env)
4080 self.temp_counter += 1
4082 def allocate_temp(self, env, result=None):
4083 if result is None:
4084 self.result_code = env.allocate_temp(self.type)
4085 else:
4086 self.result_code = result
4088 def release_temp(self, env):
4089 if self.temp_counter == self.uses:
4090 env.release_temp(self.result_code)
4092 #------------------------------------------------------------------------------------
4094 # Runtime support code
4096 #------------------------------------------------------------------------------------
4098 get_name_interned_utility_code = [
4099 """
4100 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
4101 ""","""
4102 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
4103 PyObject *result;
4104 result = PyObject_GetAttr(dict, name);
4105 if (!result)
4106 PyErr_SetObject(PyExc_NameError, name);
4107 return result;
4109 """]
4111 #------------------------------------------------------------------------------------
4113 import_utility_code = [
4114 """
4115 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
4116 ""","""
4117 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
4118 PyObject *__import__ = 0;
4119 PyObject *empty_list = 0;
4120 PyObject *module = 0;
4121 PyObject *global_dict = 0;
4122 PyObject *empty_dict = 0;
4123 PyObject *list;
4124 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
4125 if (!__import__)
4126 goto bad;
4127 if (from_list)
4128 list = from_list;
4129 else {
4130 empty_list = PyList_New(0);
4131 if (!empty_list)
4132 goto bad;
4133 list = empty_list;
4135 global_dict = PyModule_GetDict(%(GLOBALS)s);
4136 if (!global_dict)
4137 goto bad;
4138 empty_dict = PyDict_New();
4139 if (!empty_dict)
4140 goto bad;
4141 module = PyObject_CallFunction(__import__, "OOOO",
4142 name, global_dict, empty_dict, list);
4143 bad:
4144 Py_XDECREF(empty_list);
4145 Py_XDECREF(__import__);
4146 Py_XDECREF(empty_dict);
4147 return module;
4149 """ % {
4150 "BUILTINS": Naming.builtins_cname,
4151 "GLOBALS": Naming.module_cname,
4152 }]
4154 #------------------------------------------------------------------------------------
4156 get_exception_utility_code = [
4157 """
4158 static PyObject *__Pyx_GetExcValue(void); /*proto*/
4159 ""","""
4160 static PyObject *__Pyx_GetExcValue(void) {
4161 PyObject *type = 0, *value = 0, *tb = 0;
4162 PyObject *tmp_type, *tmp_value, *tmp_tb;
4163 PyObject *result = 0;
4164 PyThreadState *tstate = PyThreadState_Get();
4165 PyErr_Fetch(&type, &value, &tb);
4166 PyErr_NormalizeException(&type, &value, &tb);
4167 if (PyErr_Occurred())
4168 goto bad;
4169 if (!value) {
4170 value = Py_None;
4171 Py_INCREF(value);
4173 tmp_type = tstate->exc_type;
4174 tmp_value = tstate->exc_value;
4175 tmp_tb = tstate->exc_traceback;
4176 tstate->exc_type = type;
4177 tstate->exc_value = value;
4178 tstate->exc_traceback = tb;
4179 /* Make sure tstate is in a consistent state when we XDECREF
4180 these objects (XDECREF may run arbitrary code). */
4181 Py_XDECREF(tmp_type);
4182 Py_XDECREF(tmp_value);
4183 Py_XDECREF(tmp_tb);
4184 result = value;
4185 Py_XINCREF(result);
4186 type = 0;
4187 value = 0;
4188 tb = 0;
4189 bad:
4190 Py_XDECREF(type);
4191 Py_XDECREF(value);
4192 Py_XDECREF(tb);
4193 return result;
4195 """]
4197 #------------------------------------------------------------------------------------
4199 unpacking_utility_code = [
4200 """
4201 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
4202 static int __Pyx_EndUnpack(PyObject *); /*proto*/
4203 ""","""
4204 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
4205 PyObject *item;
4206 if (!(item = PyIter_Next(iter))) {
4207 if (!PyErr_Occurred()) {
4208 PyErr_Format(PyExc_ValueError,
4209 #if PY_VERSION_HEX < 0x02050000
4210 "need more than %d values to unpack", (int)index);
4211 #else
4212 "need more than %zd values to unpack", index);
4213 #endif
4216 return item;
4219 static int __Pyx_EndUnpack(PyObject *iter) {
4220 PyObject *item;
4221 if ((item = PyIter_Next(iter))) {
4222 Py_DECREF(item);
4223 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
4224 return -1;
4226 else if (!PyErr_Occurred())
4227 return 0;
4228 else
4229 return -1;
4231 """]
4233 #------------------------------------------------------------------------------------
4235 type_test_utility_code = [
4236 """
4237 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
4238 ""","""
4239 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
4240 if (!type) {
4241 PyErr_Format(PyExc_SystemError, "Missing type object");
4242 return 0;
4244 if (obj == Py_None || PyObject_TypeCheck(obj, type))
4245 return 1;
4246 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
4247 Py_TYPE(obj)->tp_name, type->tp_name);
4248 return 0;
4250 """]
4252 #------------------------------------------------------------------------------------
4254 create_class_utility_code = [
4255 """
4256 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
4257 ""","""
4258 static PyObject *__Pyx_CreateClass(
4259 PyObject *bases, PyObject *dict, PyObject *name, char *modname)
4261 PyObject *py_modname;
4262 PyObject *result = 0;
4264 #if PY_MAJOR_VERSION < 3
4265 py_modname = PyString_FromString(modname);
4266 #else
4267 py_modname = PyUnicode_FromString(modname);
4268 #endif
4269 if (!py_modname)
4270 goto bad;
4271 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
4272 goto bad;
4273 #if PY_MAJOR_VERSION < 3
4274 result = PyClass_New(bases, dict, name);
4275 #else
4276 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
4277 #endif
4278 bad:
4279 Py_XDECREF(py_modname);
4280 return result;
4282 """]
4284 #------------------------------------------------------------------------------------
4286 cpp_exception_utility_code = [
4287 """
4288 #ifndef __Pyx_CppExn2PyErr
4289 static void __Pyx_CppExn2PyErr() {
4290 try {
4291 if (PyErr_Occurred())
4292 ; // let the latest Python exn pass through and ignore the current one
4293 else
4294 throw;
4295 } catch (const std::out_of_range& exn) {
4296 // catch out_of_range explicitly so the proper Python exn may be raised
4297 PyErr_SetString(PyExc_IndexError, exn.what());
4298 } catch (const std::exception& exn) {
4299 PyErr_SetString(PyExc_RuntimeError, exn.what());
4301 catch (...)
4303 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
4306 #endif
4307 """,""]
4309 #------------------------------------------------------------------------------------
4311 append_utility_code = [
4312 """
4313 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
4314 if (likely(PyList_CheckExact(L))) {
4315 if (PyList_Append(L, x) < 0) return NULL;
4316 Py_INCREF(Py_None);
4317 return Py_None; // this is just to have an accurate signature
4319 else {
4320 return PyObject_CallMethod(L, "append", "(O)", x);
4323 """,""
4326 #------------------------------------------------------------------------------------
4328 type_cache_invalidation_code = [
4329 """
4330 #if PY_VERSION_HEX >= 0x02060000
4331 /* #define __Pyx_TypeModified(t) PyType_Modified(t) */ /* Py3.0beta1 */
4332 static void __Pyx_TypeModified(PyTypeObject* type); /*proto*/
4333 #else
4334 #define __Pyx_TypeModified(t)
4335 #endif
4336 ""","""
4337 #if PY_VERSION_HEX >= 0x02060000
4338 /* copied from typeobject.c in Python 3.0a5 */
4339 static void __Pyx_TypeModified(PyTypeObject* type) {
4340 PyObject *raw, *ref;
4341 Py_ssize_t i, n;
4343 if (!PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))
4344 return;
4346 raw = type->tp_subclasses;
4347 if (raw != NULL) {
4348 n = PyList_GET_SIZE(raw);
4349 for (i = 0; i < n; i++) {
4350 ref = PyList_GET_ITEM(raw, i);
4351 ref = PyWeakref_GET_OBJECT(ref);
4352 if (ref != Py_None) {
4353 __Pyx_TypeModified((PyTypeObject *)ref);
4357 type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
4359 #endif
4360 """
4363 #------------------------------------------------------------------------------------
4365 # If the is_unsigned flag is set, we need to do some extra work to make
4366 # sure the index doesn't become negative.
4368 getitem_int_utility_code = [
4369 """
4370 static INLINE PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
4371 PyObject *r;
4372 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
4373 r = PyList_GET_ITEM(o, i);
4374 Py_INCREF(r);
4376 else if (PyTuple_CheckExact(o) && 0 <= i && i < PyTuple_GET_SIZE(o)) {
4377 r = PyTuple_GET_ITEM(o, i);
4378 Py_INCREF(r);
4380 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0) || !is_unsigned))
4381 r = PySequence_GetItem(o, i);
4382 else {
4383 PyObject *j = (likely(i >= 0) || !is_unsigned) ? PyInt_FromLong(i) : PyLong_FromUnsignedLongLong((sizeof(unsigned long long) > sizeof(Py_ssize_t) ? (1ULL << (sizeof(Py_ssize_t)*8)) : 0) + i);
4384 if (!j)
4385 return 0;
4386 r = PyObject_GetItem(o, j);
4387 Py_DECREF(j);
4389 return r;
4391 """,
4392 """
4393 """]
4395 #------------------------------------------------------------------------------------
4397 setitem_int_utility_code = [
4398 """
4399 static INLINE int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v, int is_unsigned) {
4400 int r;
4401 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
4402 Py_DECREF(PyList_GET_ITEM(o, i));
4403 Py_INCREF(v);
4404 PyList_SET_ITEM(o, i, v);
4405 return 1;
4407 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
4408 r = PySequence_SetItem(o, i, v);
4409 else {
4410 PyObject *j = (likely(i >= 0) || !is_unsigned) ? PyInt_FromLong(i) : PyLong_FromUnsignedLongLong((sizeof(unsigned long long) > sizeof(Py_ssize_t) ? (1ULL << (sizeof(Py_ssize_t)*8)) : 0) + i);
4411 if (!j)
4412 return -1;
4413 r = PyObject_SetItem(o, j, v);
4414 Py_DECREF(j);
4416 return r;
4418 """,
4419 """
4420 """]