Cython has moved to github.

cython-devel

view Cython/Compiler/ExprNodes.py @ 1174:eedadcc8c22c

Use method to get result code, deferred to code generation time.
author Robert Bradshaw <robertwb@math.washington.edu>
date Tue Sep 23 13:48:06 2008 -0700 (3 years ago)
parents 947f6697b088
children 06bcb482828a 28b0311d6bff 6f928ec0df43
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 StringEncoding
10 import Naming
11 from Nodes import Node
12 import PyrexTypes
13 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
14 from Builtin import list_type, tuple_type, dict_type, unicode_type
15 import Symtab
16 import Options
17 from Annotate import AnnotationItem
19 from Cython.Debugging import print_call_chain
20 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
21 debug_coercion
24 class ExprNode(Node):
25 # subexprs [string] Class var holding names of subexpr node attrs
26 # type PyrexType Type of the result
27 # result_code string Code fragment
28 # result_ctype string C type of result_code if different from type
29 # is_temp boolean Result is in a temporary variable
30 # is_sequence_constructor
31 # boolean Is a list or tuple constructor expression
32 # saved_subexpr_nodes
33 # [ExprNode or [ExprNode or None] or None]
34 # Cached result of subexpr_nodes()
36 result_ctype = None
37 type = None
39 # The Analyse Expressions phase for expressions is split
40 # into two sub-phases:
41 #
42 # Analyse Types
43 # Determines the result type of the expression based
44 # on the types of its sub-expressions, and inserts
45 # coercion nodes into the expression tree where needed.
46 # Marks nodes which will need to have temporary variables
47 # allocated.
48 #
49 # Allocate Temps
50 # Allocates temporary variables where needed, and fills
51 # in the result_code field of each node.
52 #
53 # ExprNode provides some convenience routines which
54 # perform both of the above phases. These should only
55 # be called from statement nodes, and only when no
56 # coercion nodes need to be added around the expression
57 # being analysed. In that case, the above two phases
58 # should be invoked separately.
59 #
60 # Framework code in ExprNode provides much of the common
61 # processing for the various phases. It makes use of the
62 # 'subexprs' class attribute of ExprNodes, which should
63 # contain a list of the names of attributes which can
64 # hold sub-nodes or sequences of sub-nodes.
65 #
66 # The framework makes use of a number of abstract methods.
67 # Their responsibilities are as follows.
68 #
69 # Declaration Analysis phase
70 #
71 # analyse_target_declaration
72 # Called during the Analyse Declarations phase to analyse
73 # the LHS of an assignment or argument of a del statement.
74 # Nodes which cannot be the LHS of an assignment need not
75 # implement it.
76 #
77 # Expression Analysis phase
78 #
79 # analyse_types
80 # - Call analyse_types on all sub-expressions.
81 # - Check operand types, and wrap coercion nodes around
82 # sub-expressions where needed.
83 # - Set the type of this node.
84 # - If a temporary variable will be required for the
85 # result, set the is_temp flag of this node.
86 #
87 # analyse_target_types
88 # Called during the Analyse Types phase to analyse
89 # the LHS of an assignment or argument of a del
90 # statement. Similar responsibilities to analyse_types.
91 #
92 # allocate_temps
93 # - Call allocate_temps for all sub-nodes.
94 # - Call allocate_temp for this node.
95 # - If a temporary was allocated, call release_temp on
96 # all sub-expressions.
97 #
98 # allocate_target_temps
99 # - Call allocate_temps on sub-nodes and allocate any other
100 # temps used during assignment.
101 # - Fill in result_code with a C lvalue if needed.
102 # - If a rhs node is supplied, call release_temp on it.
103 # - Call release_temp on sub-nodes and release any other
104 # temps used during assignment.
105 #
106 # target_code
107 # Called by the default implementation of allocate_target_temps.
108 # Should return a C lvalue for assigning to the node. The default
109 # implementation calls calculate_result_code.
110 #
111 # check_const
112 # - Check that this node and its subnodes form a
113 # legal constant expression. If so, do nothing,
114 # otherwise call not_const.
115 #
116 # The default implementation of check_const
117 # assumes that the expression is not constant.
118 #
119 # check_const_addr
120 # - Same as check_const, except check that the
121 # expression is a C lvalue whose address is
122 # constant. Otherwise, call addr_not_const.
123 #
124 # The default implementation of calc_const_addr
125 # assumes that the expression is not a constant
126 # lvalue.
127 #
128 # Code Generation phase
129 #
130 # generate_evaluation_code
131 # - Call generate_evaluation_code for sub-expressions.
132 # - Perform the functions of generate_result_code
133 # (see below).
134 # - If result is temporary, call generate_disposal_code
135 # on all sub-expressions.
136 #
137 # A default implementation of generate_evaluation_code
138 # is provided which uses the following abstract methods:
139 #
140 # generate_result_code
141 # - Generate any C statements necessary to calculate
142 # the result of this node from the results of its
143 # sub-expressions.
144 #
145 # calculate_result_code
146 # - Should return a C code fragment evaluating to the
147 # result. This is only called when the result is not
148 # a temporary.
149 #
150 # generate_assignment_code
151 # Called on the LHS of an assignment.
152 # - Call generate_evaluation_code for sub-expressions.
153 # - Generate code to perform the assignment.
154 # - If the assignment absorbed a reference, call
155 # generate_post_assignment_code on the RHS,
156 # otherwise call generate_disposal_code on it.
157 #
158 # generate_deletion_code
159 # Called on an argument of a del statement.
160 # - Call generate_evaluation_code for sub-expressions.
161 # - Generate code to perform the deletion.
162 # - Call generate_disposal_code on all sub-expressions.
163 #
164 #
166 is_sequence_constructor = 0
167 is_attribute = 0
169 saved_subexpr_nodes = None
170 is_temp = 0
172 def get_child_attrs(self):
173 return self.subexprs
174 child_attrs = property(fget=get_child_attrs)
176 def not_implemented(self, method_name):
177 print_call_chain(method_name, "not implemented") ###
178 raise InternalError(
179 "%s.%s not implemented" %
180 (self.__class__.__name__, method_name))
182 def is_lvalue(self):
183 return 0
185 def is_ephemeral(self):
186 # An ephemeral node is one whose result is in
187 # a Python temporary and we suspect there are no
188 # other references to it. Certain operations are
189 # disallowed on such values, since they are
190 # likely to result in a dangling pointer.
191 return self.type.is_pyobject and self.is_temp
193 def subexpr_nodes(self):
194 # Extract a list of subexpression nodes based
195 # on the contents of the subexprs class attribute.
196 if self.saved_subexpr_nodes is None:
197 nodes = []
198 for name in self.subexprs:
199 item = getattr(self, name)
200 if item:
201 if isinstance(item, ExprNode):
202 nodes.append(item)
203 else:
204 nodes.extend(item)
205 self.saved_subexpr_nodes = nodes
206 return self.saved_subexpr_nodes
208 def result(self):
209 if self.is_temp:
210 return self.result_code
211 else:
212 return self.calculate_result_code()
214 def result_as(self, type = None):
215 # Return the result code cast to the specified C type.
216 return typecast(type, self.ctype(), self.result())
218 def py_result(self):
219 # Return the result code cast to PyObject *.
220 return self.result_as(py_object_type)
222 def ctype(self):
223 # Return the native C type of the result (i.e. the
224 # C type of the result_code expression).
225 return self.result_ctype or self.type
227 def compile_time_value(self, denv):
228 # Return value of compile-time expression, or report error.
229 error(self.pos, "Invalid compile-time expression")
231 def compile_time_value_error(self, e):
232 error(self.pos, "Error in compile-time expression: %s: %s" % (
233 e.__class__.__name__, e))
235 # ------------- Declaration Analysis ----------------
237 def analyse_target_declaration(self, env):
238 error(self.pos, "Cannot assign to or delete this")
240 # ------------- Expression Analysis ----------------
242 def analyse_const_expression(self, env):
243 # Called during the analyse_declarations phase of a
244 # constant expression. Analyses the expression's type,
245 # checks whether it is a legal const expression,
246 # and determines its value.
247 self.analyse_types(env)
248 self.allocate_temps(env)
249 self.check_const()
251 def analyse_expressions(self, env):
252 # Convenience routine performing both the Type
253 # Analysis and Temp Allocation phases for a whole
254 # expression.
255 self.analyse_types(env)
256 self.allocate_temps(env)
258 def analyse_target_expression(self, env, rhs):
259 # Convenience routine performing both the Type
260 # Analysis and Temp Allocation phases for the LHS of
261 # an assignment.
262 self.analyse_target_types(env)
263 self.allocate_target_temps(env, rhs)
265 def analyse_boolean_expression(self, env):
266 # Analyse expression and coerce to a boolean.
267 self.analyse_types(env)
268 bool = self.coerce_to_boolean(env)
269 bool.allocate_temps(env)
270 return bool
272 def analyse_temp_boolean_expression(self, env):
273 # Analyse boolean expression and coerce result into
274 # a temporary. This is used when a branch is to be
275 # performed on the result and we won't have an
276 # opportunity to ensure disposal code is executed
277 # afterwards. By forcing the result into a temporary,
278 # we ensure that all disposal has been done by the
279 # time we get the result.
280 self.analyse_types(env)
281 bool = self.coerce_to_boolean(env)
282 temp_bool = bool.coerce_to_temp(env)
283 temp_bool.allocate_temps(env)
284 return temp_bool
286 # --------------- Type Analysis ------------------
288 def analyse_as_module(self, env):
289 # If this node can be interpreted as a reference to a
290 # cimported module, return its scope, else None.
291 return None
293 def analyse_as_extension_type(self, env):
294 # If this node can be interpreted as a reference to an
295 # extension type, return its type, else None.
296 return None
298 def analyse_types(self, env):
299 self.not_implemented("analyse_types")
301 def analyse_target_types(self, env):
302 self.analyse_types(env)
304 def gil_assignment_check(self, env):
305 if env.nogil and self.type.is_pyobject:
306 error(self.pos, "Assignment of Python object not allowed without gil")
308 def check_const(self):
309 self.not_const()
311 def not_const(self):
312 error(self.pos, "Not allowed in a constant expression")
314 def check_const_addr(self):
315 self.addr_not_const()
317 def addr_not_const(self):
318 error(self.pos, "Address is not constant")
320 def gil_check(self, env):
321 if env.nogil and self.type.is_pyobject:
322 self.gil_error()
324 # ----------------- Result Allocation -----------------
326 def result_in_temp(self):
327 # Return true if result is in a temporary owned by
328 # this node or one of its subexpressions. Overridden
329 # by certain nodes which can share the result of
330 # a subnode.
331 return self.is_temp
333 def allocate_target_temps(self, env, rhs):
334 # Perform temp allocation for the LHS of an assignment.
335 if debug_temp_alloc:
336 print("%s Allocating target temps" % self)
337 self.allocate_subexpr_temps(env)
338 self.result_code = self.target_code()
339 if rhs:
340 rhs.release_temp(env)
341 self.release_subexpr_temps(env)
343 def allocate_temps(self, env, result = None):
344 # Allocate temporary variables for this node and
345 # all its sub-expressions. If a result is specified,
346 # this must be a temp node and the specified variable
347 # is used as the result instead of allocating a new
348 # one.
349 if debug_temp_alloc:
350 print("%s Allocating temps" % self)
351 self.allocate_subexpr_temps(env)
352 self.allocate_temp(env, result)
353 if self.is_temp:
354 self.release_subexpr_temps(env)
356 def allocate_subexpr_temps(self, env):
357 # Allocate temporary variables for all sub-expressions
358 # of this node.
359 if debug_temp_alloc:
360 print("%s Allocating temps for: %s" % (self, self.subexprs))
361 for node in self.subexpr_nodes():
362 if node:
363 if debug_temp_alloc:
364 print("%s Allocating temps for %s" % (self, node))
365 node.allocate_temps(env)
367 def allocate_temp(self, env, result = None):
368 # If this node requires a temporary variable for its
369 # result, allocate one, otherwise set the result to
370 # a C code fragment. If a result is specified,
371 # this must be a temp node and the specified variable
372 # is used as the result instead of allocating a new
373 # one.
374 if debug_temp_alloc:
375 print("%s Allocating temp" % self)
376 if result:
377 if not self.is_temp:
378 raise InternalError("Result forced on non-temp node")
379 self.result_code = result
380 elif self.is_temp:
381 type = self.type
382 if not type.is_void:
383 if type.is_pyobject:
384 type = PyrexTypes.py_object_type
385 self.result_code = env.allocate_temp(type)
386 else:
387 self.result_code = None
388 if debug_temp_alloc:
389 print("%s Allocated result %s" % (self, self.result_code))
391 def target_code(self):
392 # Return code fragment for use as LHS of a C assignment.
393 return self.calculate_result_code()
395 def calculate_result_code(self):
396 self.not_implemented("calculate_result_code")
398 # def release_target_temp(self, env):
399 # # Release temporaries used by LHS of an assignment.
400 # self.release_subexpr_temps(env)
402 def release_temp(self, env):
403 # If this node owns a temporary result, release it,
404 # otherwise release results of its sub-expressions.
405 if self.is_temp:
406 if debug_temp_alloc:
407 print("%s Releasing result %s" % (self, self.result_code))
408 env.release_temp(self.result_code)
409 else:
410 self.release_subexpr_temps(env)
412 def release_subexpr_temps(self, env):
413 # Release the results of all sub-expressions of
414 # this node.
415 for node in self.subexpr_nodes():
416 if node:
417 node.release_temp(env)
419 # ---------------- Code Generation -----------------
421 def make_owned_reference(self, code):
422 # If result is a pyobject, make sure we own
423 # a reference to it.
424 if self.type.is_pyobject and not self.result_in_temp():
425 code.put_incref(self.result(), self.ctype())
427 def generate_evaluation_code(self, code):
428 code.mark_pos(self.pos)
429 # Generate code to evaluate this node and
430 # its sub-expressions, and dispose of any
431 # temporary results of its sub-expressions.
432 self.generate_subexpr_evaluation_code(code)
433 self.generate_result_code(code)
434 if self.is_temp:
435 self.generate_subexpr_disposal_code(code)
437 def generate_subexpr_evaluation_code(self, code):
438 for node in self.subexpr_nodes():
439 node.generate_evaluation_code(code)
441 def generate_result_code(self, code):
442 self.not_implemented("generate_result_code")
444 def generate_disposal_code(self, code):
445 # If necessary, generate code to dispose of
446 # temporary Python reference.
447 if self.is_temp:
448 if self.type.is_pyobject:
449 code.put_decref_clear(self.result(), self.ctype())
450 else:
451 self.generate_subexpr_disposal_code(code)
453 def generate_subexpr_disposal_code(self, code):
454 # Generate code to dispose of temporary results
455 # of all sub-expressions.
456 for node in self.subexpr_nodes():
457 node.generate_disposal_code(code)
459 def generate_post_assignment_code(self, code):
460 # Same as generate_disposal_code except that
461 # assignment will have absorbed a reference to
462 # the result if it is a Python object.
463 if self.is_temp:
464 if self.type.is_pyobject:
465 code.putln("%s = 0;" % self.result())
466 else:
467 self.generate_subexpr_disposal_code(code)
469 def generate_assignment_code(self, rhs, code):
470 # Stub method for nodes which are not legal as
471 # the LHS of an assignment. An error will have
472 # been reported earlier.
473 pass
475 def generate_deletion_code(self, code):
476 # Stub method for nodes that are not legal as
477 # the argument of a del statement. An error
478 # will have been reported earlier.
479 pass
481 # ---------------- Annotation ---------------------
483 def annotate(self, code):
484 for node in self.subexpr_nodes():
485 node.annotate(code)
487 # ----------------- Coercion ----------------------
489 def coerce_to(self, dst_type, env):
490 # Coerce the result so that it can be assigned to
491 # something of type dst_type. If processing is necessary,
492 # wraps this node in a coercion node and returns that.
493 # Otherwise, returns this node unchanged.
494 #
495 # This method is called during the analyse_expressions
496 # phase of the src_node's processing.
497 src = self
498 src_type = self.type
499 src_is_py_type = src_type.is_pyobject
500 dst_is_py_type = dst_type.is_pyobject
502 if dst_type.is_pyobject:
503 if not src.type.is_pyobject:
504 src = CoerceToPyTypeNode(src, env)
505 if not src.type.subtype_of(dst_type):
506 if not isinstance(src, NoneNode):
507 src = PyTypeTestNode(src, dst_type, env)
508 elif src.type.is_pyobject:
509 src = CoerceFromPyTypeNode(dst_type, src, env)
510 else: # neither src nor dst are py types
511 # Added the string comparison, since for c types that
512 # is enough, but Cython gets confused when the types are
513 # in different files.
514 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
515 error(self.pos, "Cannot assign type '%s' to '%s'" %
516 (src.type, dst_type))
517 return src
519 def coerce_to_pyobject(self, env):
520 return self.coerce_to(PyrexTypes.py_object_type, env)
522 def coerce_to_boolean(self, env):
523 # Coerce result to something acceptable as
524 # a boolean value.
525 type = self.type
526 if type.is_pyobject or type.is_ptr or type.is_float:
527 return CoerceToBooleanNode(self, env)
528 else:
529 if not type.is_int and not type.is_error:
530 error(self.pos,
531 "Type '%s' not acceptable as a boolean" % type)
532 return self
534 def coerce_to_integer(self, env):
535 # If not already some C integer type, coerce to longint.
536 if self.type.is_int:
537 return self
538 else:
539 return self.coerce_to(PyrexTypes.c_long_type, env)
541 def coerce_to_temp(self, env):
542 # Ensure that the result is in a temporary.
543 if self.result_in_temp():
544 return self
545 else:
546 return CoerceToTempNode(self, env)
548 def coerce_to_simple(self, env):
549 # Ensure that the result is simple (see is_simple).
550 if self.is_simple():
551 return self
552 else:
553 return self.coerce_to_temp(env)
555 def is_simple(self):
556 # A node is simple if its result is something that can
557 # be referred to without performing any operations, e.g.
558 # a constant, local var, C global var, struct member
559 # reference, or temporary.
560 return self.result_in_temp()
563 class AtomicExprNode(ExprNode):
564 # Abstract base class for expression nodes which have
565 # no sub-expressions.
567 subexprs = []
570 class PyConstNode(AtomicExprNode):
571 # Abstract base class for constant Python values.
573 is_literal = 1
575 def is_simple(self):
576 return 1
578 def analyse_types(self, env):
579 self.type = py_object_type
581 def calculate_result_code(self):
582 return self.value
584 def generate_result_code(self, code):
585 pass
588 class NoneNode(PyConstNode):
589 # The constant value None
591 value = "Py_None"
593 def compile_time_value(self, denv):
594 return None
596 class EllipsisNode(PyConstNode):
597 # '...' in a subscript list.
599 value = "Py_Ellipsis"
601 def compile_time_value(self, denv):
602 return Ellipsis
605 class ConstNode(AtomicExprNode):
606 # Abstract base type for literal constant nodes.
607 #
608 # value string C code fragment
610 is_literal = 1
612 def is_simple(self):
613 return 1
615 def analyse_types(self, env):
616 pass # Types are held in class variables
618 def check_const(self):
619 pass
621 def calculate_result_code(self):
622 return str(self.value)
624 def generate_result_code(self, code):
625 pass
628 class BoolNode(ConstNode):
629 type = PyrexTypes.c_bint_type
630 # The constant value True or False
632 def compile_time_value(self, denv):
633 return self.value
635 def calculate_result_code(self):
636 return str(int(self.value))
638 class NullNode(ConstNode):
639 type = PyrexTypes.c_null_ptr_type
640 value = "NULL"
643 class CharNode(ConstNode):
644 type = PyrexTypes.c_char_type
646 def compile_time_value(self, denv):
647 return ord(self.value)
649 def calculate_result_code(self):
650 return "'%s'" % StringEncoding.escape_character(self.value)
653 class IntNode(ConstNode):
655 # unsigned "" or "U"
656 # longness "" or "L" or "LL"
658 unsigned = ""
659 longness = ""
660 type = PyrexTypes.c_long_type
662 def coerce_to(self, dst_type, env):
663 # Arrange for a Python version of the string to be pre-allocated
664 # when coercing to a Python type.
665 if dst_type.is_pyobject:
666 self.entry = env.get_py_num(self.value, self.longness)
667 self.type = PyrexTypes.py_object_type
668 # We still need to perform normal coerce_to processing on the
669 # result, because we might be coercing to an extension type,
670 # in which case a type test node will be needed.
671 return ConstNode.coerce_to(self, dst_type, env)
673 def calculate_result_code(self):
674 if self.type.is_pyobject:
675 return self.entry.cname
676 else:
677 return str(self.value) + self.unsigned + self.longness
679 def compile_time_value(self, denv):
680 return int(self.value, 0)
683 class FloatNode(ConstNode):
684 type = PyrexTypes.c_double_type
686 def compile_time_value(self, denv):
687 return float(self.value)
689 def calculate_result_code(self):
690 strval = str(self.value)
691 if strval == 'nan':
692 return "(Py_HUGE_VAL * 0)"
693 elif strval == 'inf':
694 return "Py_HUGE_VAL"
695 elif strval == '-inf':
696 return "(-Py_HUGE_VAL)"
697 else:
698 return strval
701 class StringNode(ConstNode):
702 # entry Symtab.Entry
704 type = PyrexTypes.c_char_ptr_type
706 def compile_time_value(self, denv):
707 return self.value
709 def analyse_types(self, env):
710 self.entry = env.add_string_const(self.value)
712 def coerce_to(self, dst_type, env):
713 if dst_type.is_int:
714 if not self.type.is_pyobject and len(self.entry.init) == 1:
715 return CharNode(self.pos, value=self.value)
716 else:
717 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
718 return self
719 # Arrange for a Python version of the string to be pre-allocated
720 # when coercing to a Python type.
721 if dst_type.is_pyobject and not self.type.is_pyobject:
722 node = self.as_py_string_node(env)
723 else:
724 node = self
725 # We still need to perform normal coerce_to processing on the
726 # result, because we might be coercing to an extension type,
727 # in which case a type test node will be needed.
728 return ConstNode.coerce_to(node, dst_type, env)
730 def as_py_string_node(self, env):
731 # Return a new StringNode with the same entry as this node
732 # but whose type is a Python type instead of a C type.
733 entry = self.entry
734 env.add_py_string(entry)
735 return StringNode(self.pos, entry = entry, type = py_object_type)
737 def calculate_result_code(self):
738 if self.type.is_pyobject:
739 return self.entry.pystring_cname
740 else:
741 return self.entry.cname
744 class UnicodeNode(PyConstNode):
745 # entry Symtab.Entry
747 type = unicode_type
749 def analyse_types(self, env):
750 self.entry = env.add_string_const(self.value)
751 env.add_py_string(self.entry)
753 def calculate_result_code(self):
754 return self.entry.pystring_cname
756 def _coerce_to(self, dst_type, env):
757 if not dst_type.is_pyobject:
758 node = StringNode(self.pos, entry = entry, type = py_object_type)
759 return ConstNode.coerce_to(node, dst_type, env)
760 else:
761 return self
762 # We still need to perform normal coerce_to processing on the
763 # result, because we might be coercing to an extension type,
764 # in which case a type test node will be needed.
766 def compile_time_value(self, env):
767 return self.value
770 class IdentifierStringNode(ConstNode):
771 # A Python string that behaves like an identifier, e.g. for
772 # keyword arguments in a call, or for imported names
773 type = PyrexTypes.py_object_type
775 def analyse_types(self, env):
776 self.cname = env.intern_identifier(self.value)
778 def calculate_result_code(self):
779 return self.cname
782 class LongNode(AtomicExprNode):
783 # Python long integer literal
784 #
785 # value string
787 def compile_time_value(self, denv):
788 return long(self.value)
790 gil_message = "Constructing Python long int"
792 def analyse_types(self, env):
793 self.type = py_object_type
794 self.gil_check(env)
795 self.is_temp = 1
797 gil_message = "Constructing Python long int"
799 def generate_evaluation_code(self, code):
800 code.putln(
801 '%s = PyLong_FromString("%s", 0, 0); %s' % (
802 self.result(),
803 self.value,
804 code.error_goto_if_null(self.result(), self.pos)))
807 class ImagNode(AtomicExprNode):
808 # Imaginary number literal
809 #
810 # value float imaginary part
812 def compile_time_value(self, denv):
813 return complex(0.0, self.value)
815 def analyse_types(self, env):
816 self.type = py_object_type
817 self.gil_check(env)
818 self.is_temp = 1
820 gil_message = "Constructing complex number"
822 def generate_evaluation_code(self, code):
823 code.putln(
824 "%s = PyComplex_FromDoubles(0.0, %s); %s" % (
825 self.result(),
826 self.value,
827 code.error_goto_if_null(self.result(), self.pos)))
830 class NameNode(AtomicExprNode):
831 # Reference to a local or global variable name.
832 #
833 # name string Python name of the variable
834 #
835 # entry Entry Symbol table entry
836 # interned_cname string
838 is_name = 1
839 skip_assignment_decref = False
840 entry = None
842 def create_analysed_rvalue(pos, env, entry):
843 node = NameNode(pos)
844 node.analyse_types(env, entry=entry)
845 return node
847 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
849 def compile_time_value(self, denv):
850 try:
851 return denv.lookup(self.name)
852 except KeyError:
853 error(self.pos, "Compile-time name '%s' not defined" % self.name)
855 def coerce_to(self, dst_type, env):
856 # If coercing to a generic pyobject and this is a builtin
857 # C function with a Python equivalent, manufacture a NameNode
858 # referring to the Python builtin.
859 #print "NameNode.coerce_to:", self.name, dst_type ###
860 if dst_type is py_object_type:
861 entry = self.entry
862 if entry and entry.is_cfunction:
863 var_entry = entry.as_variable
864 if var_entry:
865 if var_entry.is_builtin and Options.cache_builtins:
866 var_entry = env.declare_builtin(var_entry.name, self.pos)
867 node = NameNode(self.pos, name = self.name)
868 node.entry = var_entry
869 node.analyse_rvalue_entry(env)
870 return node
871 return AtomicExprNode.coerce_to(self, dst_type, env)
873 def analyse_as_module(self, env):
874 # Try to interpret this as a reference to a cimported module.
875 # Returns the module scope, or None.
876 entry = self.entry
877 if not entry:
878 entry = env.lookup(self.name)
879 if entry and entry.as_module:
880 return entry.as_module
881 return None
883 def analyse_as_extension_type(self, env):
884 # Try to interpret this as a reference to an extension type.
885 # Returns the extension type, or None.
886 entry = self.entry
887 if not entry:
888 entry = env.lookup(self.name)
889 if entry and entry.is_type and entry.type.is_extension_type:
890 return entry.type
891 else:
892 return None
894 def analyse_target_declaration(self, env):
895 if not self.entry:
896 self.entry = env.lookup_here(self.name)
897 if not self.entry:
898 self.entry = env.declare_var(self.name, py_object_type, self.pos)
899 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
900 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
901 if self.entry.is_declared_generic:
902 self.result_ctype = py_object_type
904 def analyse_types(self, env):
905 if self.entry is None:
906 self.entry = env.lookup(self.name)
907 if not self.entry:
908 self.entry = env.declare_builtin(self.name, self.pos)
909 if not self.entry:
910 self.type = PyrexTypes.error_type
911 return
912 self.analyse_rvalue_entry(env)
914 def analyse_target_types(self, env):
915 self.analyse_entry(env)
916 if not self.is_lvalue():
917 error(self.pos, "Assignment to non-lvalue '%s'"
918 % self.name)
919 self.type = PyrexTypes.error_type
920 self.entry.used = 1
921 if self.entry.type.is_buffer:
922 import Buffer
923 Buffer.used_buffer_aux_vars(self.entry)
925 def analyse_rvalue_entry(self, env):
926 #print "NameNode.analyse_rvalue_entry:", self.name ###
927 #print "Entry:", self.entry.__dict__ ###
928 self.analyse_entry(env)
929 entry = self.entry
930 if entry.is_declared_generic:
931 self.result_ctype = py_object_type
932 if entry.is_pyglobal or entry.is_builtin:
933 if Options.cache_builtins and entry.is_builtin:
934 self.is_temp = 0
935 else:
936 self.is_temp = 1
937 env.use_utility_code(get_name_interned_utility_code)
938 self.gil_check(env)
940 gil_message = "Accessing Python global or builtin"
942 def analyse_entry(self, env):
943 #print "NameNode.analyse_entry:", self.name ###
944 self.check_identifier_kind()
945 entry = self.entry
946 type = entry.type
947 self.type = type
948 if entry.is_pyglobal or entry.is_builtin:
949 assert type.is_pyobject, "Python global or builtin not a Python object"
950 self.interned_cname = self.entry.interned_cname = \
951 env.intern_identifier(self.entry.name)
953 def check_identifier_kind(self):
954 #print "NameNode.check_identifier_kind:", self.entry.name ###
955 #print self.entry.__dict__ ###
956 entry = self.entry
957 #entry.used = 1
958 if not (entry.is_const or entry.is_variable
959 or entry.is_builtin or entry.is_cfunction):
960 if self.entry.as_variable:
961 self.entry = self.entry.as_variable
962 else:
963 error(self.pos,
964 "'%s' is not a constant, variable or function identifier" % self.name)
966 def is_simple(self):
967 # If it's not a C variable, it'll be in a temp.
968 return 1
970 def calculate_target_results(self, env):
971 pass
973 def check_const(self):
974 entry = self.entry
975 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
976 self.not_const()
978 def check_const_addr(self):
979 entry = self.entry
980 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
981 self.addr_not_const()
983 def is_lvalue(self):
984 return self.entry.is_variable and \
985 not self.entry.type.is_array and \
986 not self.entry.is_readonly
988 def is_ephemeral(self):
989 # Name nodes are never ephemeral, even if the
990 # result is in a temporary.
991 return 0
993 def allocate_temp(self, env, result = None):
994 AtomicExprNode.allocate_temp(self, env, result)
995 entry = self.entry
996 if entry:
997 entry.used = 1
998 if entry.type.is_buffer:
999 import Buffer
1000 Buffer.used_buffer_aux_vars(entry)
1001 if entry.utility_code:
1002 env.use_utility_code(entry.utility_code)
1004 def calculate_result_code(self):
1005 entry = self.entry
1006 if not entry:
1007 return "<error>" # There was an error earlier
1008 return entry.cname
1010 def generate_result_code(self, code):
1011 assert hasattr(self, 'entry')
1012 entry = self.entry
1013 if entry is None:
1014 return # There was an error earlier
1015 if entry.is_builtin and Options.cache_builtins:
1016 return # Lookup already cached
1017 elif entry.is_pyglobal or entry.is_builtin:
1018 if entry.is_builtin:
1019 namespace = Naming.builtins_cname
1020 else: # entry.is_pyglobal
1021 namespace = entry.scope.namespace_cname
1022 code.putln(
1023 '%s = __Pyx_GetName(%s, %s); %s' % (
1024 self.result(),
1025 namespace,
1026 self.interned_cname,
1027 code.error_goto_if_null(self.result(), self.pos)))
1028 elif entry.is_local and False:
1029 # control flow not good enough yet
1030 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1031 if assigned is False:
1032 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1033 elif not Options.init_local_none and assigned is None:
1034 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
1035 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1037 def generate_assignment_code(self, rhs, code):
1038 #print "NameNode.generate_assignment_code:", self.name ###
1039 entry = self.entry
1040 if entry is None:
1041 return # There was an error earlier
1043 # is_pyglobal seems to be True for module level-globals only.
1044 # We use this to access class->tp_dict if necessary.
1045 if entry.is_pyglobal:
1046 namespace = self.entry.scope.namespace_cname
1047 if entry.is_member:
1048 # if the entry is a member we have to cheat: SetAttr does not work
1049 # on types, so we create a descriptor which is then added to tp_dict
1050 code.put_error_if_neg(self.pos,
1051 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1052 namespace,
1053 self.interned_cname,
1054 rhs.py_result()))
1055 # in Py2.6+, we need to invalidate the method cache
1056 code.putln("PyType_Modified(%s);" %
1057 entry.scope.parent_type.typeptr_cname)
1058 else:
1059 code.put_error_if_neg(self.pos,
1060 'PyObject_SetAttr(%s, %s, %s)' % (
1061 namespace,
1062 self.interned_cname,
1063 rhs.py_result()))
1064 if debug_disposal_code:
1065 print("NameNode.generate_assignment_code:")
1066 print("...generating disposal code for %s" % rhs)
1067 rhs.generate_disposal_code(code)
1069 else:
1070 if self.type.is_buffer:
1071 # Generate code for doing the buffer release/acquisition.
1072 # This might raise an exception in which case the assignment (done
1073 # below) will not happen.
1075 # The reason this is not in a typetest-like node is because the
1076 # variables that the acquired buffer info is stored to is allocated
1077 # per entry and coupled with it.
1078 self.generate_acquire_buffer(rhs, code)
1080 if self.type.is_pyobject:
1081 rhs.make_owned_reference(code)
1082 #print "NameNode.generate_assignment_code: to", self.name ###
1083 #print "...from", rhs ###
1084 #print "...LHS type", self.type, "ctype", self.ctype() ###
1085 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1086 if not self.skip_assignment_decref:
1087 if entry.is_local and not Options.init_local_none:
1088 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1089 if initalized is True:
1090 code.put_decref(self.result(), self.ctype())
1091 elif initalized is None:
1092 code.put_xdecref(self.result(), self.ctype())
1093 else:
1094 code.put_decref(self.result(), self.ctype())
1095 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1096 if debug_disposal_code:
1097 print("NameNode.generate_assignment_code:")
1098 print("...generating post-assignment code for %s" % rhs)
1099 rhs.generate_post_assignment_code(code)
1101 def generate_acquire_buffer(self, rhs, code):
1102 rhstmp = code.funcstate.allocate_temp(self.entry.type)
1103 buffer_aux = self.entry.buffer_aux
1104 bufstruct = buffer_aux.buffer_info_var.cname
1105 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1107 import Buffer
1108 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1109 is_initialized=not self.skip_assignment_decref,
1110 pos=self.pos, code=code)
1111 code.putln("%s = 0;" % rhstmp)
1112 code.funcstate.release_temp(rhstmp)
1114 def generate_deletion_code(self, code):
1115 if self.entry is None:
1116 return # There was an error earlier
1117 if not self.entry.is_pyglobal:
1118 error(self.pos, "Deletion of local or C global name not supported")
1119 return
1120 code.put_error_if_neg(self.pos,
1121 'PyObject_DelAttrString(%s, "%s")' % (
1122 Naming.module_cname,
1123 self.entry.name))
1125 def annotate(self, code):
1126 if hasattr(self, 'is_called') and self.is_called:
1127 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1128 if self.type.is_pyobject:
1129 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1130 else:
1131 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1133 class BackquoteNode(ExprNode):
1134 # `expr`
1136 # arg ExprNode
1138 subexprs = ['arg']
1140 def analyse_types(self, env):
1141 self.arg.analyse_types(env)
1142 self.arg = self.arg.coerce_to_pyobject(env)
1143 self.type = py_object_type
1144 self.gil_check(env)
1145 self.is_temp = 1
1147 gil_message = "Backquote expression"
1149 def generate_result_code(self, code):
1150 code.putln(
1151 "%s = PyObject_Repr(%s); %s" % (
1152 self.result(),
1153 self.arg.py_result(),
1154 code.error_goto_if_null(self.result(), self.pos)))
1157 class ImportNode(ExprNode):
1158 # Used as part of import statement implementation.
1159 # Implements result =
1160 # __import__(module_name, globals(), None, name_list)
1162 # module_name IdentifierStringNode dotted name of module
1163 # name_list ListNode or None list of names to be imported
1165 subexprs = ['module_name', 'name_list']
1167 def analyse_types(self, env):
1168 self.module_name.analyse_types(env)
1169 self.module_name = self.module_name.coerce_to_pyobject(env)
1170 if self.name_list:
1171 self.name_list.analyse_types(env)
1172 self.type = py_object_type
1173 self.gil_check(env)
1174 self.is_temp = 1
1175 env.use_utility_code(import_utility_code)
1177 gil_message = "Python import"
1179 def generate_result_code(self, code):
1180 if self.name_list:
1181 name_list_code = self.name_list.py_result()
1182 else:
1183 name_list_code = "0"
1184 code.putln(
1185 "%s = __Pyx_Import(%s, %s); %s" % (
1186 self.result(),
1187 self.module_name.py_result(),
1188 name_list_code,
1189 code.error_goto_if_null(self.result(), self.pos)))
1192 class IteratorNode(ExprNode):
1193 # Used as part of for statement implementation.
1194 # Implements result = iter(sequence)
1196 # sequence ExprNode
1198 subexprs = ['sequence']
1200 def analyse_types(self, env):
1201 self.sequence.analyse_types(env)
1202 self.sequence = self.sequence.coerce_to_pyobject(env)
1203 self.type = py_object_type
1204 self.gil_check(env)
1205 self.is_temp = 1
1207 self.counter = TempNode(self.pos, PyrexTypes.c_py_ssize_t_type, env)
1208 self.counter.allocate_temp(env)
1210 gil_message = "Iterating over Python object"
1212 def release_temp(self, env):
1213 env.release_temp(self.result())
1214 self.counter.release_temp(env)
1216 def generate_result_code(self, code):
1217 code.putln(
1218 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1219 self.sequence.py_result(),
1220 self.sequence.py_result()))
1221 code.putln(
1222 "%s = 0; %s = %s; Py_INCREF(%s);" % (
1223 self.counter.result(),
1224 self.result(),
1225 self.sequence.py_result(),
1226 self.result()))
1227 code.putln("} else {")
1228 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1229 self.counter.result(),
1230 self.result(),
1231 self.sequence.py_result(),
1232 code.error_goto_if_null(self.result(), self.pos)))
1233 code.putln("}")
1236 class NextNode(AtomicExprNode):
1237 # Used as part of for statement implementation.
1238 # Implements result = iterator.next()
1239 # Created during analyse_types phase.
1240 # The iterator is not owned by this node.
1242 # iterator ExprNode
1244 def __init__(self, iterator, env):
1245 self.pos = iterator.pos
1246 self.iterator = iterator
1247 self.type = py_object_type
1248 self.is_temp = 1
1250 def generate_result_code(self, code):
1251 for py_type in ["List", "Tuple"]:
1252 code.putln(
1253 "if (likely(Py%s_CheckExact(%s))) {" % (py_type, self.iterator.py_result()))
1254 code.putln(
1255 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1256 self.iterator.counter.result(),
1257 py_type,
1258 self.iterator.py_result()))
1259 code.putln(
1260 "%s = Py%s_GET_ITEM(%s, %s); Py_INCREF(%s); %s++;" % (
1261 self.result(),
1262 py_type,
1263 self.iterator.py_result(),
1264 self.iterator.counter.result(),
1265 self.result(),
1266 self.iterator.counter.result()))
1267 code.put("} else ")
1268 code.putln("{")
1269 code.putln(
1270 "%s = PyIter_Next(%s);" % (
1271 self.result(),
1272 self.iterator.py_result()))
1273 code.putln(
1274 "if (!%s) {" %
1275 self.result())
1276 code.putln(code.error_goto_if_PyErr(self.pos))
1277 code.putln("break;")
1278 code.putln("}")
1279 code.putln("}")
1282 class ExcValueNode(AtomicExprNode):
1283 # Node created during analyse_types phase
1284 # of an ExceptClauseNode to fetch the current
1285 # exception value.
1287 def __init__(self, pos, env, var):
1288 ExprNode.__init__(self, pos)
1289 self.type = py_object_type
1290 self.var = var
1292 def calculate_result_code(self):
1293 return self.var
1295 def generate_result_code(self, code):
1296 pass
1298 def analyse_types(self, env):
1299 pass
1302 class TempNode(AtomicExprNode):
1303 # Node created during analyse_types phase
1304 # of some nodes to hold a temporary value.
1306 def __init__(self, pos, type, env):
1307 ExprNode.__init__(self, pos)
1308 self.type = type
1309 if type.is_pyobject:
1310 self.result_ctype = py_object_type
1311 self.is_temp = 1
1313 def analyse_types(self, env):
1314 return self.type
1316 def generate_result_code(self, code):
1317 pass
1320 class PyTempNode(TempNode):
1321 # TempNode holding a Python value.
1323 def __init__(self, pos, env):
1324 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1327 #-------------------------------------------------------------------
1329 # Trailer nodes
1331 #-------------------------------------------------------------------
1333 class IndexNode(ExprNode):
1334 # Sequence indexing.
1336 # base ExprNode
1337 # index ExprNode
1338 # indices [ExprNode]
1339 # is_buffer_access boolean Whether this is a buffer access.
1341 # indices is used on buffer access, index on non-buffer access.
1342 # The former contains a clean list of index parameters, the
1343 # latter whatever Python object is needed for index access.
1345 subexprs = ['base', 'index', 'indices']
1346 indices = None
1348 def __init__(self, pos, index, *args, **kw):
1349 ExprNode.__init__(self, pos, index=index, *args, **kw)
1350 self._index = index
1352 def compile_time_value(self, denv):
1353 base = self.base.compile_time_value(denv)
1354 index = self.index.compile_time_value(denv)
1355 try:
1356 return base[index]
1357 except Exception, e:
1358 self.compile_time_value_error(e)
1360 def is_ephemeral(self):
1361 return self.base.is_ephemeral()
1363 def analyse_target_declaration(self, env):
1364 pass
1366 def analyse_types(self, env):
1367 self.analyse_base_and_index_types(env, getting = 1)
1369 def analyse_target_types(self, env):
1370 self.analyse_base_and_index_types(env, setting = 1)
1372 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1373 # Note: This might be cleaned up by having IndexNode
1374 # parsed in a saner way and only construct the tuple if
1375 # needed.
1377 # Note that this function must leave IndexNode in a cloneable state.
1378 # For buffers, self.index is packed out on the initial analysis, and
1379 # when cloning self.indices is copied.
1380 self.is_buffer_access = False
1382 self.base.analyse_types(env)
1383 # Handle the case where base is a literal char* (and we expect a string, not an int)
1384 if isinstance(self.base, StringNode):
1385 self.base = self.base.coerce_to_pyobject(env)
1387 skip_child_analysis = False
1388 buffer_access = False
1389 if self.base.type.is_buffer:
1390 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1391 if self.indices:
1392 indices = self.indices
1393 else:
1394 # On cloning, indices is cloned. Otherwise, unpack index into indices
1395 assert not isinstance(self.index, CloneNode)
1396 if isinstance(self.index, TupleNode):
1397 indices = self.index.args
1398 else:
1399 indices = [self.index]
1400 if len(indices) == self.base.type.ndim:
1401 buffer_access = True
1402 skip_child_analysis = True
1403 for x in indices:
1404 x.analyse_types(env)
1405 if not x.type.is_int:
1406 buffer_access = False
1408 if buffer_access:
1409 self.indices = indices
1410 self.index = None
1411 self.type = self.base.type.dtype
1412 self.is_buffer_access = True
1413 self.buffer_type = self.base.entry.type
1415 if getting:
1416 # we only need a temp because result_code isn't refactored to
1417 # generation time, but this seems an ok shortcut to take
1418 self.is_temp = True
1419 if setting:
1420 if not self.base.entry.type.writable:
1421 error(self.pos, "Writing to readonly buffer")
1422 else:
1423 self.base.entry.buffer_aux.writable_needed = True
1424 else:
1425 if isinstance(self.index, TupleNode):
1426 self.index.analyse_types(env, skip_children=skip_child_analysis)
1427 elif not skip_child_analysis:
1428 self.index.analyse_types(env)
1429 if self.base.type.is_pyobject:
1430 if self.index.type.is_int and not self.index.type.is_longlong:
1431 self.original_index_type = self.index.type
1432 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1433 if getting:
1434 env.use_utility_code(getitem_int_utility_code)
1435 if setting:
1436 env.use_utility_code(setitem_int_utility_code)
1437 else:
1438 self.index = self.index.coerce_to_pyobject(env)
1439 self.type = py_object_type
1440 self.gil_check(env)
1441 self.is_temp = 1
1442 else:
1443 if self.base.type.is_ptr or self.base.type.is_array:
1444 self.type = self.base.type.base_type
1445 else:
1446 error(self.pos,
1447 "Attempting to index non-array type '%s'" %
1448 self.base.type)
1449 self.type = PyrexTypes.error_type
1450 if self.index.type.is_pyobject:
1451 self.index = self.index.coerce_to(
1452 PyrexTypes.c_py_ssize_t_type, env)
1453 if not self.index.type.is_int:
1454 error(self.pos,
1455 "Invalid index type '%s'" %
1456 self.index.type)
1458 gil_message = "Indexing Python object"
1460 def check_const_addr(self):
1461 self.base.check_const_addr()
1462 self.index.check_const()
1464 def is_lvalue(self):
1465 return 1
1467 def calculate_result_code(self):
1468 if self.is_buffer_access:
1469 return "<not used>"
1470 else:
1471 return "(%s[%s])" % (
1472 self.base.result(), self.index.result())
1474 def index_unsigned_parameter(self):
1475 if self.index.type.is_int:
1476 if self.original_index_type.signed:
1477 return ", 0"
1478 else:
1479 return ", sizeof(Py_ssize_t) <= sizeof(%s)" % self.original_index_type.declaration_code("")
1480 else:
1481 return ""
1483 def generate_subexpr_evaluation_code(self, code):
1484 self.base.generate_evaluation_code(code)
1485 if not self.indices:
1486 self.index.generate_evaluation_code(code)
1487 else:
1488 for i in self.indices:
1489 i.generate_evaluation_code(code)
1491 def generate_subexpr_disposal_code(self, code):
1492 self.base.generate_disposal_code(code)
1493 if not self.indices:
1494 self.index.generate_disposal_code(code)
1495 else:
1496 for i in self.indices:
1497 i.generate_disposal_code(code)
1499 def generate_result_code(self, code):
1500 if self.is_buffer_access:
1501 ptrcode = self.buffer_lookup_code(code)
1502 code.putln("%s = *%s;" % (
1503 self.result(),
1504 self.buffer_type.buffer_ptr_type.cast_code(ptrcode)))
1505 # Must incref the value we pulled out.
1506 if self.buffer_type.dtype.is_pyobject:
1507 code.putln("Py_INCREF((PyObject*)%s);" % self.result())
1508 elif self.type.is_pyobject:
1509 if self.index.type.is_int:
1510 function = "__Pyx_GetItemInt"
1511 index_code = self.index.result()
1512 else:
1513 function = "PyObject_GetItem"
1514 index_code = self.index.py_result()
1515 sign_code = ""
1516 code.putln(
1517 "%s = %s(%s, %s%s); if (!%s) %s" % (
1518 self.result(),
1519 function,
1520 self.base.py_result(),
1521 index_code,
1522 self.index_unsigned_parameter(),
1523 self.result(),
1524 code.error_goto(self.pos)))
1526 def generate_setitem_code(self, value_code, code):
1527 if self.index.type.is_int:
1528 function = "__Pyx_SetItemInt"
1529 index_code = self.index.result()
1530 else:
1531 function = "PyObject_SetItem"
1532 index_code = self.index.py_result()
1533 code.putln(
1534 "if (%s(%s, %s, %s%s) < 0) %s" % (
1535 function,
1536 self.base.py_result(),
1537 index_code,
1538 value_code,
1539 self.index_unsigned_parameter(),
1540 code.error_goto(self.pos)))
1542 def generate_buffer_setitem_code(self, rhs, code, op=""):
1543 # Used from generate_assignment_code and InPlaceAssignmentNode
1544 ptrexpr = self.buffer_lookup_code(code)
1545 if self.buffer_type.dtype.is_pyobject:
1546 # Must manage refcounts. Decref what is already there
1547 # and incref what we put in.
1548 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type)
1549 if rhs.is_temp:
1550 rhs_code = code.funcstate.allocate_temp(rhs.type)
1551 else:
1552 rhs_code = rhs.result()
1553 code.putln("%s = %s;" % (ptr, ptrexpr))
1554 code.putln("Py_DECREF(*%s); Py_INCREF(%s);" % (
1555 ptr, rhs_code
1556 ))
1557 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1558 if rhs.is_temp:
1559 code.funcstate.release_temp(rhs_code)
1560 code.funcstate.release_temp(ptr)
1561 else:
1562 # Simple case
1563 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1565 def generate_assignment_code(self, rhs, code):
1566 self.generate_subexpr_evaluation_code(code)
1567 if self.is_buffer_access:
1568 self.generate_buffer_setitem_code(rhs, code)
1569 elif self.type.is_pyobject:
1570 self.generate_setitem_code(rhs.py_result(), code)
1571 else:
1572 code.putln(
1573 "%s = %s;" % (
1574 self.result(), rhs.result()))
1575 self.generate_subexpr_disposal_code(code)
1576 rhs.generate_disposal_code(code)
1578 def generate_deletion_code(self, code):
1579 self.generate_subexpr_evaluation_code(code)
1580 #if self.type.is_pyobject:
1581 if self.index.type.is_int:
1582 function = "PySequence_DelItem"
1583 index_code = self.index.result()
1584 else:
1585 function = "PyObject_DelItem"
1586 index_code = self.index.py_result()
1587 code.putln(
1588 "if (%s(%s, %s) < 0) %s" % (
1589 function,
1590 self.base.py_result(),
1591 index_code,
1592 code.error_goto(self.pos)))
1593 self.generate_subexpr_disposal_code(code)
1595 def buffer_lookup_code(self, code):
1596 # Assign indices to temps
1597 index_temps = [code.funcstate.allocate_temp(i.type) for i in self.indices]
1598 for temp, index in zip(index_temps, self.indices):
1599 code.putln("%s = %s;" % (temp, index.result()))
1600 # Generate buffer access code using these temps
1601 import Buffer
1602 # The above could happen because child_attrs is wrong somewhere so that
1603 # options are not propagated.
1604 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1605 index_signeds=[i.type.signed for i in self.indices],
1606 index_cnames=index_temps,
1607 options=code.globalstate.directives,
1608 pos=self.pos, code=code)
1610 class SliceIndexNode(ExprNode):
1611 # 2-element slice indexing
1613 # base ExprNode
1614 # start ExprNode or None
1615 # stop ExprNode or None
1617 subexprs = ['base', 'start', 'stop']
1619 def compile_time_value(self, denv):
1620 base = self.base.compile_time_value(denv)
1621 start = self.start.compile_time_value(denv)
1622 stop = self.stop.compile_time_value(denv)
1623 try:
1624 return base[start:stop]
1625 except Exception, e:
1626 self.compile_time_value_error(e)
1628 def analyse_target_declaration(self, env):
1629 pass
1631 def analyse_types(self, env):
1632 self.base.analyse_types(env)
1633 if self.start:
1634 self.start.analyse_types(env)
1635 if self.stop:
1636 self.stop.analyse_types(env)
1637 self.base = self.base.coerce_to_pyobject(env)
1638 c_int = PyrexTypes.c_py_ssize_t_type
1639 if self.start:
1640 self.start = self.start.coerce_to(c_int, env)
1641 if self.stop:
1642 self.stop = self.stop.coerce_to(c_int, env)
1643 self.type = py_object_type
1644 self.gil_check(env)
1645 self.is_temp = 1
1647 gil_message = "Slicing Python object"
1649 def generate_result_code(self, code):
1650 code.putln(
1651 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1652 self.result(),
1653 self.base.py_result(),
1654 self.start_code(),
1655 self.stop_code(),
1656 code.error_goto_if_null(self.result(), self.pos)))
1658 def generate_assignment_code(self, rhs, code):
1659 self.generate_subexpr_evaluation_code(code)
1660 code.put_error_if_neg(self.pos,
1661 "PySequence_SetSlice(%s, %s, %s, %s)" % (
1662 self.base.py_result(),
1663 self.start_code(),
1664 self.stop_code(),
1665 rhs.result()))
1666 self.generate_subexpr_disposal_code(code)
1667 rhs.generate_disposal_code(code)
1669 def generate_deletion_code(self, code):
1670 self.generate_subexpr_evaluation_code(code)
1671 code.put_error_if_neg(self.pos,
1672 "PySequence_DelSlice(%s, %s, %s)" % (
1673 self.base.py_result(),
1674 self.start_code(),
1675 self.stop_code()))
1676 self.generate_subexpr_disposal_code(code)
1678 def start_code(self):
1679 if self.start:
1680 return self.start.result()
1681 else:
1682 return "0"
1684 def stop_code(self):
1685 if self.stop:
1686 return self.stop.result()
1687 else:
1688 return "PY_SSIZE_T_MAX"
1690 def calculate_result_code(self):
1691 # self.result() is not used, but this method must exist
1692 return "<unused>"
1695 class SliceNode(ExprNode):
1696 # start:stop:step in subscript list
1698 # start ExprNode
1699 # stop ExprNode
1700 # step ExprNode
1702 def compile_time_value(self, denv):
1703 start = self.start.compile_time_value(denv)
1704 stop = self.stop.compile_time_value(denv)
1705 step = step.step.compile_time_value(denv)
1706 try:
1707 return slice(start, stop, step)
1708 except Exception, e:
1709 self.compile_time_value_error(e)
1711 subexprs = ['start', 'stop', 'step']
1713 def analyse_types(self, env):
1714 self.start.analyse_types(env)
1715 self.stop.analyse_types(env)
1716 self.step.analyse_types(env)
1717 self.start = self.start.coerce_to_pyobject(env)
1718 self.stop = self.stop.coerce_to_pyobject(env)
1719 self.step = self.step.coerce_to_pyobject(env)
1720 self.type = py_object_type
1721 self.gil_check(env)
1722 self.is_temp = 1
1724 gil_message = "Constructing Python slice object"
1726 def generate_result_code(self, code):
1727 code.putln(
1728 "%s = PySlice_New(%s, %s, %s); %s" % (
1729 self.result(),
1730 self.start.py_result(),
1731 self.stop.py_result(),
1732 self.step.py_result(),
1733 code.error_goto_if_null(self.result(), self.pos)))
1736 class CallNode(ExprNode):
1737 def gil_check(self, env):
1738 # Make sure we're not in a nogil environment
1739 if env.nogil:
1740 error(self.pos, "Calling gil-requiring function without gil")
1743 class SimpleCallNode(CallNode):
1744 # Function call without keyword, * or ** args.
1746 # function ExprNode
1747 # args [ExprNode]
1748 # arg_tuple ExprNode or None used internally
1749 # self ExprNode or None used internally
1750 # coerced_self ExprNode or None used internally
1751 # wrapper_call bool used internally
1752 # has_optional_args bool used internally
1754 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
1756 self = None
1757 coerced_self = None
1758 arg_tuple = None
1759 wrapper_call = False
1760 has_optional_args = False
1762 def compile_time_value(self, denv):
1763 function = self.function.compile_time_value(denv)
1764 args = [arg.compile_time_value(denv) for arg in self.args]
1765 try:
1766 return function(*args)
1767 except Exception, e:
1768 self.compile_time_value_error(e)
1770 def analyse_types(self, env):
1771 function = self.function
1772 function.is_called = 1
1773 self.function.analyse_types(env)
1774 if function.is_attribute and function.is_py_attr and \
1775 function.attribute == "append" and len(self.args) == 1:
1776 # L.append(x) is almost always applied to a list
1777 self.py_func = self.function
1778 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
1779 self.function.analyse_types(env)
1780 self.self = self.py_func.obj
1781 function.obj = CloneNode(self.self)
1782 env.use_utility_code(append_utility_code)
1783 if function.is_attribute and function.entry and function.entry.is_cmethod:
1784 # Take ownership of the object from which the attribute
1785 # was obtained, because we need to pass it as 'self'.
1786 self.self = function.obj
1787 function.obj = CloneNode(self.self)
1788 func_type = self.function_type()
1789 if func_type.is_pyobject:
1790 self.arg_tuple = TupleNode(self.pos, args = self.args)
1791 self.arg_tuple.analyse_types(env)
1792 self.args = None
1793 self.type = py_object_type
1794 self.gil_check(env)
1795 self.is_temp = 1
1796 else:
1797 for arg in self.args:
1798 arg.analyse_types(env)
1799 if self.self and func_type.args:
1800 # Coerce 'self' to the type expected by the method.
1801 expected_type = func_type.args[0].type
1802 self.coerced_self = CloneNode(self.self).coerce_to(
1803 expected_type, env)
1804 # Insert coerced 'self' argument into argument list.
1805 self.args.insert(0, self.coerced_self)
1806 self.analyse_c_function_call(env)
1808 def function_type(self):
1809 # Return the type of the function being called, coercing a function
1810 # pointer to a function if necessary.
1811 func_type = self.function.type
1812 if func_type.is_ptr:
1813 func_type = func_type.base_type
1814 return func_type
1816 def analyse_c_function_call(self, env):
1817 func_type = self.function_type()
1818 # Check function type
1819 if not func_type.is_cfunction:
1820 if not func_type.is_error:
1821 error(self.pos, "Calling non-function type '%s'" %
1822 func_type)
1823 self.type = PyrexTypes.error_type
1824 self.result_code = "<error>"
1825 return
1826 # Check no. of args
1827 max_nargs = len(func_type.args)
1828 expected_nargs = max_nargs - func_type.optional_arg_count
1829 actual_nargs = len(self.args)
1830 if actual_nargs < expected_nargs \
1831 or (not func_type.has_varargs and actual_nargs > max_nargs):
1832 expected_str = str(expected_nargs)
1833 if func_type.has_varargs:
1834 expected_str = "at least " + expected_str
1835 elif func_type.optional_arg_count:
1836 if actual_nargs < max_nargs:
1837 expected_str = "at least " + expected_str
1838 else:
1839 expected_str = "at most " + str(max_nargs)
1840 error(self.pos,
1841 "Call with wrong number of arguments (expected %s, got %s)"
1842 % (expected_str, actual_nargs))
1843 self.args = None
1844 self.type = PyrexTypes.error_type
1845 self.result_code = "<error>"
1846 return
1847 if func_type.optional_arg_count and expected_nargs != actual_nargs:
1848 self.has_optional_args = 1
1849 self.is_temp = 1
1850 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
1851 env.release_temp(self.opt_arg_struct)
1852 # Coerce arguments
1853 for i in range(min(max_nargs, actual_nargs)):
1854 formal_type = func_type.args[i].type
1855 self.args[i] = self.args[i].coerce_to(formal_type, env)
1856 for i in range(max_nargs, actual_nargs):
1857 if self.args[i].type.is_pyobject:
1858 error(self.args[i].pos,
1859 "Python object cannot be passed as a varargs parameter")
1860 # Calc result type and code fragment
1861 self.type = func_type.return_type
1862 if self.type.is_pyobject \
1863 or func_type.exception_value is not None \
1864 or func_type.exception_check:
1865 self.is_temp = 1
1866 if self.type.is_pyobject:
1867 self.result_ctype = py_object_type
1868 # C++ exception handler
1869 if func_type.exception_check == '+':
1870 if func_type.exception_value is None:
1871 env.use_utility_code(cpp_exception_utility_code)
1872 # Check gil
1873 if not func_type.nogil:
1874 self.gil_check(env)
1876 def calculate_result_code(self):
1877 return self.c_call_code()
1879 def c_call_code(self):
1880 func_type = self.function_type()
1881 if self.args is None or not func_type.is_cfunction:
1882 return "<error>"
1883 formal_args = func_type.args
1884 arg_list_code = []
1885 args = zip(formal_args, self.args)
1886 max_nargs = len(func_type.args)
1887 expected_nargs = max_nargs - func_type.optional_arg_count
1888 actual_nargs = len(self.args)
1889 for formal_arg, actual_arg in args[:expected_nargs]:
1890 arg_code = actual_arg.result_as(formal_arg.type)
1891 arg_list_code.append(arg_code)
1893 if func_type.is_overridable:
1894 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
1896 if func_type.optional_arg_count:
1897 if expected_nargs == actual_nargs:
1898 optional_args = 'NULL'
1899 else:
1900 optional_args = "&%s" % self.opt_arg_struct
1901 arg_list_code.append(optional_args)
1903 for actual_arg in self.args[len(formal_args):]:
1904 arg_list_code.append(actual_arg.result())
1905 result = "%s(%s)" % (self.function.result(),
1906 join(arg_list_code, ", "))
1907 # if self.wrapper_call or \
1908 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
1909 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
1910 return result
1912 def generate_result_code(self, code):
1913 func_type = self.function_type()
1914 if func_type.is_pyobject:
1915 arg_code = self.arg_tuple.py_result()
1916 code.putln(
1917 "%s = PyObject_Call(%s, %s, NULL); %s" % (
1918 self.result(),
1919 self.function.py_result(),
1920 arg_code,
1921 code.error_goto_if_null(self.result(), self.pos)))
1922 elif func_type.is_cfunction:
1923 if self.has_optional_args:
1924 actual_nargs = len(self.args)
1925 expected_nargs = len(func_type.args) - func_type.optional_arg_count
1926 code.putln("%s.%s = %s;" % (
1927 self.opt_arg_struct,
1928 Naming.pyrex_prefix + "n",
1929 len(self.args) - expected_nargs))
1930 args = zip(func_type.args, self.args)
1931 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
1932 code.putln("%s.%s = %s;" % (
1933 self.opt_arg_struct,
1934 formal_arg.name,
1935 actual_arg.result_as(formal_arg.type)))
1936 exc_checks = []
1937 if self.type.is_pyobject:
1938 exc_checks.append("!%s" % self.result())
1939 else:
1940 exc_val = func_type.exception_value
1941 exc_check = func_type.exception_check
1942 if exc_val is not None:
1943 exc_checks.append("%s == %s" % (self.result(), exc_val))
1944 if exc_check:
1945 exc_checks.append("PyErr_Occurred()")
1946 if self.is_temp or exc_checks:
1947 rhs = self.c_call_code()
1948 if self.result():
1949 lhs = "%s = " % self.result()
1950 if self.is_temp and self.type.is_pyobject:
1951 #return_type = self.type # func_type.return_type
1952 #print "SimpleCallNode.generate_result_code: casting", rhs, \
1953 # "from", return_type, "to pyobject" ###
1954 rhs = typecast(py_object_type, self.type, rhs)
1955 else:
1956 lhs = ""
1957 if func_type.exception_check == '+':
1958 if func_type.exception_value is None:
1959 raise_py_exception = "__Pyx_CppExn2PyErr()"
1960 elif func_type.exception_value.type.is_pyobject:
1961 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
1962 else:
1963 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
1964 code.putln(
1965 "try {%s%s;} catch(...) {%s; %s}" % (
1966 lhs,
1967 rhs,
1968 raise_py_exception,
1969 code.error_goto(self.pos)))
1970 else:
1971 if exc_checks:
1972 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
1973 else:
1974 goto_error = ""
1975 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
1977 class GeneralCallNode(CallNode):
1978 # General Python function call, including keyword,
1979 # * and ** arguments.
1981 # function ExprNode
1982 # positional_args ExprNode Tuple of positional arguments
1983 # keyword_args ExprNode or None Dict of keyword arguments
1984 # starstar_arg ExprNode or None Dict of extra keyword args
1986 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
1988 def compile_time_value(self, denv):
1989 function = self.function.compile_time_value(denv)
1990 positional_args = self.positional_args.compile_time_value(denv)
1991 keyword_args = self.keyword_args.compile_time_value(denv)
1992 starstar_arg = self.starstar_arg.compile_time_value(denv)
1993 try:
1994 keyword_args.update(starstar_arg)
1995 return function(*positional_args, **keyword_args)
1996 except Exception, e:
1997 self.compile_time_value_error(e)
1999 def analyse_types(self, env):
2000 self.function.analyse_types(env)
2001 self.positional_args.analyse_types(env)
2002 if self.keyword_args:
2003 self.keyword_args.analyse_types(env)
2004 if self.starstar_arg:
2005 self.starstar_arg.analyse_types(env)
2006 self.function = self.function.coerce_to_pyobject(env)
2007 self.positional_args = \
2008 self.positional_args.coerce_to_pyobject(env)
2009 if self.starstar_arg:
2010 self.starstar_arg = \
2011 self.starstar_arg.coerce_to_pyobject(env)
2012 self.type = py_object_type
2013 self.gil_check(env)
2014 self.is_temp = 1
2016 def generate_result_code(self, code):
2017 if self.keyword_args and self.starstar_arg:
2018 code.put_error_if_neg(self.pos,
2019 "PyDict_Update(%s, %s)" % (
2020 self.keyword_args.py_result(),
2021 self.starstar_arg.py_result()))
2022 keyword_code = self.keyword_args.py_result()
2023 elif self.keyword_args:
2024 keyword_code = self.keyword_args.py_result()
2025 elif self.starstar_arg:
2026 keyword_code = self.starstar_arg.py_result()
2027 else:
2028 keyword_code = None
2029 if not keyword_code:
2030 call_code = "PyObject_Call(%s, %s, NULL)" % (
2031 self.function.py_result(),
2032 self.positional_args.py_result())
2033 else:
2034 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2035 self.function.py_result(),
2036 self.positional_args.py_result(),
2037 keyword_code)
2038 code.putln(
2039 "%s = %s; %s" % (
2040 self.result(),
2041 call_code,
2042 code.error_goto_if_null(self.result(), self.pos)))
2045 class AsTupleNode(ExprNode):
2046 # Convert argument to tuple. Used for normalising
2047 # the * argument of a function call.
2049 # arg ExprNode
2051 subexprs = ['arg']
2053 def compile_time_value(self, denv):
2054 arg = self.arg.compile_time_value(denv)
2055 try:
2056 return tuple(arg)
2057 except Exception, e:
2058 self.compile_time_value_error(e)
2060 def analyse_types(self, env):
2061 self.arg.analyse_types(env)
2062 self.arg = self.arg.coerce_to_pyobject(env)
2063 self.type = py_object_type
2064 self.gil_check(env)
2065 self.is_temp = 1
2067 gil_message = "Constructing Python tuple"
2069 def generate_result_code(self, code):
2070 code.putln(
2071 "%s = PySequence_Tuple(%s); %s" % (
2072 self.result(),
2073 self.arg.py_result(),
2074 code.error_goto_if_null(self.result(), self.pos)))
2077 class AttributeNode(ExprNode):
2078 # obj.attribute
2080 # obj ExprNode
2081 # attribute string
2082 # needs_none_check boolean Used if obj is an extension type.
2083 # If set to True, it is known that the type is not None.
2085 # Used internally:
2087 # is_py_attr boolean Is a Python getattr operation
2088 # member string C name of struct member
2089 # is_called boolean Function call is being done on result
2090 # entry Entry Symbol table entry of attribute
2091 # interned_attr_cname string C name of interned attribute name
2093 is_attribute = 1
2094 subexprs = ['obj']
2096 type = PyrexTypes.error_type
2097 entry = None
2098 is_called = 0
2099 needs_none_check = True
2101 def coerce_to(self, dst_type, env):
2102 # If coercing to a generic pyobject and this is a cpdef function
2103 # we can create the corresponding attribute
2104 if dst_type is py_object_type:
2105 entry = self.entry
2106 if entry and entry.is_cfunction and entry.as_variable:
2107 # must be a cpdef function
2108 self.is_temp = 1
2109 self.entry = entry.as_variable
2110 self.analyse_as_python_attribute(env)
2111 return self
2112 return ExprNode.coerce_to(self, dst_type, env)
2114 def compile_time_value(self, denv):
2115 attr = self.attribute
2116 if attr.beginswith("__") and attr.endswith("__"):
2117 self.error("Invalid attribute name '%s' in compile-time expression"
2118 % attr)
2119 return None
2120 obj = self.arg.compile_time_value(denv)
2121 try:
2122 return getattr(obj, attr)
2123 except Exception, e:
2124 self.compile_time_value_error(e)
2126 def analyse_target_declaration(self, env):
2127 pass
2129 def analyse_target_types(self, env):
2130 self.analyse_types(env, target = 1)
2132 def analyse_types(self, env, target = 0):
2133 if self.analyse_as_cimported_attribute(env, target):
2134 return
2135 if not target and self.analyse_as_unbound_cmethod(env):
2136 return
2137 self.analyse_as_ordinary_attribute(env, target)
2139 def analyse_as_cimported_attribute(self, env, target):
2140 # Try to interpret this as a reference to an imported
2141 # C const, type, var or function. If successful, mutates
2142 # this node into a NameNode and returns 1, otherwise
2143 # returns 0.
2144 module_scope = self.obj.analyse_as_module(env)
2145 if module_scope:
2146 entry = module_scope.lookup_here(self.attribute)
2147 if entry and (
2148 entry.is_cglobal or entry.is_cfunction
2149 or entry.is_type or entry.is_const):
2150 self.mutate_into_name_node(env, entry, target)
2151 return 1
2152 return 0
2154 def analyse_as_unbound_cmethod(self, env):
2155 # Try to interpret this as a reference to an unbound
2156 # C method of an extension type. If successful, mutates
2157 # this node into a NameNode and returns 1, otherwise
2158 # returns 0.
2159 type = self.obj.analyse_as_extension_type(env)
2160 if type:
2161 entry = type.scope.lookup_here(self.attribute)
2162 if entry and entry.is_cmethod:
2163 # Create a temporary entry describing the C method
2164 # as an ordinary function.
2165 ubcm_entry = Symtab.Entry(entry.name,
2166 "%s->%s" % (type.vtabptr_cname, entry.cname),
2167 entry.type)
2168 ubcm_entry.is_cfunction = 1
2169 ubcm_entry.func_cname = entry.func_cname
2170 ubcm_entry.is_unbound_cmethod = 1
2171 self.mutate_into_name_node(env, ubcm_entry, None)
2172 return 1
2173 return 0
2175 def analyse_as_extension_type(self, env):
2176 # Try to interpret this as a reference to an extension type
2177 # in a cimported module. Returns the extension type, or None.
2178 module_scope = self.obj.analyse_as_module(env)
2179 if module_scope:
2180 entry = module_scope.lookup_here(self.attribute)
2181 if entry and entry.is_type and entry.type.is_extension_type:
2182 return entry.type
2183 return None
2185 def analyse_as_module(self, env):
2186 # Try to interpret this as a reference to a cimported module
2187 # in another cimported module. Returns the module scope, or None.
2188 module_scope = self.obj.analyse_as_module(env)
2189 if module_scope:
2190 entry = module_scope.lookup_here(self.attribute)
2191 if entry and entry.as_module:
2192 return entry.as_module
2193 return None
2195 def mutate_into_name_node(self, env, entry, target):
2196 # Mutate this node into a NameNode and complete the
2197 # analyse_types phase.
2198 self.__class__ = NameNode
2199 self.name = self.attribute
2200 self.entry = entry
2201 del self.obj
2202 del self.attribute
2203 if target:
2204 NameNode.analyse_target_types(self, env)
2205 else:
2206 NameNode.analyse_rvalue_entry(self, env)
2208 def analyse_as_ordinary_attribute(self, env, target):
2209 self.obj.analyse_types(env)
2210 self.analyse_attribute(env)
2211 if self.entry and self.entry.is_cmethod and not self.is_called:
2212 # error(self.pos, "C method can only be called")
2213 pass
2214 ## Reference to C array turns into pointer to first element.
2215 #while self.type.is_array:
2216 # self.type = self.type.element_ptr_type()
2217 if self.is_py_attr:
2218 if not target:
2219 self.is_temp = 1
2220 self.result_ctype = py_object_type
2222 def analyse_attribute(self, env):
2223 # Look up attribute and set self.type and self.member.
2224 self.is_py_attr = 0
2225 self.member = self.attribute
2226 if self.obj.type.is_string:
2227 self.obj = self.obj.coerce_to_pyobject(env)
2228 obj_type = self.obj.type
2229 if obj_type.is_ptr or obj_type.is_array:
2230 obj_type = obj_type.base_type
2231 self.op = "->"
2232 elif obj_type.is_extension_type:
2233 self.op = "->"
2234 else:
2235 self.op = "."
2236 if obj_type.has_attributes:
2237 entry = None
2238 if obj_type.attributes_known():
2239 entry = obj_type.scope.lookup_here(self.attribute)
2240 if entry and entry.is_member:
2241 entry = None
2242 else:
2243 error(self.pos,
2244 "Cannot select attribute of incomplete type '%s'"
2245 % obj_type)
2246 self.type = PyrexTypes.error_type
2247 return
2248 self.entry = entry
2249 if entry:
2250 if obj_type.is_extension_type and entry.name == "__weakref__":
2251 error(self.pos, "Illegal use of special attribute __weakref__")
2252 # methods need the normal attribute lookup
2253 # because they do not have struct entries
2254 if entry.is_variable or entry.is_cmethod:
2255 self.type = entry.type
2256 self.member = entry.cname
2257 return
2258 else:
2259 # If it's not a variable or C method, it must be a Python
2260 # method of an extension type, so we treat it like a Python
2261 # attribute.
2262 pass
2263 # If we get here, the base object is not a struct/union/extension
2264 # type, or it is an extension type and the attribute is either not
2265 # declared or is declared as a Python method. Treat it as a Python
2266 # attribute reference.
2267 self.analyse_as_python_attribute(env)
2269 def analyse_as_python_attribute(self, env):
2270 obj_type = self.obj.type
2271 self.member = self.attribute
2272 if obj_type.is_pyobject:
2273 self.type = py_object_type
2274 self.is_py_attr = 1
2275 self.interned_attr_cname = env.intern_identifier(self.attribute)
2276 self.gil_check(env)
2277 else:
2278 if not obj_type.is_error:
2279 error(self.pos,
2280 "Object of type '%s' has no attribute '%s'" %
2281 (obj_type, self.attribute))
2283 gil_message = "Accessing Python attribute"
2285 def is_simple(self):
2286 if self.obj:
2287 return self.result_in_temp() or self.obj.is_simple()
2288 else:
2289 return NameNode.is_simple(self)
2291 def is_lvalue(self):
2292 if self.obj:
2293 return 1
2294 else:
2295 return NameNode.is_lvalue(self)
2297 def is_ephemeral(self):
2298 if self.obj:
2299 return self.obj.is_ephemeral()
2300 else:
2301 return NameNode.is_ephemeral(self)
2303 def calculate_result_code(self):
2304 #print "AttributeNode.calculate_result_code:", self.member ###
2305 #print "...obj node =", self.obj, "code", self.obj.result() ###
2306 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2307 obj = self.obj
2308 obj_code = obj.result_as(obj.type)
2309 #print "...obj_code =", obj_code ###
2310 if self.entry and self.entry.is_cmethod:
2311 if obj.type.is_extension_type:
2312 return "((struct %s *)%s%s%s)->%s" % (
2313 obj.type.vtabstruct_cname, obj_code, self.op,
2314 obj.type.vtabslot_cname, self.member)
2315 else:
2316 return self.member
2317 else:
2318 return "%s%s%s" % (obj_code, self.op, self.member)
2320 def generate_result_code(self, code):
2321 if self.is_py_attr:
2322 code.putln(
2323 '%s = PyObject_GetAttr(%s, %s); %s' % (
2324 self.result(),
2325 self.obj.py_result(),
2326 self.interned_attr_cname,
2327 code.error_goto_if_null(self.result(), self.pos)))
2328 else:
2329 # result_code contains what is needed, but we may need to insert
2330 # a check and raise an exception
2331 if (self.obj.type.is_extension_type
2332 and self.needs_none_check
2333 and code.globalstate.directives['nonecheck']):
2334 self.put_nonecheck(code)
2336 def generate_assignment_code(self, rhs, code):
2337 self.obj.generate_evaluation_code(code)
2338 if self.is_py_attr:
2339 code.put_error_if_neg(self.pos,
2340 'PyObject_SetAttr(%s, %s, %s)' % (
2341 self.obj.py_result(),
2342 self.interned_attr_cname,
2343 rhs.py_result()))
2344 rhs.generate_disposal_code(code)
2345 else:
2346 if (self.obj.type.is_extension_type
2347 and self.needs_none_check
2348 and code.globalstate.directives['nonecheck']):
2349 self.put_nonecheck(code)
2351 select_code = self.result()
2352 if self.type.is_pyobject:
2353 rhs.make_owned_reference(code)
2354 code.put_decref(select_code, self.ctype())
2355 code.putln(
2356 "%s = %s;" % (
2357 select_code,
2358 rhs.result_as(self.ctype())))
2359 #rhs.result()))
2360 rhs.generate_post_assignment_code(code)
2361 self.obj.generate_disposal_code(code)
2363 def generate_deletion_code(self, code):
2364 self.obj.generate_evaluation_code(code)
2365 if self.is_py_attr:
2366 code.put_error_if_neg(self.pos,
2367 'PyObject_DelAttr(%s, %s)' % (
2368 self.obj.py_result(),
2369 self.interned_attr_cname))
2370 else:
2371 error(self.pos, "Cannot delete C attribute of extension type")
2372 self.obj.generate_disposal_code(code)
2374 def annotate(self, code):
2375 if self.is_py_attr:
2376 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2377 else:
2378 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2380 def put_nonecheck(self, code):
2381 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
2382 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
2383 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
2384 code.putln(code.error_goto(self.pos))
2385 code.putln("}")
2388 #-------------------------------------------------------------------
2390 # Constructor nodes
2392 #-------------------------------------------------------------------
2394 class SequenceNode(ExprNode):
2395 # Base class for list and tuple constructor nodes.
2396 # Contains common code for performing sequence unpacking.
2398 # args [ExprNode]
2399 # iterator ExprNode
2400 # unpacked_items [ExprNode] or None
2401 # coerced_unpacked_items [ExprNode] or None
2403 subexprs = ['args']
2405 is_sequence_constructor = 1
2406 unpacked_items = None
2408 def compile_time_value_list(self, denv):
2409 return [arg.compile_time_value(denv) for arg in self.args]
2411 def analyse_target_declaration(self, env):
2412 for arg in self.args:
2413 arg.analyse_target_declaration(env)
2415 def analyse_types(self, env, skip_children=False):
2416 for i in range(len(self.args)):
2417 arg = self.args[i]
2418 if not skip_children: arg.analyse_types(env)
2419 self.args[i] = arg.coerce_to_pyobject(env)
2420 self.type = py_object_type
2421 self.gil_check(env)
2422 self.is_temp = 1
2424 def analyse_target_types(self, env):
2425 self.iterator = PyTempNode(self.pos, env)
2426 self.unpacked_items = []
2427 self.coerced_unpacked_items = []
2428 for arg in self.args:
2429 arg.analyse_target_types(env)
2430 unpacked_item = PyTempNode(self.pos, env)
2431 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2432 self.unpacked_items.append(unpacked_item)
2433 self.coerced_unpacked_items.append(coerced_unpacked_item)
2434 self.type = py_object_type
2435 env.use_utility_code(unpacking_utility_code)
2437 def allocate_target_temps(self, env, rhs):
2438 self.iterator.allocate_temps(env)
2439 for arg, node in zip(self.args, self.coerced_unpacked_items):
2440 node.allocate_temps(env)
2441 arg.allocate_target_temps(env, node)
2442 #arg.release_target_temp(env)
2443 #node.release_temp(env)
2444 if rhs:
2445 rhs.release_temp(env)
2446 self.iterator.release_temp(env)
2448 # def release_target_temp(self, env):
2449 # #for arg in self.args:
2450 # # arg.release_target_temp(env)
2451 # #for node in self.coerced_unpacked_items:
2452 # # node.release_temp(env)
2453 # self.iterator.release_temp(env)
2455 def generate_result_code(self, code):
2456 self.generate_operation_code(code)
2458 def generate_assignment_code(self, rhs, code):
2459 code.putln(
2460 "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
2461 rhs.py_result(),
2462 rhs.py_result(),
2463 len(self.args)))
2464 code.putln("PyObject* tuple = %s;" % rhs.py_result())
2465 for i in range(len(self.args)):
2466 item = self.unpacked_items[i]
2467 code.putln(
2468 "%s = PyTuple_GET_ITEM(tuple, %s);" % (
2469 item.result(),
2470 i))
2471 code.put_incref(item.result(), item.ctype())
2472 value_node = self.coerced_unpacked_items[i]
2473 value_node.generate_evaluation_code(code)
2474 self.args[i].generate_assignment_code(value_node, code)
2476 rhs.generate_disposal_code(code)
2477 code.putln("}")
2478 code.putln("else {")
2480 code.putln(
2481 "%s = PyObject_GetIter(%s); %s" % (
2482 self.iterator.result(),
2483 rhs.py_result(),
2484 code.error_goto_if_null(self.iterator.result(), self.pos)))
2485 rhs.generate_disposal_code(code)
2486 for i in range(len(self.args)):
2487 item = self.unpacked_items[i]
2488 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
2489 self.iterator.py_result(), i)
2490 code.putln(
2491 "%s = %s; %s" % (
2492 item.result(),
2493 typecast(item.ctype(), py_object_type, unpack_code),
2494 code.error_goto_if_null(item.result(), self.pos)))
2495 value_node = self.coerced_unpacked_items[i]
2496 value_node.generate_evaluation_code(code)
2497 self.args[i].generate_assignment_code(value_node, code)
2498 code.put_error_if_neg(self.pos,
2499 "__Pyx_EndUnpack(%s)" % (
2500 self.iterator.py_result()))
2501 if debug_disposal_code:
2502 print("UnpackNode.generate_assignment_code:")
2503 print("...generating disposal code for %s" % self.iterator)
2504 self.iterator.generate_disposal_code(code)
2506 code.putln("}")
2508 def annotate(self, code):
2509 for arg in self.args:
2510 arg.annotate(code)
2511 if self.unpacked_items:
2512 for arg in self.unpacked_items:
2513 arg.annotate(code)
2514 for arg in self.coerced_unpacked_items:
2515 arg.annotate(code)
2518 class TupleNode(SequenceNode):
2519 # Tuple constructor.
2521 gil_message = "Constructing Python tuple"
2523 def analyse_types(self, env, skip_children=False):
2524 if len(self.args) == 0:
2525 self.is_temp = 0
2526 self.is_literal = 1
2527 else:
2528 SequenceNode.analyse_types(self, env, skip_children)
2529 self.type = tuple_type
2531 def calculate_result_code(self):
2532 if len(self.args) > 0:
2533 error(self.pos, "Positive length tuples must be constructed.")
2534 else:
2535 return Naming.empty_tuple
2537 def compile_time_value(self, denv):
2538 values = self.compile_time_value_list(denv)
2539 try:
2540 return tuple(values)
2541 except Exception, e:
2542 self.compile_time_value_error(e)
2544 def generate_operation_code(self, code):
2545 if len(self.args) == 0:
2546 # result_code is Naming.empty_tuple
2547 return
2548 code.putln(
2549 "%s = PyTuple_New(%s); %s" % (
2550 self.result(),
2551 len(self.args),
2552 code.error_goto_if_null(self.result(), self.pos)))
2553 for i in range(len(self.args)):
2554 arg = self.args[i]
2555 if not arg.result_in_temp():
2556 code.put_incref(arg.result(), arg.ctype())
2557 code.putln(
2558 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2559 self.result(),
2560 i,
2561 arg.py_result()))
2563 def generate_subexpr_disposal_code(self, code):
2564 # We call generate_post_assignment_code here instead
2565 # of generate_disposal_code, because values were stored
2566 # in the tuple using a reference-stealing operation.
2567 for arg in self.args:
2568 arg.generate_post_assignment_code(code)
2571 class ListNode(SequenceNode):
2572 # List constructor.
2574 gil_message = "Constructing Python list"
2576 def analyse_types(self, env):
2577 SequenceNode.analyse_types(self, env)
2578 self.type = list_type
2580 def compile_time_value(self, denv):
2581 return self.compile_time_value_list(denv)
2583 def generate_operation_code(self, code):
2584 code.putln("%s = PyList_New(%s); %s" %
2585 (self.result(),
2586 len(self.args),
2587 code.error_goto_if_null(self.result(), self.pos)))
2588 for i in range(len(self.args)):
2589 arg = self.args[i]
2590 #if not arg.is_temp:
2591 if not arg.result_in_temp():
2592 code.put_incref(arg.result(), arg.ctype())
2593 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
2594 (self.result(),
2595 i,
2596 arg.py_result()))
2598 def generate_subexpr_disposal_code(self, code):
2599 # We call generate_post_assignment_code here instead
2600 # of generate_disposal_code, because values were stored
2601 # in the list using a reference-stealing operation.
2602 for arg in self.args:
2603 arg.generate_post_assignment_code(code)
2606 class ListComprehensionNode(SequenceNode):
2608 subexprs = []
2609 is_sequence_constructor = 0 # not unpackable
2611 child_attrs = ["loop", "append"]
2613 def analyse_types(self, env):
2614 self.type = list_type
2615 self.is_temp = 1
2616 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
2618 def allocate_temps(self, env, result = None):
2619 if debug_temp_alloc:
2620 print("%s Allocating temps" % self)
2621 self.allocate_temp(env, result)
2622 self.loop.analyse_declarations(env)
2623 self.loop.analyse_expressions(env)
2625 def generate_operation_code(self, code):
2626 code.putln("%s = PyList_New(%s); %s" %
2627 (self.result(),
2628 0,
2629 code.error_goto_if_null(self.result(), self.pos)))
2630 self.loop.generate_execution_code(code)
2632 def annotate(self, code):
2633 self.loop.annotate(code)
2636 class ListComprehensionAppendNode(ExprNode):
2638 # Need to be careful to avoid infinite recursion:
2639 # target must not be in child_attrs/subexprs
2640 subexprs = ['expr']
2642 def analyse_types(self, env):
2643 self.expr.analyse_types(env)
2644 if self.expr.type != py_object_type:
2645 self.expr = self.expr.coerce_to_pyobject(env)
2646 self.type = PyrexTypes.c_int_type
2647 self.is_temp = 1
2649 def generate_result_code(self, code):
2650 code.putln("%s = PyList_Append(%s, (PyObject*)%s); %s" %
2651 (self.result(),
2652 self.target.result(),
2653 self.expr.result(),
2654 code.error_goto_if(self.result(), self.pos)))
2657 class DictNode(ExprNode):
2658 # Dictionary constructor.
2660 # key_value_pairs [DictItemNode]
2662 subexprs = ['key_value_pairs']
2664 def compile_time_value(self, denv):
2665 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
2666 for item in self.key_value_pairs]
2667 try:
2668 return dict(pairs)
2669 except Exception, e:
2670 self.compile_time_value_error(e)
2672 def analyse_types(self, env):
2673 for item in self.key_value_pairs:
2674 item.analyse_types(env)
2675 self.type = dict_type
2676 self.gil_check(env)
2677 self.is_temp = 1
2679 gil_message = "Constructing Python dict"
2681 def allocate_temps(self, env, result = None):
2682 # Custom method used here because key-value
2683 # pairs are evaluated and used one at a time.
2684 self.allocate_temp(env, result)
2685 for item in self.key_value_pairs:
2686 item.key.allocate_temps(env)
2687 item.value.allocate_temps(env)
2688 item.key.release_temp(env)
2689 item.value.release_temp(env)
2691 def generate_evaluation_code(self, code):
2692 # Custom method used here because key-value
2693 # pairs are evaluated and used one at a time.
2694 code.putln(
2695 "%s = PyDict_New(); %s" % (
2696 self.result(),
2697 code.error_goto_if_null(self.result(), self.pos)))
2698 for item in self.key_value_pairs:
2699 item.generate_evaluation_code(code)
2700 code.put_error_if_neg(self.pos,
2701 "PyDict_SetItem(%s, %s, %s)" % (
2702 self.result(),
2703 item.key.py_result(),
2704 item.value.py_result()))
2705 item.generate_disposal_code(code)
2707 def annotate(self, code):
2708 for item in self.key_value_pairs:
2709 item.annotate(code)
2711 class DictItemNode(ExprNode):
2712 # Represents a single item in a DictNode
2714 # key ExprNode
2715 # value ExprNode
2716 subexprs = ['key', 'value']
2718 def analyse_types(self, env):
2719 self.key.analyse_types(env)
2720 self.value.analyse_types(env)
2721 self.key = self.key.coerce_to_pyobject(env)
2722 self.value = self.value.coerce_to_pyobject(env)
2724 def generate_evaluation_code(self, code):
2725 self.key.generate_evaluation_code(code)
2726 self.value.generate_evaluation_code(code)
2728 def generate_disposal_code(self, code):
2729 self.key.generate_disposal_code(code)
2730 self.value.generate_disposal_code(code)
2733 class ClassNode(ExprNode):
2734 # Helper class used in the implementation of Python
2735 # class definitions. Constructs a class object given
2736 # a name, tuple of bases and class dictionary.
2738 # name EncodedString Name of the class
2739 # cname string Class name as a Python string
2740 # bases ExprNode Base class tuple
2741 # dict ExprNode Class dict (not owned by this node)
2742 # doc ExprNode or None Doc string
2743 # module_name string Name of defining module
2745 subexprs = ['bases', 'doc']
2747 def analyse_types(self, env):
2748 self.cname = env.intern_identifier(self.name)
2749 self.bases.analyse_types(env)
2750 if self.doc:
2751 self.doc.analyse_types(env)
2752 self.doc = self.doc.coerce_to_pyobject(env)
2753 self.module_name = env.global_scope().qualified_name
2754 self.type = py_object_type
2755 self.gil_check(env)
2756 self.is_temp = 1
2757 env.use_utility_code(create_class_utility_code);
2759 gil_message = "Constructing Python class"
2761 def generate_result_code(self, code):
2762 if self.doc:
2763 code.put_error_if_neg(self.pos,
2764 'PyDict_SetItemString(%s, "__doc__", %s)' % (
2765 self.dict.py_result(),
2766 self.doc.py_result()))
2767 code.putln(
2768 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
2769 self.result(),
2770 self.bases.py_result(),
2771 self.dict.py_result(),
2772 self.cname,
2773 self.module_name,
2774 code.error_goto_if_null(self.result(), self.pos)))
2777 class UnboundMethodNode(ExprNode):
2778 # Helper class used in the implementation of Python
2779 # class definitions. Constructs an unbound method
2780 # object from a class and a function.
2782 # class_cname string C var holding the class object
2783 # function ExprNode Function object
2785 subexprs = ['function']
2787 def analyse_types(self, env):
2788 self.function.analyse_types(env)
2789 self.type = py_object_type
2790 self.gil_check(env)
2791 self.is_temp = 1
2793 gil_message = "Constructing an unbound method"
2795 def generate_result_code(self, code):
2796 code.putln(
2797 "%s = PyMethod_New(%s, 0, %s); %s" % (
2798 self.result(),
2799 self.function.py_result(),
2800 self.class_cname,
2801 code.error_goto_if_null(self.result(), self.pos)))
2804 class PyCFunctionNode(AtomicExprNode):
2805 # Helper class used in the implementation of Python
2806 # class definitions. Constructs a PyCFunction object
2807 # from a PyMethodDef struct.
2809 # pymethdef_cname string PyMethodDef structure
2811 def analyse_types(self, env):
2812 self.type = py_object_type
2813 self.gil_check(env)
2814 self.is_temp = 1
2816 gil_message = "Constructing Python function"
2818 def generate_result_code(self, code):
2819 code.putln(
2820 "%s = PyCFunction_New(&%s, 0); %s" % (
2821 self.result(),
2822 self.pymethdef_cname,
2823 code.error_goto_if_null(self.result(), self.pos)))
2825 #-------------------------------------------------------------------
2827 # Unary operator nodes
2829 #-------------------------------------------------------------------
2831 compile_time_unary_operators = {
2832 'not': operator.not_,
2833 '~': operator.inv,
2834 '-': operator.neg,
2835 '+': operator.pos,
2838 class UnopNode(ExprNode):
2839 # operator string
2840 # operand ExprNode
2842 # Processing during analyse_expressions phase:
2844 # analyse_c_operation
2845 # Called when the operand is not a pyobject.
2846 # - Check operand type and coerce if needed.
2847 # - Determine result type and result code fragment.
2848 # - Allocate temporary for result if needed.
2850 subexprs = ['operand']
2852 def compile_time_value(self, denv):
2853 func = compile_time_unary_operators.get(self.operator)
2854 if not func:
2855 error(self.pos,
2856 "Unary '%s' not supported in compile-time expression"
2857 % self.operator)
2858 operand = self.operand.compile_time_value(denv)
2859 try:
2860 return func(operand)
2861 except Exception, e:
2862 self.compile_time_value_error(e)
2864 def analyse_types(self, env):
2865 self.operand.analyse_types(env)
2866 if self.is_py_operation():
2867 self.coerce_operand_to_pyobject(env)
2868 self.type = py_object_type
2869 self.gil_check(env)
2870 self.is_temp = 1
2871 else:
2872 self.analyse_c_operation(env)
2874 def check_const(self):
2875 self.operand.check_const()
2877 def is_py_operation(self):
2878 return self.operand.type.is_pyobject
2880 def coerce_operand_to_pyobject(self, env):
2881 self.operand = self.operand.coerce_to_pyobject(env)
2883 def generate_result_code(self, code):
2884 if self.operand.type.is_pyobject:
2885 self.generate_py_operation_code(code)
2886 else:
2887 if self.is_temp:
2888 self.generate_c_operation_code(code)
2890 def generate_py_operation_code(self, code):
2891 function = self.py_operation_function()
2892 code.putln(
2893 "%s = %s(%s); %s" % (
2894 self.result(),
2895 function,
2896 self.operand.py_result(),
2897 code.error_goto_if_null(self.result(), self.pos)))
2899 def type_error(self):
2900 if not self.operand.type.is_error:
2901 error(self.pos, "Invalid operand type for '%s' (%s)" %
2902 (self.operator, self.operand.type))
2903 self.type = PyrexTypes.error_type
2906 class NotNode(ExprNode):
2907 # 'not' operator
2909 # operand ExprNode
2911 def compile_time_value(self, denv):
2912 operand = self.operand.compile_time_value(denv)
2913 try:
2914 return not operand
2915 except Exception, e:
2916 self.compile_time_value_error(e)
2918 subexprs = ['operand']
2920 def analyse_types(self, env):
2921 self.operand.analyse_types(env)
2922 self.operand = self.operand.coerce_to_boolean(env)
2923 self.type = PyrexTypes.c_bint_type
2925 def calculate_result_code(self):
2926 return "(!%s)" % self.operand.result()
2928 def generate_result_code(self, code):
2929 pass
2932 class UnaryPlusNode(UnopNode):
2933 # unary '+' operator
2935 operator = '+'
2937 def analyse_c_operation(self, env):
2938 self.type = self.operand.type
2940 def py_operation_function(self):
2941 return "PyNumber_Positive"
2943 def calculate_result_code(self):
2944 return self.operand.result()
2947 class UnaryMinusNode(UnopNode):
2948 # unary '-' operator
2950 operator = '-'
2952 def analyse_c_operation(self, env):
2953 if self.operand.type.is_numeric:
2954 self.type = self.operand.type
2955 else:
2956 self.type_error()
2958 def py_operation_function(self):
2959 return "PyNumber_Negative"
2961 def calculate_result_code(self):
2962 return "(-%s)" % self.operand.result()
2965 class TildeNode(UnopNode):
2966 # unary '~' operator
2968 def analyse_c_operation(self, env):
2969 if self.operand.type.is_int:
2970 self.type = self.operand.type
2971 else:
2972 self.type_error()
2974 def py_operation_function(self):
2975 return "PyNumber_Invert"
2977 def calculate_result_code(self):
2978 return "(~%s)" % self.operand.result()
2981 class AmpersandNode(ExprNode):
2982 # The C address-of operator.
2984 # operand ExprNode
2986 subexprs = ['operand']
2988 def analyse_types(self, env):
2989 self.operand.analyse_types(env)
2990 argtype = self.operand.type
2991 if not (argtype.is_cfunction or self.operand.is_lvalue()):
2992 self.error("Taking address of non-lvalue")
2993 return
2994 if argtype.is_pyobject:
2995 self.error("Cannot take address of Python variable")
2996 return
2997 self.type = PyrexTypes.c_ptr_type(argtype)
2999 def check_const(self):
3000 self.operand.check_const_addr()
3002 def error(self, mess):
3003 error(self.pos, mess)
3004 self.type = PyrexTypes.error_type
3005 self.result_code = "<error>"
3007 def calculate_result_code(self):
3008 return "(&%s)" % self.operand.result()
3010 def generate_result_code(self, code):
3011 pass
3014 unop_node_classes = {
3015 "+": UnaryPlusNode,
3016 "-": UnaryMinusNode,
3017 "~": TildeNode,
3020 def unop_node(pos, operator, operand):
3021 # Construct unnop node of appropriate class for
3022 # given operator.
3023 if isinstance(operand, IntNode) and operator == '-':
3024 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3025 elif isinstance(operand, UnopNode) and operand.operator == operator:
3026 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3027 return unop_node_classes[operator](pos,
3028 operator = operator,
3029 operand = operand)
3032 class TypecastNode(ExprNode):
3033 # C type cast
3035 # operand ExprNode
3036 # base_type CBaseTypeNode
3037 # declarator CDeclaratorNode
3039 # If used from a transform, one can if wanted specify the attribute
3040 # "type" directly and leave base_type and declarator to None
3042 subexprs = ['operand']
3043 base_type = declarator = type = None
3045 def analyse_types(self, env):
3046 if self.type is None:
3047 base_type = self.base_type.analyse(env)
3048 _, self.type = self.declarator.analyse(base_type, env)
3049 if self.type.is_cfunction:
3050 error(self.pos,
3051 "Cannot cast to a function type")
3052 self.type = PyrexTypes.error_type
3053 self.operand.analyse_types(env)
3054 to_py = self.type.is_pyobject
3055 from_py = self.operand.type.is_pyobject
3056 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3057 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3058 if to_py and not from_py:
3059 if self.operand.type.to_py_function:
3060 self.result_ctype = py_object_type
3061 self.operand = self.operand.coerce_to_pyobject(env)
3062 else:
3063 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3064 self.operand = self.operand.coerce_to_simple(env)
3065 elif from_py and not to_py:
3066 if self.type.from_py_function:
3067 self.operand = self.operand.coerce_to(self.type, env)
3068 else:
3069 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3070 elif from_py and to_py:
3071 if self.typecheck and self.type.is_extension_type:
3072 self.operand = PyTypeTestNode(self.operand, self.type, env)
3074 def check_const(self):
3075 self.operand.check_const()
3077 def calculate_result_code(self):
3078 opnd = self.operand
3079 return self.type.cast_code(opnd.result())
3081 def result_as(self, type):
3082 if self.type.is_pyobject and not self.is_temp:
3083 # Optimise away some unnecessary casting
3084 return self.operand.result_as(type)
3085 else:
3086 return ExprNode.result_as(self, type)
3088 def generate_result_code(self, code):
3089 if self.is_temp:
3090 code.putln(
3091 "%s = (PyObject *)%s;" % (
3092 self.result(),
3093 self.operand.result()))
3094 code.put_incref(self.result(), self.ctype())
3097 class SizeofNode(ExprNode):
3098 # Abstract base class for sizeof(x) expression nodes.
3100 def check_const(self):
3101 pass
3103 def generate_result_code(self, code):
3104 pass
3107 class SizeofTypeNode(SizeofNode):
3108 # C sizeof function applied to a type
3110 # base_type CBaseTypeNode
3111 # declarator CDeclaratorNode
3113 subexprs = []
3115 def analyse_types(self, env):
3116 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
3117 # this could be better handled by more uniformly treating types as runtime-available objects
3118 if self.base_type.module_path:
3119 path = self.base_type.module_path
3120 obj = env.lookup(path[0])
3121 if obj.as_module is None:
3122 operand = NameNode(pos=self.pos, name=path[0])
3123 for attr in path[1:]:
3124 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
3125 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
3126 self.operand = operand
3127 self.__class__ = SizeofVarNode
3128 self.analyse_types(env)
3129 return
3130 base_type = self.base_type.analyse(env)
3131 _, arg_type = self.declarator.analyse(base_type, env)
3132 self.arg_type = arg_type
3133 if arg_type.is_pyobject and not arg_type.is_extension_type:
3134 error(self.pos, "Cannot take sizeof Python object")
3135 elif arg_type.is_void:
3136 error(self.pos, "Cannot take sizeof void")
3137 elif not arg_type.is_complete():
3138 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
3139 self.type = PyrexTypes.c_int_type
3141 def calculate_result_code(self):
3142 if self.arg_type.is_extension_type:
3143 # the size of the pointer is boring
3144 # we want the size of the actual struct
3145 arg_code = self.arg_type.declaration_code("", deref=1)
3146 else:
3147 arg_code = self.arg_type.declaration_code("")
3148 return "(sizeof(%s))" % arg_code
3151 class SizeofVarNode(SizeofNode):
3152 # C sizeof function applied to a variable
3154 # operand ExprNode
3156 subexprs = ['operand']
3158 def analyse_types(self, env):
3159 self.operand.analyse_types(env)
3160 self.type = PyrexTypes.c_int_type
3162 def calculate_result_code(self):
3163 return "(sizeof(%s))" % self.operand.result()
3165 def generate_result_code(self, code):
3166 pass
3169 #-------------------------------------------------------------------
3171 # Binary operator nodes
3173 #-------------------------------------------------------------------
3175 def _not_in(x, seq):
3176 return x not in seq
3178 compile_time_binary_operators = {
3179 '<': operator.lt,
3180 '<=': operator.le,
3181 '==': operator.eq,
3182 '!=': operator.ne,
3183 '>=': operator.ge,
3184 '>': operator.gt,
3185 'is': operator.is_,
3186 'is_not': operator.is_not,
3187 '+': operator.add,
3188 '&': operator.and_,
3189 '/': operator.div,
3190 '//': operator.floordiv,
3191 '<<': operator.lshift,
3192 '%': operator.mod,
3193 '*': operator.mul,
3194 '|': operator.or_,
3195 '**': operator.pow,
3196 '>>': operator.rshift,
3197 '-': operator.sub,
3198 #'/': operator.truediv,
3199 '^': operator.xor,
3200 'in': operator.contains,
3201 'not_in': _not_in,
3204 def get_compile_time_binop(node):
3205 func = compile_time_binary_operators.get(node.operator)
3206 if not func:
3207 error(node.pos,
3208 "Binary '%s' not supported in compile-time expression"
3209 % node.operator)
3210 return func
3212 class BinopNode(ExprNode):
3213 # operator string
3214 # operand1 ExprNode
3215 # operand2 ExprNode
3217 # Processing during analyse_expressions phase:
3219 # analyse_c_operation
3220 # Called when neither operand is a pyobject.
3221 # - Check operand types and coerce if needed.
3222 # - Determine result type and result code fragment.
3223 # - Allocate temporary for result if needed.
3225 subexprs = ['operand1', 'operand2']
3227 def compile_time_value(self, denv):
3228 func = get_compile_time_binop(self)
3229 operand1 = self.operand1.compile_time_value(denv)
3230 operand2 = self.operand2.compile_time_value(denv)
3231 try:
3232 return func(operand1, operand2)
3233 except Exception, e:
3234 self.compile_time_value_error(e)
3236 def analyse_types(self, env):
3237 self.operand1.analyse_types(env)
3238 self.operand2.analyse_types(env)
3239 if self.is_py_operation():
3240 self.coerce_operands_to_pyobjects(env)
3241 self.type = py_object_type
3242 self.gil_check(env)
3243 self.is_temp = 1
3244 if Options.incref_local_binop and self.operand1.type.is_pyobject:
3245 self.operand1 = self.operand1.coerce_to_temp(env)
3246 else:
3247 self.analyse_c_operation(env)
3249 def is_py_operation(self):
3250 return (self.operand1.type.is_pyobject
3251 or self.operand2.type.is_pyobject)
3253 def coerce_operands_to_pyobjects(self, env):
3254 self.operand1 = self.operand1.coerce_to_pyobject(env)
3255 self.operand2 = self.operand2.coerce_to_pyobject(env)
3257 def check_const(self):
3258 self.operand1.check_const()
3259 self.operand2.check_const()
3261 def generate_result_code(self, code):
3262 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
3263 if self.operand1.type.is_pyobject:
3264 function = self.py_operation_function()
3265 if function == "PyNumber_Power":
3266 extra_args = ", Py_None"
3267 else:
3268 extra_args = ""
3269 code.putln(
3270 "%s = %s(%s, %s%s); %s" % (
3271 self.result(),
3272 function,
3273 self.operand1.py_result(),
3274 self.operand2.py_result(),
3275 extra_args,
3276 code.error_goto_if_null(self.result(), self.pos)))
3277 else:
3278 if self.is_temp:
3279 self.generate_c_operation_code(code)
3281 def type_error(self):
3282 if not (self.operand1.type.is_error
3283 or self.operand2.type.is_error):
3284 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
3285 (self.operator, self.operand1.type,
3286 self.operand2.type))
3287 self.type = PyrexTypes.error_type
3290 class NumBinopNode(BinopNode):
3291 # Binary operation taking numeric arguments.
3293 def analyse_c_operation(self, env):
3294 type1 = self.operand1.type
3295 type2 = self.operand2.type
3296 if self.operator == "**" and type1.is_int and type2.is_int:
3297 error(self.pos, "** with two C int types is ambiguous")
3298 self.type = error_type
3299 return
3300 self.type = self.compute_c_result_type(type1, type2)
3301 if not self.type:
3302 self.type_error()
3304 def compute_c_result_type(self, type1, type2):
3305 if self.c_types_okay(type1, type2):
3306 return PyrexTypes.widest_numeric_type(type1, type2)
3307 else:
3308 return None
3310 def c_types_okay(self, type1, type2):
3311 #print "NumBinopNode.c_types_okay:", type1, type2 ###
3312 return (type1.is_numeric or type1.is_enum) \
3313 and (type2.is_numeric or type2.is_enum)
3315 def calculate_result_code(self):
3316 return "(%s %s %s)" % (
3317 self.operand1.result(),
3318 self.operator,
3319 self.operand2.result())
3321 def py_operation_function(self):
3322 return self.py_functions[self.operator]
3324 py_functions = {
3325 "|": "PyNumber_Or",
3326 "^": "PyNumber_Xor",
3327 "&": "PyNumber_And",
3328 "<<": "PyNumber_Lshift",
3329 ">>": "PyNumber_Rshift",
3330 "+": "PyNumber_Add",
3331 "-": "PyNumber_Subtract",
3332 "*": "PyNumber_Multiply",
3333 "/": "__Pyx_PyNumber_Divide",
3334 "//": "PyNumber_FloorDivide",
3335 "%": "PyNumber_Remainder",
3336 "**": "PyNumber_Power"
3340 class IntBinopNode(NumBinopNode):
3341 # Binary operation taking integer arguments.
3343 def c_types_okay(self, type1, type2):
3344 #print "IntBinopNode.c_types_okay:", type1, type2 ###
3345 return (type1.is_int or type1.is_enum) \
3346 and (type2.is_int or type2.is_enum)
3349 class AddNode(NumBinopNode):
3350 # '+' operator.
3352 def is_py_operation(self):
3353 if self.operand1.type.is_string \
3354 and self.operand2.type.is_string:
3355 return 1
3356 else:
3357 return NumBinopNode.is_py_operation(self)
3359 def compute_c_result_type(self, type1, type2):
3360 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
3361 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3362 return type1
3363 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
3364 return type2
3365 else:
3366 return NumBinopNode.compute_c_result_type(
3367 self, type1, type2)
3370 class SubNode(NumBinopNode):
3371 # '-' operator.
3373 def compute_c_result_type(self, type1, type2):
3374 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3375 return type1
3376 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
3377 return PyrexTypes.c_int_type
3378 else:
3379 return NumBinopNode.compute_c_result_type(
3380 self, type1, type2)
3383 class MulNode(NumBinopNode):
3384 # '*' operator.
3386 def is_py_operation(self):
3387 type1 = self.operand1.type
3388 type2 = self.operand2.type
3389 if (type1.is_string and type2.is_int) \
3390 or (type2.is_string and type1.is_int):
3391 return 1
3392 else:
3393 return NumBinopNode.is_py_operation(self)
3396 class FloorDivNode(NumBinopNode):
3397 # '//' operator.
3399 def calculate_result_code(self):
3400 return "(%s %s %s)" % (
3401 self.operand1.result(),
3402 "/", # c division is by default floor-div
3403 self.operand2.result())
3406 class ModNode(IntBinopNode):
3407 # '%' operator.
3409 def is_py_operation(self):
3410 return (self.operand1.type.is_string
3411 or self.operand2.type.is_string
3412 or IntBinopNode.is_py_operation(self))
3415 class PowNode(NumBinopNode):
3416 # '**' operator.
3418 def analyse_types(self, env):
3419 env.pow_function_used = 1
3420 NumBinopNode.analyse_types(self, env)
3422 def compute_c_result_type(self, type1, type2):
3423 if self.c_types_okay(type1, type2):
3424 return PyrexTypes.c_double_type
3425 else:
3426 return None
3428 def c_types_okay(self, type1, type2):
3429 return (type1.is_float or type2.is_float) and \
3430 NumBinopNode.c_types_okay(self, type1, type2)
3432 def type_error(self):
3433 if not (self.operand1.type.is_error or self.operand2.type.is_error):
3434 if self.operand1.type.is_int and self.operand2.type.is_int:
3435 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
3436 (self.operator, self.operand1.type, self.operand2.type))
3437 else:
3438 NumBinopNode.type_error(self)
3439 self.type = PyrexTypes.error_type
3441 def calculate_result_code(self):
3442 return "pow(%s, %s)" % (
3443 self.operand1.result(), self.operand2.result())
3446 class BoolBinopNode(ExprNode):
3447 # Short-circuiting boolean operation.
3449 # operator string
3450 # operand1 ExprNode
3451 # operand2 ExprNode
3452 # temp_bool ExprNode used internally
3454 temp_bool = None
3456 subexprs = ['operand1', 'operand2', 'temp_bool']
3458 def compile_time_value(self, denv):
3459 if self.operator == 'and':
3460 return self.operand1.compile_time_value(denv) \
3461 and self.operand2.compile_time_value(denv)
3462 else:
3463 return self.operand1.compile_time_value(denv) \
3464 or self.operand2.compile_time_value(denv)
3466 def analyse_types(self, env):
3467 self.operand1.analyse_types(env)
3468 self.operand2.analyse_types(env)
3469 if self.operand1.type.is_pyobject or \
3470 self.operand2.type.is_pyobject:
3471 self.operand1 = self.operand1.coerce_to_pyobject(env)
3472 self.operand2 = self.operand2.coerce_to_pyobject(env)
3473 self.temp_bool = TempNode(self.pos, PyrexTypes.c_bint_type, env)
3474 self.type = py_object_type
3475 self.gil_check(env)
3476 else:
3477 self.operand1 = self.operand1.coerce_to_boolean(env)
3478 self.operand2 = self.operand2.coerce_to_boolean(env)
3479 self.type = PyrexTypes.c_bint_type
3480 # For what we're about to do, it's vital that
3481 # both operands be temp nodes.
3482 self.operand1 = self.operand1.coerce_to_temp(env) #CTT
3483 self.operand2 = self.operand2.coerce_to_temp(env)
3484 self.is_temp = 1
3486 gil_message = "Truth-testing Python object"
3488 def allocate_temps(self, env, result_code = None):
3489 # We don't need both operands at the same time, and
3490 # one of the operands will also be our result. So we
3491 # use an allocation strategy here which results in
3492 # this node and both its operands sharing the same
3493 # result variable. This allows us to avoid some
3494 # assignments and increfs/decrefs that would otherwise
3495 # be necessary.
3496 self.allocate_temp(env, result_code)
3497 self.operand1.allocate_temps(env, self.result())
3498 if self.temp_bool:
3499 self.temp_bool.allocate_temp(env)
3500 self.temp_bool.release_temp(env)
3501 self.operand2.allocate_temps(env, self.result())
3502 # We haven't called release_temp on either operand,
3503 # because although they are temp nodes, they don't own
3504 # their result variable. And because they are temp
3505 # nodes, any temps in their subnodes will have been
3506 # released before their allocate_temps returned.
3507 # Therefore, they contain no temp vars that need to
3508 # be released.
3510 def check_const(self):
3511 self.operand1.check_const()
3512 self.operand2.check_const()
3514 def calculate_result_code(self):
3515 return "(%s %s %s)" % (
3516 self.operand1.result(),
3517 self.py_to_c_op[self.operator],
3518 self.operand2.result())
3520 py_to_c_op = {'and': "&&", 'or': "||"}
3522 def generate_evaluation_code(self, code):
3523 self.operand1.generate_evaluation_code(code)
3524 test_result = self.generate_operand1_test(code)
3525 if self.operator == 'and':
3526 sense = ""
3527 else:
3528 sense = "!"
3529 code.putln(
3530 "if (%s%s) {" % (
3531 sense,
3532 test_result))
3533 self.operand1.generate_disposal_code(code)
3534 self.operand2.generate_evaluation_code(code)
3535 code.putln(
3536 "}")
3538 def generate_operand1_test(self, code):
3539 # Generate code to test the truth of the first operand.
3540 if self.type.is_pyobject:
3541 test_result = self.temp_bool.result()
3542 code.putln(
3543 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3544 test_result,
3545 self.operand1.py_result(),
3546 code.error_goto_if_neg(test_result, self.pos)))
3547 else:
3548 test_result = self.operand1.result()
3549 return test_result
3552 class CondExprNode(ExprNode):
3553 # Short-circuiting conditional expression.
3555 # test ExprNode
3556 # true_val ExprNode
3557 # false_val ExprNode
3559 temp_bool = None
3560 true_val = None
3561 false_val = None
3563 subexprs = ['test', 'true_val', 'false_val']
3565 def analyse_types(self, env):
3566 self.test.analyse_types(env)
3567 self.test = self.test.coerce_to_boolean(env)
3568 self.true_val.analyse_types(env)
3569 self.false_val.analyse_types(env)
3570 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
3571 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
3572 self.true_val = self.true_val.coerce_to(self.type, env)
3573 self.false_val = self.false_val.coerce_to(self.type, env)
3574 # must be tmp variables so they can share a result
3575 self.true_val = self.true_val.coerce_to_temp(env)
3576 self.false_val = self.false_val.coerce_to_temp(env)
3577 self.is_temp = 1
3578 if self.type == PyrexTypes.error_type:
3579 self.type_error()
3581 def allocate_temps(self, env, result_code = None):
3582 # We only ever evaluate one side, and this is
3583 # after evaluating the truth value, so we may
3584 # use an allocation strategy here which results in
3585 # this node and both its operands sharing the same
3586 # result variable. This allows us to avoid some
3587 # assignments and increfs/decrefs that would otherwise
3588 # be necessary.
3589 self.allocate_temp(env, result_code)
3590 self.test.allocate_temps(env, result_code)
3591 self.true_val.allocate_temps(env, self.result())
3592 self.false_val.allocate_temps(env, self.result())
3593 # We haven't called release_temp on either value,
3594 # because although they are temp nodes, they don't own
3595 # their result variable. And because they are temp
3596 # nodes, any temps in their subnodes will have been
3597 # released before their allocate_temps returned.
3598 # Therefore, they contain no temp vars that need to
3599 # be released.
3601 def compute_result_type(self, type1, type2):
3602 if type1 == type2:
3603 return type1
3604 elif type1.is_numeric and type2.is_numeric:
3605 return PyrexTypes.widest_numeric_type(type1, type2)
3606 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
3607 return type2
3608 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
3609 return type1
3610 elif type1.is_pyobject or type2.is_pyobject:
3611 return py_object_type
3612 elif type1.assignable_from(type2):
3613 return type1
3614 elif type2.assignable_from(type1):
3615 return type2
3616 else:
3617 return PyrexTypes.error_type
3619 def type_error(self):
3620 if not (self.true_val.type.is_error or self.false_val.type.is_error):
3621 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
3622 (self.true_val.type, self.false_val.type))
3623 self.type = PyrexTypes.error_type
3625 def check_const(self):
3626 self.test.check_const()
3627 self.true_val.check_const()
3628 self.false_val.check_const()
3630 def generate_evaluation_code(self, code):
3631 self.test.generate_evaluation_code(code)
3632 code.putln("if (%s) {" % self.test.result() )
3633 self.true_val.generate_evaluation_code(code)
3634 code.putln("} else {")
3635 self.false_val.generate_evaluation_code(code)
3636 code.putln("}")
3637 self.test.generate_disposal_code(code)
3639 richcmp_constants = {
3640 "<" : "Py_LT",
3641 "<=": "Py_LE",
3642 "==": "Py_EQ",
3643 "!=": "Py_NE",
3644 "<>": "Py_NE",
3645 ">" : "Py_GT",
3646 ">=": "Py_GE",
3649 class CmpNode:
3650 # Mixin class containing code common to PrimaryCmpNodes
3651 # and CascadedCmpNodes.
3653 def cascaded_compile_time_value(self, operand1, denv):
3654 func = get_compile_time_binop(self)
3655 operand2 = self.operand2.compile_time_value(denv)
3656 try:
3657 result = func(operand1, operand2)
3658 except Exception, e:
3659 self.compile_time_value_error(e)
3660 result = None
3661 if result:
3662 cascade = self.cascade
3663 if cascade:
3664 result = result and cascade.compile_time_value(operand2, denv)
3665 return result
3667 def is_python_comparison(self):
3668 return (self.has_python_operands()
3669 or (self.cascade and self.cascade.is_python_comparison())
3670 or self.operator in ('in', 'not_in'))
3672 def is_python_result(self):
3673 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
3674 or (self.cascade and self.cascade.is_python_result()))
3676 def check_types(self, env, operand1, op, operand2):
3677 if not self.types_okay(operand1, op, operand2):
3678 error(self.pos, "Invalid types for '%s' (%s, %s)" %
3679 (self.operator, operand1.type, operand2.type))
3681 def types_okay(self, operand1, op, operand2):
3682 type1 = operand1.type
3683 type2 = operand2.type
3684 if type1.is_error or type2.is_error:
3685 return 1
3686 if type1.is_pyobject: # type2 will be, too
3687 return 1
3688 elif type1.is_ptr or type1.is_array:
3689 return type1.is_null_ptr or type2.is_null_ptr \
3690 or ((type2.is_ptr or type2.is_array)
3691 and type1.base_type.same_as(type2.base_type))
3692 elif ((type1.is_numeric and type2.is_numeric
3693 or type1.is_enum and (type1 is type2 or type2.is_int)
3694 or type1.is_int and type2.is_enum)
3695 and op not in ('is', 'is_not')):
3696 return 1
3697 else:
3698 return type1.is_cfunction and type1.is_cfunction and type1 == type2
3700 def generate_operation_code(self, code, result_code,
3701 operand1, op , operand2):
3702 if self.type is PyrexTypes.py_object_type:
3703 coerce_result = "__Pyx_PyBool_FromLong"
3704 else:
3705 coerce_result = ""
3706 if 'not' in op: negation = "!"
3707 else: negation = ""
3708 if op == 'in' or op == 'not_in':
3709 code.putln(
3710 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
3711 result_code,
3712 coerce_result,
3713 negation,
3714 operand2.py_result(),
3715 operand1.py_result(),
3716 code.error_goto_if_neg(result_code, self.pos)))
3717 elif (operand1.type.is_pyobject
3718 and op not in ('is', 'is_not')):
3719 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
3720 result_code,
3721 operand1.py_result(),
3722 operand2.py_result(),
3723 richcmp_constants[op],
3724 code.error_goto_if_null(result_code, self.pos)))
3725 else:
3726 type1 = operand1.type
3727 type2 = operand2.type
3728 if (type1.is_extension_type or type2.is_extension_type) \
3729 and not type1.same_as(type2):
3730 common_type = py_object_type
3731 elif type1.is_numeric:
3732 common_type = PyrexTypes.widest_numeric_type(type1, type2)
3733 else:
3734 common_type = type1
3735 code1 = operand1.result_as(common_type)
3736 code2 = operand2.result_as(common_type)
3737 code.putln("%s = %s(%s %s %s);" % (
3738 result_code,
3739 coerce_result,
3740 code1,
3741 self.c_operator(op),
3742 code2))
3744 def c_operator(self, op):
3745 if op == 'is':
3746 return "=="
3747 elif op == 'is_not':
3748 return "!="
3749 else:
3750 return op
3753 class PrimaryCmpNode(ExprNode, CmpNode):
3754 # Non-cascaded comparison or first comparison of
3755 # a cascaded sequence.
3757 # operator string
3758 # operand1 ExprNode
3759 # operand2 ExprNode
3760 # cascade CascadedCmpNode
3762 # We don't use the subexprs mechanism, because
3763 # things here are too complicated for it to handle.
3764 # Instead, we override all the framework methods
3765 # which use it.
3767 child_attrs = ['operand1', 'operand2', 'cascade']
3769 cascade = None
3771 def compile_time_value(self, denv):
3772 operand1 = self.operand1.compile_time_value(denv)
3773 return self.cascaded_compile_time_value(operand1, denv)
3775 def analyse_types(self, env):
3776 self.operand1.analyse_types(env)
3777 self.operand2.analyse_types(env)
3778 if self.cascade:
3779 self.cascade.analyse_types(env, self.operand2)
3780 self.is_pycmp = self.is_python_comparison()
3781 if self.is_pycmp:
3782 self.coerce_operands_to_pyobjects(env)
3783 if self.has_int_operands():
3784 self.coerce_chars_to_ints(env)
3785 if self.cascade:
3786 self.operand2 = self.operand2.coerce_to_simple(env)
3787 self.cascade.coerce_cascaded_operands_to_temp(env)
3788 self.check_operand_types(env)
3789 if self.is_python_result():
3790 self.type = PyrexTypes.py_object_type
3791 else:
3792 self.type = PyrexTypes.c_bint_type
3793 cdr = self.cascade
3794 while cdr:
3795 cdr.type = self.type
3796 cdr = cdr.cascade
3797 if self.is_pycmp or self.cascade:
3798 self.is_temp = 1
3800 def check_operand_types(self, env):
3801 self.check_types(env,
3802 self.operand1, self.operator, self.operand2)
3803 if self.cascade:
3804 self.cascade.check_operand_types(env, self.operand2)
3806 def has_python_operands(self):
3807 return (self.operand1.type.is_pyobject
3808 or self.operand2.type.is_pyobject)
3810 def coerce_operands_to_pyobjects(self, env):
3811 self.operand1 = self.operand1.coerce_to_pyobject(env)
3812 self.operand2 = self.operand2.coerce_to_pyobject(env)
3813 if self.cascade:
3814 self.cascade.coerce_operands_to_pyobjects(env)
3816 def has_int_operands(self):
3817 return (self.operand1.type.is_int or self.operand2.type.is_int) \
3818 or (self.cascade and self.cascade.has_int_operands())
3820 def coerce_chars_to_ints(self, env):
3821 # coerce literal single-char strings to c chars
3822 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
3823 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
3824 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
3825 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3826 if self.cascade:
3827 self.cascade.coerce_chars_to_ints(env)
3829 def allocate_subexpr_temps(self, env):
3830 self.operand1.allocate_temps(env)
3831 self.operand2.allocate_temps(env)
3832 if self.cascade:
3833 self.cascade.allocate_subexpr_temps(env)
3835 def release_subexpr_temps(self, env):
3836 self.operand1.release_temp(env)
3837 self.operand2.release_temp(env)
3838 if self.cascade:
3839 self.cascade.release_subexpr_temps(env)
3841 def check_const(self):
3842 self.operand1.check_const()
3843 self.operand2.check_const()
3844 if self.cascade:
3845 self.not_const()
3847 def calculate_result_code(self):
3848 return "(%s %s %s)" % (
3849 self.operand1.result(),
3850 self.c_operator(self.operator),
3851 self.operand2.result())
3853 def generate_evaluation_code(self, code):
3854 self.operand1.generate_evaluation_code(code)
3855 self.operand2.generate_evaluation_code(code)
3856 if self.is_temp:
3857 self.generate_operation_code(code, self.result(),
3858 self.operand1, self.operator, self.operand2)
3859 if self.cascade:
3860 self.cascade.generate_evaluation_code(code,
3861 self.result(), self.operand2)
3862 self.operand1.generate_disposal_code(code)
3863 self.operand2.generate_disposal_code(code)
3865 def generate_subexpr_disposal_code(self, code):
3866 # If this is called, it is a non-cascaded cmp,
3867 # so only need to dispose of the two main operands.
3868 self.operand1.generate_disposal_code(code)
3869 self.operand2.generate_disposal_code(code)
3871 def annotate(self, code):
3872 self.operand1.annotate(code)
3873 self.operand2.annotate(code)
3874 if self.cascade:
3875 self.cascade.annotate(code)
3878 class CascadedCmpNode(Node, CmpNode):
3879 # A CascadedCmpNode is not a complete expression node. It
3880 # hangs off the side of another comparison node, shares
3881 # its left operand with that node, and shares its result
3882 # with the PrimaryCmpNode at the head of the chain.
3884 # operator string
3885 # operand2 ExprNode
3886 # cascade CascadedCmpNode
3888 child_attrs = ['operand2', 'cascade']
3890 cascade = None
3892 def analyse_types(self, env, operand1):
3893 self.operand2.analyse_types(env)
3894 if self.cascade:
3895 self.cascade.analyse_types(env, self.operand2)
3897 def check_operand_types(self, env, operand1):
3898 self.check_types(env,
3899 operand1, self.operator, self.operand2)
3900 if self.cascade:
3901 self.cascade.check_operand_types(env, self.operand2)
3903 def has_python_operands(self):
3904 return self.operand2.type.is_pyobject
3906 def coerce_operands_to_pyobjects(self, env):
3907 self.operand2 = self.operand2.coerce_to_pyobject(env)
3908 if self.cascade:
3909 self.cascade.coerce_operands_to_pyobjects(env)
3911 def has_int_operands(self):
3912 return self.operand2.type.is_int
3914 def coerce_chars_to_ints(self, env):
3915 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
3916 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3918 def coerce_cascaded_operands_to_temp(self, env):
3919 if self.cascade:
3920 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
3921 self.operand2 = self.operand2.coerce_to_simple(env)
3922 self.cascade.coerce_cascaded_operands_to_temp(env)
3924 def allocate_subexpr_temps(self, env):
3925 self.operand2.allocate_temps(env)
3926 if self.cascade:
3927 self.cascade.allocate_subexpr_temps(env)
3929 def release_subexpr_temps(self, env):
3930 self.operand2.release_temp(env)
3931 if self.cascade:
3932 self.cascade.release_subexpr_temps(env)
3934 def generate_evaluation_code(self, code, result, operand1):
3935 if self.type.is_pyobject:
3936 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
3937 else:
3938 code.putln("if (%s) {" % result)
3939 self.operand2.generate_evaluation_code(code)
3940 self.generate_operation_code(code, result,
3941 operand1, self.operator, self.operand2)
3942 if self.cascade:
3943 self.cascade.generate_evaluation_code(
3944 code, result, self.operand2)
3945 # Cascaded cmp result is always temp
3946 self.operand2.generate_disposal_code(code)
3947 code.putln("}")
3949 def annotate(self, code):
3950 self.operand2.annotate(code)
3951 if self.cascade:
3952 self.cascade.annotate(code)
3955 binop_node_classes = {
3956 "or": BoolBinopNode,
3957 "and": BoolBinopNode,
3958 "|": IntBinopNode,
3959 "^": IntBinopNode,
3960 "&": IntBinopNode,
3961 "<<": IntBinopNode,
3962 ">>": IntBinopNode,
3963 "+": AddNode,
3964 "-": SubNode,
3965 "*": MulNode,
3966 "/": NumBinopNode,
3967 "//": FloorDivNode,
3968 "%": ModNode,
3969 "**": PowNode
3972 def binop_node(pos, operator, operand1, operand2):
3973 # Construct binop node of appropriate class for
3974 # given operator.
3975 return binop_node_classes[operator](pos,
3976 operator = operator,
3977 operand1 = operand1,
3978 operand2 = operand2)
3980 #-------------------------------------------------------------------
3982 # Coercion nodes
3984 # Coercion nodes are special in that they are created during
3985 # the analyse_types phase of parse tree processing.
3986 # Their __init__ methods consequently incorporate some aspects
3987 # of that phase.
3989 #-------------------------------------------------------------------
3991 class CoercionNode(ExprNode):
3992 # Abstract base class for coercion nodes.
3994 # arg ExprNode node being coerced
3996 subexprs = ['arg']
3998 def __init__(self, arg):
3999 self.pos = arg.pos
4000 self.arg = arg
4001 if debug_coercion:
4002 print("%s Coercing %s" % (self, self.arg))
4004 def annotate(self, code):
4005 self.arg.annotate(code)
4006 if self.arg.type != self.type:
4007 file, line, col = self.pos
4008 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
4011 class CastNode(CoercionNode):
4012 # Wrap a node in a C type cast.
4014 def __init__(self, arg, new_type):
4015 CoercionNode.__init__(self, arg)
4016 self.type = new_type
4018 def calculate_result_code(self):
4019 return self.arg.result_as(self.type)
4021 def generate_result_code(self, code):
4022 self.arg.generate_result_code(code)
4025 class PyTypeTestNode(CoercionNode):
4026 # This node is used to check that a generic Python
4027 # object is an instance of a particular extension type.
4028 # This node borrows the result of its argument node.
4030 def __init__(self, arg, dst_type, env):
4031 # The arg is know to be a Python object, and
4032 # the dst_type is known to be an extension type.
4033 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
4034 CoercionNode.__init__(self, arg)
4035 self.type = dst_type
4036 self.gil_check(env)
4037 self.result_ctype = arg.ctype()
4038 env.use_utility_code(type_test_utility_code)
4040 gil_message = "Python type test"
4042 def analyse_types(self, env):
4043 pass
4045 def result_in_temp(self):
4046 return self.arg.result_in_temp()
4048 def is_ephemeral(self):
4049 return self.arg.is_ephemeral()
4051 def calculate_result_code(self):
4052 return self.arg.result()
4054 def generate_result_code(self, code):
4055 if self.type.typeobj_is_available():
4056 code.putln(
4057 "if (!(%s)) %s" % (
4058 self.type.type_test_code(self.arg.py_result()),
4059 code.error_goto(self.pos)))
4060 else:
4061 error(self.pos, "Cannot test type of extern C class "
4062 "without type object name specification")
4064 def generate_post_assignment_code(self, code):
4065 self.arg.generate_post_assignment_code(code)
4068 class CoerceToPyTypeNode(CoercionNode):
4069 # This node is used to convert a C data type
4070 # to a Python object.
4072 def __init__(self, arg, env):
4073 CoercionNode.__init__(self, arg)
4074 self.type = py_object_type
4075 self.gil_check(env)
4076 self.is_temp = 1
4077 if not arg.type.to_py_function:
4078 error(arg.pos,
4079 "Cannot convert '%s' to Python object" % arg.type)
4081 gil_message = "Converting to Python object"
4083 def analyse_types(self, env):
4084 # The arg is always already analysed
4085 pass
4087 def generate_result_code(self, code):
4088 function = self.arg.type.to_py_function
4089 code.putln('%s = %s(%s); %s' % (
4090 self.result(),
4091 function,
4092 self.arg.result(),
4093 code.error_goto_if_null(self.result(), self.pos)))
4096 class CoerceFromPyTypeNode(CoercionNode):
4097 # This node is used to convert a Python object
4098 # to a C data type.
4100 def __init__(self, result_type, arg, env):
4101 CoercionNode.__init__(self, arg)
4102 self.type = result_type
4103 self.is_temp = 1
4104 if not result_type.from_py_function:
4105 error(arg.pos,
4106 "Cannot convert Python object to '%s'" % result_type)
4107 if self.type.is_string and self.arg.is_ephemeral():
4108 error(arg.pos,
4109 "Obtaining char * from temporary Python value")
4111 def analyse_types(self, env):
4112 # The arg is always already analysed
4113 pass
4115 def generate_result_code(self, code):
4116 function = self.type.from_py_function
4117 operand = self.arg.py_result()
4118 rhs = "%s(%s)" % (function, operand)
4119 if self.type.is_enum:
4120 rhs = typecast(self.type, c_long_type, rhs)
4121 code.putln('%s = %s; %s' % (
4122 self.result(),
4123 rhs,
4124 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
4127 class CoerceToBooleanNode(CoercionNode):
4128 # This node is used when a result needs to be used
4129 # in a boolean context.
4131 def __init__(self, arg, env):
4132 CoercionNode.__init__(self, arg)
4133 self.type = PyrexTypes.c_bint_type
4134 if arg.type.is_pyobject:
4135 if env.nogil:
4136 self.gil_error()
4137 self.is_temp = 1
4139 gil_message = "Truth-testing Python object"
4141 def check_const(self):
4142 if self.is_temp:
4143 self.not_const()
4144 self.arg.check_const()
4146 def calculate_result_code(self):
4147 return "(%s != 0)" % self.arg.result()
4149 def generate_result_code(self, code):
4150 if self.arg.type.is_pyobject:
4151 code.putln(
4152 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4153 self.result(),
4154 self.arg.py_result(),
4155 code.error_goto_if_neg(self.result(), self.pos)))
4158 class CoerceToTempNode(CoercionNode):
4159 # This node is used to force the result of another node
4160 # to be stored in a temporary. It is only used if the
4161 # argument node's result is not already in a temporary.
4163 def __init__(self, arg, env):
4164 CoercionNode.__init__(self, arg)
4165 self.type = self.arg.type
4166 self.is_temp = 1
4167 if self.type.is_pyobject:
4168 self.gil_check(env)
4169 self.result_ctype = py_object_type
4171 gil_message = "Creating temporary Python reference"
4173 def analyse_types(self, env):
4174 # The arg is always already analysed
4175 pass
4177 def generate_result_code(self, code):
4178 #self.arg.generate_evaluation_code(code) # Already done
4179 # by generic generate_subexpr_evaluation_code!
4180 code.putln("%s = %s;" % (
4181 self.result(), self.arg.result_as(self.ctype())))
4182 if self.type.is_pyobject:
4183 code.put_incref(self.result(), self.ctype())
4186 class CloneNode(CoercionNode):
4187 # This node is employed when the result of another node needs
4188 # to be used multiple times. The argument node's result must
4189 # be in a temporary. This node "borrows" the result from the
4190 # argument node, and does not generate any evaluation or
4191 # disposal code for it. The original owner of the argument
4192 # node is responsible for doing those things.
4194 subexprs = [] # Arg is not considered a subexpr
4196 def __init__(self, arg):
4197 CoercionNode.__init__(self, arg)
4198 if hasattr(arg, 'type'):
4199 self.type = arg.type
4200 self.result_ctype = arg.result_ctype
4201 if hasattr(arg, 'entry'):
4202 self.entry = arg.entry
4204 def calculate_result_code(self):
4205 return self.arg.result()
4207 def analyse_types(self, env):
4208 self.type = self.arg.type
4209 self.result_ctype = self.arg.result_ctype
4210 self.is_temp = 1
4211 if hasattr(self.arg, 'entry'):
4212 self.entry = self.arg.entry
4214 def generate_evaluation_code(self, code):
4215 pass
4217 def generate_result_code(self, code):
4218 pass
4220 def generate_disposal_code(self, code):
4221 pass
4223 def allocate_temps(self, env):
4224 self.result_code = self.calculate_result_code()
4226 def release_temp(self, env):
4227 pass
4229 class PersistentNode(ExprNode):
4230 # A PersistentNode is like a CloneNode except it handles the temporary
4231 # allocation itself by keeping track of the number of times it has been
4232 # used.
4234 subexprs = ["arg"]
4235 temp_counter = 0
4236 generate_counter = 0
4237 analyse_counter = 0
4238 result_code = None
4240 def __init__(self, arg, uses):
4241 self.pos = arg.pos
4242 self.arg = arg
4243 self.uses = uses
4245 def analyse_types(self, env):
4246 if self.analyse_counter == 0:
4247 self.arg.analyse_types(env)
4248 self.type = self.arg.type
4249 self.result_ctype = self.arg.result_ctype
4250 self.is_temp = 1
4251 self.analyse_counter += 1
4253 def calculate_result_code(self):
4254 return self.result()
4256 def generate_evaluation_code(self, code):
4257 if self.generate_counter == 0:
4258 self.arg.generate_evaluation_code(code)
4259 code.putln("%s = %s;" % (
4260 self.result(), self.arg.result_as(self.ctype())))
4261 if self.type.is_pyobject:
4262 code.put_incref(self.result(), self.ctype())
4263 self.arg.generate_disposal_code(code)
4264 self.generate_counter += 1
4266 def generate_disposal_code(self, code):
4267 if self.generate_counter == self.uses:
4268 if self.type.is_pyobject:
4269 code.put_decref_clear(self.result(), self.ctype())
4271 def allocate_temps(self, env, result=None):
4272 if self.temp_counter == 0:
4273 self.arg.allocate_temps(env)
4274 self.allocate_temp(env, result)
4275 self.arg.release_temp(env)
4276 self.temp_counter += 1
4278 def allocate_temp(self, env, result=None):
4279 if result is None:
4280 self.result_code = env.allocate_temp(self.type)
4281 else:
4282 self.result_code = result
4284 def release_temp(self, env):
4285 if self.temp_counter == self.uses:
4286 env.release_temp(self.result())
4288 #------------------------------------------------------------------------------------
4290 # Runtime support code
4292 #------------------------------------------------------------------------------------
4294 get_name_interned_utility_code = [
4295 """
4296 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
4297 ""","""
4298 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
4299 PyObject *result;
4300 result = PyObject_GetAttr(dict, name);
4301 if (!result)
4302 PyErr_SetObject(PyExc_NameError, name);
4303 return result;
4305 """]
4307 #------------------------------------------------------------------------------------
4309 import_utility_code = [
4310 """
4311 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
4312 ""","""
4313 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
4314 PyObject *__import__ = 0;
4315 PyObject *empty_list = 0;
4316 PyObject *module = 0;
4317 PyObject *global_dict = 0;
4318 PyObject *empty_dict = 0;
4319 PyObject *list;
4320 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
4321 if (!__import__)
4322 goto bad;
4323 if (from_list)
4324 list = from_list;
4325 else {
4326 empty_list = PyList_New(0);
4327 if (!empty_list)
4328 goto bad;
4329 list = empty_list;
4331 global_dict = PyModule_GetDict(%(GLOBALS)s);
4332 if (!global_dict)
4333 goto bad;
4334 empty_dict = PyDict_New();
4335 if (!empty_dict)
4336 goto bad;
4337 module = PyObject_CallFunction(__import__, "OOOO",
4338 name, global_dict, empty_dict, list);
4339 bad:
4340 Py_XDECREF(empty_list);
4341 Py_XDECREF(__import__);
4342 Py_XDECREF(empty_dict);
4343 return module;
4345 """ % {
4346 "BUILTINS": Naming.builtins_cname,
4347 "GLOBALS": Naming.module_cname,
4348 }]
4350 #------------------------------------------------------------------------------------
4352 get_exception_utility_code = [
4353 """
4354 static PyObject *__Pyx_GetExcValue(void); /*proto*/
4355 ""","""
4356 static PyObject *__Pyx_GetExcValue(void) {
4357 PyObject *type = 0, *value = 0, *tb = 0;
4358 PyObject *tmp_type, *tmp_value, *tmp_tb;
4359 PyObject *result = 0;
4360 PyThreadState *tstate = PyThreadState_Get();
4361 PyErr_Fetch(&type, &value, &tb);
4362 PyErr_NormalizeException(&type, &value, &tb);
4363 if (PyErr_Occurred())
4364 goto bad;
4365 if (!value) {
4366 value = Py_None;
4367 Py_INCREF(value);
4369 tmp_type = tstate->exc_type;
4370 tmp_value = tstate->exc_value;
4371 tmp_tb = tstate->exc_traceback;
4372 tstate->exc_type = type;
4373 tstate->exc_value = value;
4374 tstate->exc_traceback = tb;
4375 /* Make sure tstate is in a consistent state when we XDECREF
4376 these objects (XDECREF may run arbitrary code). */
4377 Py_XDECREF(tmp_type);
4378 Py_XDECREF(tmp_value);
4379 Py_XDECREF(tmp_tb);
4380 result = value;
4381 Py_XINCREF(result);
4382 type = 0;
4383 value = 0;
4384 tb = 0;
4385 bad:
4386 Py_XDECREF(type);
4387 Py_XDECREF(value);
4388 Py_XDECREF(tb);
4389 return result;
4391 """]
4393 #------------------------------------------------------------------------------------
4395 unpacking_utility_code = [
4396 """
4397 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
4398 static int __Pyx_EndUnpack(PyObject *); /*proto*/
4399 ""","""
4400 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
4401 PyObject *item;
4402 if (!(item = PyIter_Next(iter))) {
4403 if (!PyErr_Occurred()) {
4404 PyErr_Format(PyExc_ValueError,
4405 #if PY_VERSION_HEX < 0x02050000
4406 "need more than %d values to unpack", (int)index);
4407 #else
4408 "need more than %zd values to unpack", index);
4409 #endif
4412 return item;
4415 static int __Pyx_EndUnpack(PyObject *iter) {
4416 PyObject *item;
4417 if ((item = PyIter_Next(iter))) {
4418 Py_DECREF(item);
4419 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
4420 return -1;
4422 else if (!PyErr_Occurred())
4423 return 0;
4424 else
4425 return -1;
4427 """]
4429 #------------------------------------------------------------------------------------
4431 type_test_utility_code = [
4432 """
4433 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
4434 ""","""
4435 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
4436 if (!type) {
4437 PyErr_Format(PyExc_SystemError, "Missing type object");
4438 return 0;
4440 if (obj == Py_None || PyObject_TypeCheck(obj, type))
4441 return 1;
4442 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
4443 Py_TYPE(obj)->tp_name, type->tp_name);
4444 return 0;
4446 """]
4448 #------------------------------------------------------------------------------------
4450 create_class_utility_code = [
4451 """
4452 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
4453 ""","""
4454 static PyObject *__Pyx_CreateClass(
4455 PyObject *bases, PyObject *dict, PyObject *name, char *modname)
4457 PyObject *py_modname;
4458 PyObject *result = 0;
4460 #if PY_MAJOR_VERSION < 3
4461 py_modname = PyString_FromString(modname);
4462 #else
4463 py_modname = PyUnicode_FromString(modname);
4464 #endif
4465 if (!py_modname)
4466 goto bad;
4467 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
4468 goto bad;
4469 #if PY_MAJOR_VERSION < 3
4470 result = PyClass_New(bases, dict, name);
4471 #else
4472 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
4473 #endif
4474 bad:
4475 Py_XDECREF(py_modname);
4476 return result;
4478 """]
4480 #------------------------------------------------------------------------------------
4482 cpp_exception_utility_code = [
4483 """
4484 #ifndef __Pyx_CppExn2PyErr
4485 static void __Pyx_CppExn2PyErr() {
4486 try {
4487 if (PyErr_Occurred())
4488 ; // let the latest Python exn pass through and ignore the current one
4489 else
4490 throw;
4491 } catch (const std::out_of_range& exn) {
4492 // catch out_of_range explicitly so the proper Python exn may be raised
4493 PyErr_SetString(PyExc_IndexError, exn.what());
4494 } catch (const std::exception& exn) {
4495 PyErr_SetString(PyExc_RuntimeError, exn.what());
4497 catch (...)
4499 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
4502 #endif
4503 """,""]
4505 #------------------------------------------------------------------------------------
4507 append_utility_code = [
4508 """
4509 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
4510 if (likely(PyList_CheckExact(L))) {
4511 if (PyList_Append(L, x) < 0) return NULL;
4512 Py_INCREF(Py_None);
4513 return Py_None; // this is just to have an accurate signature
4515 else {
4516 return PyObject_CallMethod(L, "append", "(O)", x);
4519 """,""
4522 #------------------------------------------------------------------------------------
4524 # If the is_unsigned flag is set, we need to do some extra work to make
4525 # sure the index doesn't become negative.
4527 getitem_int_utility_code = [
4528 """
4529 static INLINE PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
4530 PyObject *r;
4531 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
4532 r = PyList_GET_ITEM(o, i);
4533 Py_INCREF(r);
4535 else if (PyTuple_CheckExact(o) && 0 <= i && i < PyTuple_GET_SIZE(o)) {
4536 r = PyTuple_GET_ITEM(o, i);
4537 Py_INCREF(r);
4539 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0) || !is_unsigned))
4540 r = PySequence_GetItem(o, i);
4541 else {
4542 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);
4543 if (!j)
4544 return 0;
4545 r = PyObject_GetItem(o, j);
4546 Py_DECREF(j);
4548 return r;
4550 """,
4551 """
4552 """]
4554 #------------------------------------------------------------------------------------
4556 setitem_int_utility_code = [
4557 """
4558 static INLINE int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v, int is_unsigned) {
4559 int r;
4560 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
4561 Py_DECREF(PyList_GET_ITEM(o, i));
4562 Py_INCREF(v);
4563 PyList_SET_ITEM(o, i, v);
4564 return 1;
4566 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
4567 r = PySequence_SetItem(o, i, v);
4568 else {
4569 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);
4570 if (!j)
4571 return -1;
4572 r = PyObject_SetItem(o, j, v);
4573 Py_DECREF(j);
4575 return r;
4577 """,
4578 """
4579 """]
4580 #------------------------------------------------------------------------------------
4582 raise_noneattr_error_utility_code = [
4583 """
4584 static INLINE void __Pyx_RaiseNoneAttributeError(char* attrname);
4585 """, """
4586 static INLINE void __Pyx_RaiseNoneAttributeError(char* attrname) {
4587 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
4589 """]