Cython has moved to github.
cython-devel
view Cython/Compiler/ExprNodes.py @ 1064:9d489341f992
sizeof() works on cdef attributes and cimported types
| author | Robert Bradshaw <robertwb@math.washington.edu> |
|---|---|
| date | Sat Aug 16 16:30:15 2008 -0700 (3 years ago) |
| parents | c4007b987ae9 |
| children | f58bacff008d 4d543e06c926 |
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 # calculate_result_code
107 # - Called during the Allocate Temps phase. Should return a
108 # C code fragment evaluating to the result. This is only
109 # called when the result is not a temporary.
110 #
111 # target_code
112 # Called by the default implementation of allocate_target_temps.
113 # Should return a C lvalue for assigning to the node. The default
114 # implementation calls calculate_result_code.
115 #
116 # check_const
117 # - Check that this node and its subnodes form a
118 # legal constant expression. If so, do nothing,
119 # otherwise call not_const.
120 #
121 # The default implementation of check_const
122 # assumes that the expression is not constant.
123 #
124 # check_const_addr
125 # - Same as check_const, except check that the
126 # expression is a C lvalue whose address is
127 # constant. Otherwise, call addr_not_const.
128 #
129 # The default implementation of calc_const_addr
130 # assumes that the expression is not a constant
131 # lvalue.
132 #
133 # Code Generation phase
134 #
135 # generate_evaluation_code
136 # - Call generate_evaluation_code for sub-expressions.
137 # - Perform the functions of generate_result_code
138 # (see below).
139 # - If result is temporary, call generate_disposal_code
140 # on all sub-expressions.
141 #
142 # A default implementation of generate_evaluation_code
143 # is provided which uses the following abstract method:
144 #
145 # generate_result_code
146 # - Generate any C statements necessary to calculate
147 # the result of this node from the results of its
148 # sub-expressions.
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_as(self, type = None):
209 # Return the result code cast to the specified C type.
210 return typecast(type, self.ctype(), self.result_code)
212 def py_result(self):
213 # Return the result code cast to PyObject *.
214 return self.result_as(py_object_type)
216 def ctype(self):
217 # Return the native C type of the result (i.e. the
218 # C type of the result_code expression).
219 return self.result_ctype or self.type
221 def compile_time_value(self, denv):
222 # Return value of compile-time expression, or report error.
223 error(self.pos, "Invalid compile-time expression")
225 def compile_time_value_error(self, e):
226 error(self.pos, "Error in compile-time expression: %s: %s" % (
227 e.__class__.__name__, e))
229 # ------------- Declaration Analysis ----------------
231 def analyse_target_declaration(self, env):
232 error(self.pos, "Cannot assign to or delete this")
234 # ------------- Expression Analysis ----------------
236 def analyse_const_expression(self, env):
237 # Called during the analyse_declarations phase of a
238 # constant expression. Analyses the expression's type,
239 # checks whether it is a legal const expression,
240 # and determines its value.
241 self.analyse_types(env)
242 self.allocate_temps(env)
243 self.check_const()
245 def analyse_expressions(self, env):
246 # Convenience routine performing both the Type
247 # Analysis and Temp Allocation phases for a whole
248 # expression.
249 self.analyse_types(env)
250 self.allocate_temps(env)
252 def analyse_target_expression(self, env, rhs):
253 # Convenience routine performing both the Type
254 # Analysis and Temp Allocation phases for the LHS of
255 # an assignment.
256 self.analyse_target_types(env)
257 self.allocate_target_temps(env, rhs)
259 def analyse_boolean_expression(self, env):
260 # Analyse expression and coerce to a boolean.
261 self.analyse_types(env)
262 bool = self.coerce_to_boolean(env)
263 bool.allocate_temps(env)
264 return bool
266 def analyse_temp_boolean_expression(self, env):
267 # Analyse boolean expression and coerce result into
268 # a temporary. This is used when a branch is to be
269 # performed on the result and we won't have an
270 # opportunity to ensure disposal code is executed
271 # afterwards. By forcing the result into a temporary,
272 # we ensure that all disposal has been done by the
273 # time we get the result.
274 self.analyse_types(env)
275 bool = self.coerce_to_boolean(env)
276 temp_bool = bool.coerce_to_temp(env)
277 temp_bool.allocate_temps(env)
278 return temp_bool
280 # --------------- Type Analysis ------------------
282 def analyse_as_module(self, env):
283 # If this node can be interpreted as a reference to a
284 # cimported module, return its scope, else None.
285 return None
287 def analyse_as_extension_type(self, env):
288 # If this node can be interpreted as a reference to an
289 # extension type, return its type, else None.
290 return None
292 def analyse_types(self, env):
293 self.not_implemented("analyse_types")
295 def analyse_target_types(self, env):
296 self.analyse_types(env)
298 def gil_assignment_check(self, env):
299 if env.nogil and self.type.is_pyobject:
300 error(self.pos, "Assignment of Python object not allowed without gil")
302 def check_const(self):
303 self.not_const()
305 def not_const(self):
306 error(self.pos, "Not allowed in a constant expression")
308 def check_const_addr(self):
309 self.addr_not_const()
311 def addr_not_const(self):
312 error(self.pos, "Address is not constant")
314 def gil_check(self, env):
315 if env.nogil and self.type.is_pyobject:
316 self.gil_error()
318 # ----------------- Result Allocation -----------------
320 def result_in_temp(self):
321 # Return true if result is in a temporary owned by
322 # this node or one of its subexpressions. Overridden
323 # by certain nodes which can share the result of
324 # a subnode.
325 return self.is_temp
327 def allocate_target_temps(self, env, rhs):
328 # Perform temp allocation for the LHS of an assignment.
329 if debug_temp_alloc:
330 print("%s Allocating target temps" % self)
331 self.allocate_subexpr_temps(env)
332 self.result_code = self.target_code()
333 if rhs:
334 rhs.release_temp(env)
335 self.release_subexpr_temps(env)
337 def allocate_temps(self, env, result = None):
338 # Allocate temporary variables for this node and
339 # all its sub-expressions. If a result is specified,
340 # this must be a temp node and the specified variable
341 # is used as the result instead of allocating a new
342 # one.
343 if debug_temp_alloc:
344 print("%s Allocating temps" % self)
345 self.allocate_subexpr_temps(env)
346 self.allocate_temp(env, result)
347 if self.is_temp:
348 self.release_subexpr_temps(env)
350 def allocate_subexpr_temps(self, env):
351 # Allocate temporary variables for all sub-expressions
352 # of this node.
353 if debug_temp_alloc:
354 print("%s Allocating temps for: %s" % (self, self.subexprs))
355 for node in self.subexpr_nodes():
356 if node:
357 if debug_temp_alloc:
358 print("%s Allocating temps for %s" % (self, node))
359 node.allocate_temps(env)
361 def allocate_temp(self, env, result = None):
362 # If this node requires a temporary variable for its
363 # result, allocate one, otherwise set the result to
364 # a C code fragment. If a result is specified,
365 # this must be a temp node and the specified variable
366 # is used as the result instead of allocating a new
367 # one.
368 if debug_temp_alloc:
369 print("%s Allocating temp" % self)
370 if result:
371 if not self.is_temp:
372 raise InternalError("Result forced on non-temp node")
373 self.result_code = result
374 elif self.is_temp:
375 type = self.type
376 if not type.is_void:
377 if type.is_pyobject:
378 type = PyrexTypes.py_object_type
379 self.result_code = env.allocate_temp(type)
380 else:
381 self.result_code = None
382 if debug_temp_alloc:
383 print("%s Allocated result %s" % (self, self.result_code))
384 else:
385 self.result_code = self.calculate_result_code()
387 def target_code(self):
388 # Return code fragment for use as LHS of a C assignment.
389 return self.calculate_result_code()
391 def calculate_result_code(self):
392 self.not_implemented("calculate_result_code")
394 # def release_target_temp(self, env):
395 # # Release temporaries used by LHS of an assignment.
396 # self.release_subexpr_temps(env)
398 def release_temp(self, env):
399 # If this node owns a temporary result, release it,
400 # otherwise release results of its sub-expressions.
401 if self.is_temp:
402 if debug_temp_alloc:
403 print("%s Releasing result %s" % (self, self.result_code))
404 env.release_temp(self.result_code)
405 else:
406 self.release_subexpr_temps(env)
408 def release_subexpr_temps(self, env):
409 # Release the results of all sub-expressions of
410 # this node.
411 for node in self.subexpr_nodes():
412 if node:
413 node.release_temp(env)
415 # ---------------- Code Generation -----------------
417 def make_owned_reference(self, code):
418 # If result is a pyobject, make sure we own
419 # a reference to it.
420 if self.type.is_pyobject and not self.result_in_temp():
421 code.put_incref(self.result_code, self.ctype())
423 def generate_evaluation_code(self, code):
424 code.mark_pos(self.pos)
425 # Generate code to evaluate this node and
426 # its sub-expressions, and dispose of any
427 # temporary results of its sub-expressions.
428 self.generate_subexpr_evaluation_code(code)
429 self.generate_result_code(code)
430 if self.is_temp:
431 self.generate_subexpr_disposal_code(code)
433 def generate_subexpr_evaluation_code(self, code):
434 for node in self.subexpr_nodes():
435 node.generate_evaluation_code(code)
437 def generate_result_code(self, code):
438 self.not_implemented("generate_result_code")
440 def generate_disposal_code(self, code):
441 # If necessary, generate code to dispose of
442 # temporary Python reference.
443 if self.is_temp:
444 if self.type.is_pyobject:
445 code.put_decref_clear(self.result_code, self.ctype())
446 else:
447 self.generate_subexpr_disposal_code(code)
449 def generate_subexpr_disposal_code(self, code):
450 # Generate code to dispose of temporary results
451 # of all sub-expressions.
452 for node in self.subexpr_nodes():
453 node.generate_disposal_code(code)
455 def generate_post_assignment_code(self, code):
456 # Same as generate_disposal_code except that
457 # assignment will have absorbed a reference to
458 # the result if it is a Python object.
459 if self.is_temp:
460 if self.type.is_pyobject:
461 code.putln("%s = 0;" % self.result_code)
462 else:
463 self.generate_subexpr_disposal_code(code)
465 def generate_assignment_code(self, rhs, code):
466 # Stub method for nodes which are not legal as
467 # the LHS of an assignment. An error will have
468 # been reported earlier.
469 pass
471 def generate_deletion_code(self, code):
472 # Stub method for nodes that are not legal as
473 # the argument of a del statement. An error
474 # will have been reported earlier.
475 pass
477 # ---------------- Annotation ---------------------
479 def annotate(self, code):
480 for node in self.subexpr_nodes():
481 node.annotate(code)
483 # ----------------- Coercion ----------------------
485 def coerce_to(self, dst_type, env):
486 # Coerce the result so that it can be assigned to
487 # something of type dst_type. If processing is necessary,
488 # wraps this node in a coercion node and returns that.
489 # Otherwise, returns this node unchanged.
490 #
491 # This method is called during the analyse_expressions
492 # phase of the src_node's processing.
493 src = self
494 src_type = self.type
495 src_is_py_type = src_type.is_pyobject
496 dst_is_py_type = dst_type.is_pyobject
498 if dst_type.is_pyobject:
499 if not src.type.is_pyobject:
500 src = CoerceToPyTypeNode(src, env)
501 if not src.type.subtype_of(dst_type):
502 if not isinstance(src, NoneNode):
503 src = PyTypeTestNode(src, dst_type, env)
504 elif src.type.is_pyobject:
505 src = CoerceFromPyTypeNode(dst_type, src, env)
506 else: # neither src nor dst are py types
507 # Added the string comparison, since for c types that
508 # is enough, but Cython gets confused when the types are
509 # in different files.
510 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
511 error(self.pos, "Cannot assign type '%s' to '%s'" %
512 (src.type, dst_type))
513 return src
515 def coerce_to_pyobject(self, env):
516 return self.coerce_to(PyrexTypes.py_object_type, env)
518 def coerce_to_boolean(self, env):
519 # Coerce result to something acceptable as
520 # a boolean value.
521 type = self.type
522 if type.is_pyobject or type.is_ptr or type.is_float:
523 return CoerceToBooleanNode(self, env)
524 else:
525 if not type.is_int and not type.is_error:
526 error(self.pos,
527 "Type '%s' not acceptable as a boolean" % type)
528 return self
530 def coerce_to_integer(self, env):
531 # If not already some C integer type, coerce to longint.
532 if self.type.is_int:
533 return self
534 else:
535 return self.coerce_to(PyrexTypes.c_long_type, env)
537 def coerce_to_temp(self, env):
538 # Ensure that the result is in a temporary.
539 if self.result_in_temp():
540 return self
541 else:
542 return CoerceToTempNode(self, env)
544 def coerce_to_simple(self, env):
545 # Ensure that the result is simple (see is_simple).
546 if self.is_simple():
547 return self
548 else:
549 return self.coerce_to_temp(env)
551 def is_simple(self):
552 # A node is simple if its result is something that can
553 # be referred to without performing any operations, e.g.
554 # a constant, local var, C global var, struct member
555 # reference, or temporary.
556 return self.result_in_temp()
559 class AtomicExprNode(ExprNode):
560 # Abstract base class for expression nodes which have
561 # no sub-expressions.
563 subexprs = []
566 class PyConstNode(AtomicExprNode):
567 # Abstract base class for constant Python values.
569 is_literal = 1
571 def is_simple(self):
572 return 1
574 def analyse_types(self, env):
575 self.type = py_object_type
577 def calculate_result_code(self):
578 return self.value
580 def generate_result_code(self, code):
581 pass
584 class NoneNode(PyConstNode):
585 # The constant value None
587 value = "Py_None"
589 def compile_time_value(self, denv):
590 return None
592 class EllipsisNode(PyConstNode):
593 # '...' in a subscript list.
595 value = "Py_Ellipsis"
597 def compile_time_value(self, denv):
598 return Ellipsis
601 class ConstNode(AtomicExprNode):
602 # Abstract base type for literal constant nodes.
603 #
604 # value string C code fragment
606 is_literal = 1
608 def is_simple(self):
609 return 1
611 def analyse_types(self, env):
612 pass # Types are held in class variables
614 def check_const(self):
615 pass
617 def calculate_result_code(self):
618 return str(self.value)
620 def generate_result_code(self, code):
621 pass
624 class BoolNode(ConstNode):
625 type = PyrexTypes.c_bint_type
626 # The constant value True or False
628 def compile_time_value(self, denv):
629 return self.value
631 def calculate_result_code(self):
632 return str(int(self.value))
634 class NullNode(ConstNode):
635 type = PyrexTypes.c_null_ptr_type
636 value = "NULL"
639 class CharNode(ConstNode):
640 type = PyrexTypes.c_char_type
642 def compile_time_value(self, denv):
643 return ord(self.value)
645 def calculate_result_code(self):
646 return "'%s'" % StringEncoding.escape_character(self.value)
649 class IntNode(ConstNode):
651 # unsigned "" or "U"
652 # longness "" or "L" or "LL"
654 unsigned = ""
655 longness = ""
656 type = PyrexTypes.c_long_type
658 def coerce_to(self, dst_type, env):
659 # Arrange for a Python version of the string to be pre-allocated
660 # when coercing to a Python type.
661 if dst_type.is_pyobject:
662 self.entry = env.get_py_num(self.value, self.longness)
663 self.type = PyrexTypes.py_object_type
664 # We still need to perform normal coerce_to processing on the
665 # result, because we might be coercing to an extension type,
666 # in which case a type test node will be needed.
667 return ConstNode.coerce_to(self, dst_type, env)
669 def calculate_result_code(self):
670 if self.type.is_pyobject:
671 return self.entry.cname
672 else:
673 return str(self.value) + self.unsigned + self.longness
675 def compile_time_value(self, denv):
676 return int(self.value, 0)
679 class FloatNode(ConstNode):
680 type = PyrexTypes.c_double_type
682 def compile_time_value(self, denv):
683 return float(self.value)
685 def calculate_result_code(self):
686 strval = str(self.value)
687 if strval == 'nan':
688 return "(Py_HUGE_VAL * 0)"
689 elif strval == 'inf':
690 return "Py_HUGE_VAL"
691 elif strval == '-inf':
692 return "(-Py_HUGE_VAL)"
693 else:
694 return strval
697 class StringNode(ConstNode):
698 # entry Symtab.Entry
700 type = PyrexTypes.c_char_ptr_type
702 def compile_time_value(self, denv):
703 return self.value
705 def analyse_types(self, env):
706 self.entry = env.add_string_const(self.value)
708 def coerce_to(self, dst_type, env):
709 if dst_type.is_int:
710 if not self.type.is_pyobject and len(self.entry.init) == 1:
711 return CharNode(self.pos, value=self.value)
712 else:
713 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
714 return self
715 # Arrange for a Python version of the string to be pre-allocated
716 # when coercing to a Python type.
717 if dst_type.is_pyobject and not self.type.is_pyobject:
718 node = self.as_py_string_node(env)
719 else:
720 node = self
721 # We still need to perform normal coerce_to processing on the
722 # result, because we might be coercing to an extension type,
723 # in which case a type test node will be needed.
724 return ConstNode.coerce_to(node, dst_type, env)
726 def as_py_string_node(self, env):
727 # Return a new StringNode with the same entry as this node
728 # but whose type is a Python type instead of a C type.
729 entry = self.entry
730 env.add_py_string(entry)
731 return StringNode(self.pos, entry = entry, type = py_object_type)
733 def calculate_result_code(self):
734 if self.type.is_pyobject:
735 return self.entry.pystring_cname
736 else:
737 return self.entry.cname
740 class UnicodeNode(PyConstNode):
741 # entry Symtab.Entry
743 type = unicode_type
745 def analyse_types(self, env):
746 self.entry = env.add_string_const(self.value)
747 env.add_py_string(self.entry)
749 def calculate_result_code(self):
750 return self.entry.pystring_cname
752 def _coerce_to(self, dst_type, env):
753 if not dst_type.is_pyobject:
754 node = StringNode(self.pos, entry = entry, type = py_object_type)
755 return ConstNode.coerce_to(node, dst_type, env)
756 else:
757 return self
758 # We still need to perform normal coerce_to processing on the
759 # result, because we might be coercing to an extension type,
760 # in which case a type test node will be needed.
762 def compile_time_value(self, env):
763 return self.value
766 class IdentifierStringNode(ConstNode):
767 # A Python string that behaves like an identifier, e.g. for
768 # keyword arguments in a call, or for imported names
769 type = PyrexTypes.py_object_type
771 def analyse_types(self, env):
772 self.cname = env.intern_identifier(self.value)
774 def calculate_result_code(self):
775 return self.cname
778 class LongNode(AtomicExprNode):
779 # Python long integer literal
780 #
781 # value string
783 def compile_time_value(self, denv):
784 return long(self.value)
786 gil_message = "Constructing Python long int"
788 def analyse_types(self, env):
789 self.type = py_object_type
790 self.gil_check(env)
791 self.is_temp = 1
793 gil_message = "Constructing Python long int"
795 def generate_evaluation_code(self, code):
796 code.putln(
797 '%s = PyLong_FromString("%s", 0, 0); %s' % (
798 self.result_code,
799 self.value,
800 code.error_goto_if_null(self.result_code, self.pos)))
803 class ImagNode(AtomicExprNode):
804 # Imaginary number literal
805 #
806 # value float imaginary part
808 def compile_time_value(self, denv):
809 return complex(0.0, self.value)
811 def analyse_types(self, env):
812 self.type = py_object_type
813 self.gil_check(env)
814 self.is_temp = 1
816 gil_message = "Constructing complex number"
818 def generate_evaluation_code(self, code):
819 code.putln(
820 "%s = PyComplex_FromDoubles(0.0, %s); %s" % (
821 self.result_code,
822 self.value,
823 code.error_goto_if_null(self.result_code, self.pos)))
826 class NameNode(AtomicExprNode):
827 # Reference to a local or global variable name.
828 #
829 # name string Python name of the variable
830 #
831 # entry Entry Symbol table entry
832 # interned_cname string
834 is_name = 1
835 skip_assignment_decref = False
836 entry = None
838 def create_analysed_rvalue(pos, env, entry):
839 node = NameNode(pos)
840 node.analyse_types(env, entry=entry)
841 return node
843 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
845 def compile_time_value(self, denv):
846 try:
847 return denv.lookup(self.name)
848 except KeyError:
849 error(self.pos, "Compile-time name '%s' not defined" % self.name)
851 def coerce_to(self, dst_type, env):
852 # If coercing to a generic pyobject and this is a builtin
853 # C function with a Python equivalent, manufacture a NameNode
854 # referring to the Python builtin.
855 #print "NameNode.coerce_to:", self.name, dst_type ###
856 if dst_type is py_object_type:
857 entry = self.entry
858 if entry and entry.is_cfunction:
859 var_entry = entry.as_variable
860 if var_entry:
861 if var_entry.is_builtin and Options.cache_builtins:
862 var_entry = env.declare_builtin(var_entry.name, self.pos)
863 node = NameNode(self.pos, name = self.name)
864 node.entry = var_entry
865 node.analyse_rvalue_entry(env)
866 return node
867 return AtomicExprNode.coerce_to(self, dst_type, env)
869 def analyse_as_module(self, env):
870 # Try to interpret this as a reference to a cimported module.
871 # Returns the module scope, or None.
872 entry = self.entry
873 if not entry:
874 entry = env.lookup(self.name)
875 if entry and entry.as_module:
876 return entry.as_module
877 return None
879 def analyse_as_extension_type(self, env):
880 # Try to interpret this as a reference to an extension type.
881 # Returns the extension type, or None.
882 entry = self.entry
883 if not entry:
884 entry = env.lookup(self.name)
885 if entry and entry.is_type and entry.type.is_extension_type:
886 return entry.type
887 else:
888 return None
890 def analyse_target_declaration(self, env):
891 if not self.entry:
892 self.entry = env.lookup_here(self.name)
893 if not self.entry:
894 self.entry = env.declare_var(self.name, py_object_type, self.pos)
895 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
896 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
897 if self.entry.is_declared_generic:
898 self.result_ctype = py_object_type
900 def analyse_types(self, env):
901 if self.entry is None:
902 self.entry = env.lookup(self.name)
903 if not self.entry:
904 self.entry = env.declare_builtin(self.name, self.pos)
905 if not self.entry:
906 self.type = PyrexTypes.error_type
907 return
908 self.analyse_rvalue_entry(env)
910 def analyse_target_types(self, env):
911 self.analyse_entry(env)
912 if not self.is_lvalue():
913 error(self.pos, "Assignment to non-lvalue '%s'"
914 % self.name)
915 self.type = PyrexTypes.error_type
916 self.entry.used = 1
917 if self.entry.type.is_buffer:
918 import Buffer
919 Buffer.used_buffer_aux_vars(self.entry)
921 def analyse_rvalue_entry(self, env):
922 #print "NameNode.analyse_rvalue_entry:", self.name ###
923 #print "Entry:", self.entry.__dict__ ###
924 self.analyse_entry(env)
925 entry = self.entry
926 if entry.is_declared_generic:
927 self.result_ctype = py_object_type
928 if entry.is_pyglobal or entry.is_builtin:
929 if Options.cache_builtins and entry.is_builtin:
930 self.is_temp = 0
931 else:
932 self.is_temp = 1
933 env.use_utility_code(get_name_interned_utility_code)
934 self.gil_check(env)
936 gil_message = "Accessing Python global or builtin"
938 def analyse_entry(self, env):
939 #print "NameNode.analyse_entry:", self.name ###
940 self.check_identifier_kind()
941 entry = self.entry
942 type = entry.type
943 self.type = type
944 if entry.is_pyglobal or entry.is_builtin:
945 assert type.is_pyobject, "Python global or builtin not a Python object"
946 self.interned_cname = self.entry.interned_cname = \
947 env.intern_identifier(self.entry.name)
949 def check_identifier_kind(self):
950 #print "NameNode.check_identifier_kind:", self.entry.name ###
951 #print self.entry.__dict__ ###
952 entry = self.entry
953 #entry.used = 1
954 if not (entry.is_const or entry.is_variable
955 or entry.is_builtin or entry.is_cfunction):
956 if self.entry.as_variable:
957 self.entry = self.entry.as_variable
958 else:
959 error(self.pos,
960 "'%s' is not a constant, variable or function identifier" % self.name)
962 def is_simple(self):
963 # If it's not a C variable, it'll be in a temp.
964 return 1
966 def calculate_target_results(self, env):
967 pass
969 def check_const(self):
970 entry = self.entry
971 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
972 self.not_const()
974 def check_const_addr(self):
975 entry = self.entry
976 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
977 self.addr_not_const()
979 def is_lvalue(self):
980 return self.entry.is_variable and \
981 not self.entry.type.is_array and \
982 not self.entry.is_readonly
984 def is_ephemeral(self):
985 # Name nodes are never ephemeral, even if the
986 # result is in a temporary.
987 return 0
989 def allocate_temp(self, env, result = None):
990 AtomicExprNode.allocate_temp(self, env, result)
991 entry = self.entry
992 if entry:
993 entry.used = 1
994 if entry.type.is_buffer:
995 import Buffer
996 Buffer.used_buffer_aux_vars(entry)
997 if entry.utility_code:
998 env.use_utility_code(entry.utility_code)
1000 def calculate_result_code(self):
1001 entry = self.entry
1002 if not entry:
1003 return "<error>" # There was an error earlier
1004 return entry.cname
1006 def generate_result_code(self, code):
1007 assert hasattr(self, 'entry')
1008 entry = self.entry
1009 if entry is None:
1010 return # There was an error earlier
1011 if entry.is_builtin and Options.cache_builtins:
1012 return # Lookup already cached
1013 elif entry.is_pyglobal or entry.is_builtin:
1014 if entry.is_builtin:
1015 namespace = Naming.builtins_cname
1016 else: # entry.is_pyglobal
1017 namespace = entry.scope.namespace_cname
1018 code.putln(
1019 '%s = __Pyx_GetName(%s, %s); %s' % (
1020 self.result_code,
1021 namespace,
1022 self.interned_cname,
1023 code.error_goto_if_null(self.result_code, self.pos)))
1024 elif entry.is_local and False:
1025 # control flow not good enough yet
1026 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1027 if assigned is False:
1028 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1029 elif not Options.init_local_none and assigned is None:
1030 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
1031 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1033 def generate_assignment_code(self, rhs, code):
1034 #print "NameNode.generate_assignment_code:", self.name ###
1035 entry = self.entry
1036 if entry is None:
1037 return # There was an error earlier
1039 # is_pyglobal seems to be True for module level-globals only.
1040 # We use this to access class->tp_dict if necessary.
1041 if entry.is_pyglobal:
1042 namespace = self.entry.scope.namespace_cname
1043 if entry.is_member:
1044 # if the entry is a member we have to cheat: SetAttr does not work
1045 # on types, so we create a descriptor which is then added to tp_dict
1046 code.put_error_if_neg(self.pos,
1047 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1048 namespace,
1049 self.interned_cname,
1050 rhs.py_result()))
1051 # in Py2.6+, we need to invalidate the method cache
1052 code.putln("PyType_Modified(%s);" %
1053 entry.scope.parent_type.typeptr_cname)
1054 else:
1055 code.put_error_if_neg(self.pos,
1056 'PyObject_SetAttr(%s, %s, %s)' % (
1057 namespace,
1058 self.interned_cname,
1059 rhs.py_result()))
1060 if debug_disposal_code:
1061 print("NameNode.generate_assignment_code:")
1062 print("...generating disposal code for %s" % rhs)
1063 rhs.generate_disposal_code(code)
1065 else:
1066 if self.type.is_buffer:
1067 # Generate code for doing the buffer release/acquisition.
1068 # This might raise an exception in which case the assignment (done
1069 # below) will not happen.
1070 #
1071 # The reason this is not in a typetest-like node is because the
1072 # variables that the acquired buffer info is stored to is allocated
1073 # per entry and coupled with it.
1074 self.generate_acquire_buffer(rhs, code)
1076 if self.type.is_pyobject:
1077 rhs.make_owned_reference(code)
1078 #print "NameNode.generate_assignment_code: to", self.name ###
1079 #print "...from", rhs ###
1080 #print "...LHS type", self.type, "ctype", self.ctype() ###
1081 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1082 if not self.skip_assignment_decref:
1083 if entry.is_local and not Options.init_local_none:
1084 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1085 if initalized is True:
1086 code.put_decref(self.result_code, self.ctype())
1087 elif initalized is None:
1088 code.put_xdecref(self.result_code, self.ctype())
1089 else:
1090 code.put_decref(self.result_code, self.ctype())
1091 code.putln('%s = %s;' % (self.result_code, rhs.result_as(self.ctype())))
1092 if debug_disposal_code:
1093 print("NameNode.generate_assignment_code:")
1094 print("...generating post-assignment code for %s" % rhs)
1095 rhs.generate_post_assignment_code(code)
1097 def generate_acquire_buffer(self, rhs, code):
1098 rhstmp = code.funcstate.allocate_temp(self.entry.type)
1099 buffer_aux = self.entry.buffer_aux
1100 bufstruct = buffer_aux.buffer_info_var.cname
1101 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1103 import Buffer
1104 Buffer.put_assign_to_buffer(self.result_code, rhstmp, buffer_aux, self.entry.type,
1105 is_initialized=not self.skip_assignment_decref,
1106 pos=self.pos, code=code)
1107 code.putln("%s = 0;" % rhstmp)
1108 code.funcstate.release_temp(rhstmp)
1110 def generate_deletion_code(self, code):
1111 if self.entry is None:
1112 return # There was an error earlier
1113 if not self.entry.is_pyglobal:
1114 error(self.pos, "Deletion of local or C global name not supported")
1115 return
1116 code.put_error_if_neg(self.pos,
1117 'PyObject_DelAttrString(%s, "%s")' % (
1118 Naming.module_cname,
1119 self.entry.name))
1121 def annotate(self, code):
1122 if hasattr(self, 'is_called') and self.is_called:
1123 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1124 if self.type.is_pyobject:
1125 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1126 else:
1127 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1129 class BackquoteNode(ExprNode):
1130 # `expr`
1131 #
1132 # arg ExprNode
1134 subexprs = ['arg']
1136 def analyse_types(self, env):
1137 self.arg.analyse_types(env)
1138 self.arg = self.arg.coerce_to_pyobject(env)
1139 self.type = py_object_type
1140 self.gil_check(env)
1141 self.is_temp = 1
1143 gil_message = "Backquote expression"
1145 def generate_result_code(self, code):
1146 code.putln(
1147 "%s = PyObject_Repr(%s); %s" % (
1148 self.result_code,
1149 self.arg.py_result(),
1150 code.error_goto_if_null(self.result_code, self.pos)))
1153 class ImportNode(ExprNode):
1154 # Used as part of import statement implementation.
1155 # Implements result =
1156 # __import__(module_name, globals(), None, name_list)
1157 #
1158 # module_name IdentifierStringNode dotted name of module
1159 # name_list ListNode or None list of names to be imported
1161 subexprs = ['module_name', 'name_list']
1163 def analyse_types(self, env):
1164 self.module_name.analyse_types(env)
1165 self.module_name = self.module_name.coerce_to_pyobject(env)
1166 if self.name_list:
1167 self.name_list.analyse_types(env)
1168 self.type = py_object_type
1169 self.gil_check(env)
1170 self.is_temp = 1
1171 env.use_utility_code(import_utility_code)
1173 gil_message = "Python import"
1175 def generate_result_code(self, code):
1176 if self.name_list:
1177 name_list_code = self.name_list.py_result()
1178 else:
1179 name_list_code = "0"
1180 code.putln(
1181 "%s = __Pyx_Import(%s, %s); %s" % (
1182 self.result_code,
1183 self.module_name.py_result(),
1184 name_list_code,
1185 code.error_goto_if_null(self.result_code, self.pos)))
1188 class IteratorNode(ExprNode):
1189 # Used as part of for statement implementation.
1190 # Implements result = iter(sequence)
1191 #
1192 # sequence ExprNode
1194 subexprs = ['sequence']
1196 def analyse_types(self, env):
1197 self.sequence.analyse_types(env)
1198 self.sequence = self.sequence.coerce_to_pyobject(env)
1199 self.type = py_object_type
1200 self.gil_check(env)
1201 self.is_temp = 1
1203 self.counter = TempNode(self.pos, PyrexTypes.c_py_ssize_t_type, env)
1204 self.counter.allocate_temp(env)
1206 gil_message = "Iterating over Python object"
1208 def release_temp(self, env):
1209 env.release_temp(self.result_code)
1210 self.counter.release_temp(env)
1212 def generate_result_code(self, code):
1213 code.putln(
1214 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1215 self.sequence.py_result(),
1216 self.sequence.py_result()))
1217 code.putln(
1218 "%s = 0; %s = %s; Py_INCREF(%s);" % (
1219 self.counter.result_code,
1220 self.result_code,
1221 self.sequence.py_result(),
1222 self.result_code))
1223 code.putln("} else {")
1224 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1225 self.counter.result_code,
1226 self.result_code,
1227 self.sequence.py_result(),
1228 code.error_goto_if_null(self.result_code, self.pos)))
1229 code.putln("}")
1232 class NextNode(AtomicExprNode):
1233 # Used as part of for statement implementation.
1234 # Implements result = iterator.next()
1235 # Created during analyse_types phase.
1236 # The iterator is not owned by this node.
1237 #
1238 # iterator ExprNode
1240 def __init__(self, iterator, env):
1241 self.pos = iterator.pos
1242 self.iterator = iterator
1243 self.type = py_object_type
1244 self.is_temp = 1
1246 def generate_result_code(self, code):
1247 for py_type in ["List", "Tuple"]:
1248 code.putln(
1249 "if (likely(Py%s_CheckExact(%s))) {" % (py_type, self.iterator.py_result()))
1250 code.putln(
1251 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1252 self.iterator.counter.result_code,
1253 py_type,
1254 self.iterator.py_result()))
1255 code.putln(
1256 "%s = Py%s_GET_ITEM(%s, %s); Py_INCREF(%s); %s++;" % (
1257 self.result_code,
1258 py_type,
1259 self.iterator.py_result(),
1260 self.iterator.counter.result_code,
1261 self.result_code,
1262 self.iterator.counter.result_code))
1263 code.put("} else ")
1264 code.putln("{")
1265 code.putln(
1266 "%s = PyIter_Next(%s);" % (
1267 self.result_code,
1268 self.iterator.py_result()))
1269 code.putln(
1270 "if (!%s) {" %
1271 self.result_code)
1272 code.putln(code.error_goto_if_PyErr(self.pos))
1273 code.putln("break;")
1274 code.putln("}")
1275 code.putln("}")
1278 class ExcValueNode(AtomicExprNode):
1279 # Node created during analyse_types phase
1280 # of an ExceptClauseNode to fetch the current
1281 # exception value.
1283 def __init__(self, pos, env, var):
1284 ExprNode.__init__(self, pos)
1285 self.type = py_object_type
1286 self.var = var
1288 def calculate_result_code(self):
1289 return self.var
1291 def generate_result_code(self, code):
1292 pass
1294 def analyse_types(self, env):
1295 pass
1298 class TempNode(AtomicExprNode):
1299 # Node created during analyse_types phase
1300 # of some nodes to hold a temporary value.
1302 def __init__(self, pos, type, env):
1303 ExprNode.__init__(self, pos)
1304 self.type = type
1305 if type.is_pyobject:
1306 self.result_ctype = py_object_type
1307 self.is_temp = 1
1309 def analyse_types(self, env):
1310 return self.type
1312 def generate_result_code(self, code):
1313 pass
1316 class PyTempNode(TempNode):
1317 # TempNode holding a Python value.
1319 def __init__(self, pos, env):
1320 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1323 #-------------------------------------------------------------------
1324 #
1325 # Trailer nodes
1326 #
1327 #-------------------------------------------------------------------
1329 class IndexNode(ExprNode):
1330 # Sequence indexing.
1331 #
1332 # base ExprNode
1333 # index ExprNode
1334 # indices [ExprNode]
1335 # is_buffer_access boolean Whether this is a buffer access.
1336 #
1337 # indices is used on buffer access, index on non-buffer access.
1338 # The former contains a clean list of index parameters, the
1339 # latter whatever Python object is needed for index access.
1341 subexprs = ['base', 'index', 'indices']
1342 indices = None
1344 def __init__(self, pos, index, *args, **kw):
1345 ExprNode.__init__(self, pos, index=index, *args, **kw)
1346 self._index = index
1348 def compile_time_value(self, denv):
1349 base = self.base.compile_time_value(denv)
1350 index = self.index.compile_time_value(denv)
1351 try:
1352 return base[index]
1353 except Exception, e:
1354 self.compile_time_value_error(e)
1356 def is_ephemeral(self):
1357 return self.base.is_ephemeral()
1359 def analyse_target_declaration(self, env):
1360 pass
1362 def analyse_types(self, env):
1363 self.analyse_base_and_index_types(env, getting = 1)
1365 def analyse_target_types(self, env):
1366 self.analyse_base_and_index_types(env, setting = 1)
1368 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1369 # Note: This might be cleaned up by having IndexNode
1370 # parsed in a saner way and only construct the tuple if
1371 # needed.
1373 # Note that this function must leave IndexNode in a cloneable state.
1374 # For buffers, self.index is packed out on the initial analysis, and
1375 # when cloning self.indices is copied.
1376 self.is_buffer_access = False
1378 self.base.analyse_types(env)
1379 # Handle the case where base is a literal char* (and we expect a string, not an int)
1380 if isinstance(self.base, StringNode):
1381 self.base = self.base.coerce_to_pyobject(env)
1383 skip_child_analysis = False
1384 buffer_access = False
1385 if self.base.type.is_buffer:
1386 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1387 if self.indices:
1388 indices = self.indices
1389 else:
1390 # On cloning, indices is cloned. Otherwise, unpack index into indices
1391 assert not isinstance(self.index, CloneNode)
1392 if isinstance(self.index, TupleNode):
1393 indices = self.index.args
1394 else:
1395 indices = [self.index]
1396 if len(indices) == self.base.type.ndim:
1397 buffer_access = True
1398 skip_child_analysis = True
1399 for x in indices:
1400 x.analyse_types(env)
1401 if not x.type.is_int:
1402 buffer_access = False
1404 if buffer_access:
1405 self.indices = indices
1406 self.index = None
1407 self.type = self.base.type.dtype
1408 self.is_buffer_access = True
1409 self.buffer_type = self.base.entry.type
1411 if getting:
1412 # we only need a temp because result_code isn't refactored to
1413 # generation time, but this seems an ok shortcut to take
1414 self.is_temp = True
1415 if setting:
1416 if not self.base.entry.type.writable:
1417 error(self.pos, "Writing to readonly buffer")
1418 else:
1419 self.base.entry.buffer_aux.writable_needed = True
1420 else:
1421 if isinstance(self.index, TupleNode):
1422 self.index.analyse_types(env, skip_children=skip_child_analysis)
1423 elif not skip_child_analysis:
1424 self.index.analyse_types(env)
1425 if self.base.type.is_pyobject:
1426 if self.index.type.is_int:
1427 self.original_index_type = self.index.type
1428 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1429 if getting:
1430 env.use_utility_code(getitem_int_utility_code)
1431 if setting:
1432 env.use_utility_code(setitem_int_utility_code)
1433 else:
1434 self.index = self.index.coerce_to_pyobject(env)
1435 self.type = py_object_type
1436 self.gil_check(env)
1437 self.is_temp = 1
1438 else:
1439 if self.base.type.is_ptr or self.base.type.is_array:
1440 self.type = self.base.type.base_type
1441 else:
1442 error(self.pos,
1443 "Attempting to index non-array type '%s'" %
1444 self.base.type)
1445 self.type = PyrexTypes.error_type
1446 if self.index.type.is_pyobject:
1447 self.index = self.index.coerce_to(
1448 PyrexTypes.c_py_ssize_t_type, env)
1449 if not self.index.type.is_int:
1450 error(self.pos,
1451 "Invalid index type '%s'" %
1452 self.index.type)
1454 gil_message = "Indexing Python object"
1456 def check_const_addr(self):
1457 self.base.check_const_addr()
1458 self.index.check_const()
1460 def is_lvalue(self):
1461 return 1
1463 def calculate_result_code(self):
1464 if self.is_buffer_access:
1465 return "<not used>"
1466 else:
1467 return "(%s[%s])" % (
1468 self.base.result_code, self.index.result_code)
1470 def index_unsigned_parameter(self):
1471 if self.index.type.is_int:
1472 if self.original_index_type.signed:
1473 return ", 0"
1474 else:
1475 return ", sizeof(Py_ssize_t) <= sizeof(%s)" % self.original_index_type.declaration_code("")
1476 else:
1477 return ""
1479 def generate_subexpr_evaluation_code(self, code):
1480 self.base.generate_evaluation_code(code)
1481 if not self.indices:
1482 self.index.generate_evaluation_code(code)
1483 else:
1484 for i in self.indices:
1485 i.generate_evaluation_code(code)
1487 def generate_subexpr_disposal_code(self, code):
1488 self.base.generate_disposal_code(code)
1489 if not self.indices:
1490 self.index.generate_disposal_code(code)
1491 else:
1492 for i in self.indices:
1493 i.generate_disposal_code(code)
1495 def generate_result_code(self, code):
1496 if self.is_buffer_access:
1497 ptrcode = self.buffer_lookup_code(code)
1498 code.putln("%s = *%s;" % (
1499 self.result_code,
1500 self.buffer_type.buffer_ptr_type.cast_code(ptrcode)))
1501 # Must incref the value we pulled out.
1502 if self.buffer_type.dtype.is_pyobject:
1503 code.putln("Py_INCREF((PyObject*)%s);" % self.result_code)
1504 elif self.type.is_pyobject:
1505 if self.index.type.is_int:
1506 function = "__Pyx_GetItemInt"
1507 index_code = self.index.result_code
1508 else:
1509 function = "PyObject_GetItem"
1510 index_code = self.index.py_result()
1511 sign_code = ""
1512 code.putln(
1513 "%s = %s(%s, %s%s); if (!%s) %s" % (
1514 self.result_code,
1515 function,
1516 self.base.py_result(),
1517 index_code,
1518 self.index_unsigned_parameter(),
1519 self.result_code,
1520 code.error_goto(self.pos)))
1522 def generate_setitem_code(self, value_code, code):
1523 if self.index.type.is_int:
1524 function = "__Pyx_SetItemInt"
1525 index_code = self.index.result_code
1526 else:
1527 function = "PyObject_SetItem"
1528 index_code = self.index.py_result()
1529 code.putln(
1530 "if (%s(%s, %s, %s%s) < 0) %s" % (
1531 function,
1532 self.base.py_result(),
1533 index_code,
1534 value_code,
1535 self.index_unsigned_parameter(),
1536 code.error_goto(self.pos)))
1538 def generate_buffer_setitem_code(self, rhs, code, op=""):
1539 # Used from generate_assignment_code and InPlaceAssignmentNode
1540 ptrexpr = self.buffer_lookup_code(code)
1541 if self.buffer_type.dtype.is_pyobject:
1542 # Must manage refcounts. Decref what is already there
1543 # and incref what we put in.
1544 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type)
1545 if rhs.is_temp:
1546 rhs_code = code.funcstate.allocate_temp(rhs.type)
1547 else:
1548 rhs_code = rhs.result_code
1549 code.putln("%s = %s;" % (ptr, ptrexpr))
1550 code.putln("Py_DECREF(*%s); Py_INCREF(%s);" % (
1551 ptr, rhs_code
1552 ))
1553 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1554 if rhs.is_temp:
1555 code.funcstate.release_temp(rhs_code)
1556 code.funcstate.release_temp(ptr)
1557 else:
1558 # Simple case
1559 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result_code))
1561 def generate_assignment_code(self, rhs, code):
1562 self.generate_subexpr_evaluation_code(code)
1563 if self.is_buffer_access:
1564 self.generate_buffer_setitem_code(rhs, code)
1565 elif self.type.is_pyobject:
1566 self.generate_setitem_code(rhs.py_result(), code)
1567 else:
1568 code.putln(
1569 "%s = %s;" % (
1570 self.result_code, rhs.result_code))
1571 self.generate_subexpr_disposal_code(code)
1572 rhs.generate_disposal_code(code)
1574 def generate_deletion_code(self, code):
1575 self.generate_subexpr_evaluation_code(code)
1576 #if self.type.is_pyobject:
1577 if self.index.type.is_int:
1578 function = "PySequence_DelItem"
1579 index_code = self.index.result_code
1580 else:
1581 function = "PyObject_DelItem"
1582 index_code = self.index.py_result()
1583 code.putln(
1584 "if (%s(%s, %s) < 0) %s" % (
1585 function,
1586 self.base.py_result(),
1587 index_code,
1588 code.error_goto(self.pos)))
1589 self.generate_subexpr_disposal_code(code)
1591 def buffer_lookup_code(self, code):
1592 # Assign indices to temps
1593 index_temps = [code.funcstate.allocate_temp(i.type) for i in self.indices]
1594 for temp, index in zip(index_temps, self.indices):
1595 code.putln("%s = %s;" % (temp, index.result_code))
1596 # Generate buffer access code using these temps
1597 import Buffer
1598 assert self.options is not None
1599 # The above could happen because child_attrs is wrong somewhere so that
1600 # options are not propagated.
1601 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1602 index_signeds=[i.type.signed for i in self.indices],
1603 index_cnames=index_temps,
1604 options=self.options,
1605 pos=self.pos, code=code)
1607 class SliceIndexNode(ExprNode):
1608 # 2-element slice indexing
1609 #
1610 # base ExprNode
1611 # start ExprNode or None
1612 # stop ExprNode or None
1614 subexprs = ['base', 'start', 'stop']
1616 def compile_time_value(self, denv):
1617 base = self.base.compile_time_value(denv)
1618 start = self.start.compile_time_value(denv)
1619 stop = self.stop.compile_time_value(denv)
1620 try:
1621 return base[start:stop]
1622 except Exception, e:
1623 self.compile_time_value_error(e)
1625 def analyse_target_declaration(self, env):
1626 pass
1628 def analyse_types(self, env):
1629 self.base.analyse_types(env)
1630 if self.start:
1631 self.start.analyse_types(env)
1632 if self.stop:
1633 self.stop.analyse_types(env)
1634 self.base = self.base.coerce_to_pyobject(env)
1635 c_int = PyrexTypes.c_py_ssize_t_type
1636 if self.start:
1637 self.start = self.start.coerce_to(c_int, env)
1638 if self.stop:
1639 self.stop = self.stop.coerce_to(c_int, env)
1640 self.type = py_object_type
1641 self.gil_check(env)
1642 self.is_temp = 1
1644 gil_message = "Slicing Python object"
1646 def generate_result_code(self, code):
1647 code.putln(
1648 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1649 self.result_code,
1650 self.base.py_result(),
1651 self.start_code(),
1652 self.stop_code(),
1653 code.error_goto_if_null(self.result_code, self.pos)))
1655 def generate_assignment_code(self, rhs, code):
1656 self.generate_subexpr_evaluation_code(code)
1657 code.put_error_if_neg(self.pos,
1658 "PySequence_SetSlice(%s, %s, %s, %s)" % (
1659 self.base.py_result(),
1660 self.start_code(),
1661 self.stop_code(),
1662 rhs.result_code))
1663 self.generate_subexpr_disposal_code(code)
1664 rhs.generate_disposal_code(code)
1666 def generate_deletion_code(self, code):
1667 self.generate_subexpr_evaluation_code(code)
1668 code.put_error_if_neg(self.pos,
1669 "PySequence_DelSlice(%s, %s, %s)" % (
1670 self.base.py_result(),
1671 self.start_code(),
1672 self.stop_code()))
1673 self.generate_subexpr_disposal_code(code)
1675 def start_code(self):
1676 if self.start:
1677 return self.start.result_code
1678 else:
1679 return "0"
1681 def stop_code(self):
1682 if self.stop:
1683 return self.stop.result_code
1684 else:
1685 return "PY_SSIZE_T_MAX"
1687 def calculate_result_code(self):
1688 # self.result_code is not used, but this method must exist
1689 return "<unused>"
1692 class SliceNode(ExprNode):
1693 # start:stop:step in subscript list
1694 #
1695 # start ExprNode
1696 # stop ExprNode
1697 # step ExprNode
1699 def compile_time_value(self, denv):
1700 start = self.start.compile_time_value(denv)
1701 stop = self.stop.compile_time_value(denv)
1702 step = step.step.compile_time_value(denv)
1703 try:
1704 return slice(start, stop, step)
1705 except Exception, e:
1706 self.compile_time_value_error(e)
1708 subexprs = ['start', 'stop', 'step']
1710 def analyse_types(self, env):
1711 self.start.analyse_types(env)
1712 self.stop.analyse_types(env)
1713 self.step.analyse_types(env)
1714 self.start = self.start.coerce_to_pyobject(env)
1715 self.stop = self.stop.coerce_to_pyobject(env)
1716 self.step = self.step.coerce_to_pyobject(env)
1717 self.type = py_object_type
1718 self.gil_check(env)
1719 self.is_temp = 1
1721 gil_message = "Constructing Python slice object"
1723 def generate_result_code(self, code):
1724 code.putln(
1725 "%s = PySlice_New(%s, %s, %s); %s" % (
1726 self.result_code,
1727 self.start.py_result(),
1728 self.stop.py_result(),
1729 self.step.py_result(),
1730 code.error_goto_if_null(self.result_code, self.pos)))
1733 class CallNode(ExprNode):
1734 def gil_check(self, env):
1735 # Make sure we're not in a nogil environment
1736 if env.nogil:
1737 error(self.pos, "Calling gil-requiring function without gil")
1740 class SimpleCallNode(CallNode):
1741 # Function call without keyword, * or ** args.
1742 #
1743 # function ExprNode
1744 # args [ExprNode]
1745 # arg_tuple ExprNode or None used internally
1746 # self ExprNode or None used internally
1747 # coerced_self ExprNode or None used internally
1748 # wrapper_call bool used internally
1749 # has_optional_args bool used internally
1751 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
1753 self = None
1754 coerced_self = None
1755 arg_tuple = None
1756 wrapper_call = False
1757 has_optional_args = False
1759 def compile_time_value(self, denv):
1760 function = self.function.compile_time_value(denv)
1761 args = [arg.compile_time_value(denv) for arg in self.args]
1762 try:
1763 return function(*args)
1764 except Exception, e:
1765 self.compile_time_value_error(e)
1767 def analyse_types(self, env):
1768 function = self.function
1769 function.is_called = 1
1770 self.function.analyse_types(env)
1771 if function.is_attribute and function.is_py_attr and \
1772 function.attribute == "append" and len(self.args) == 1:
1773 # L.append(x) is almost always applied to a list
1774 self.py_func = self.function
1775 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
1776 self.function.analyse_types(env)
1777 self.self = self.py_func.obj
1778 function.obj = CloneNode(self.self)
1779 env.use_utility_code(append_utility_code)
1780 if function.is_attribute and function.entry and function.entry.is_cmethod:
1781 # Take ownership of the object from which the attribute
1782 # was obtained, because we need to pass it as 'self'.
1783 self.self = function.obj
1784 function.obj = CloneNode(self.self)
1785 func_type = self.function_type()
1786 if func_type.is_pyobject:
1787 self.arg_tuple = TupleNode(self.pos, args = self.args)
1788 self.arg_tuple.analyse_types(env)
1789 self.args = None
1790 self.type = py_object_type
1791 self.gil_check(env)
1792 self.is_temp = 1
1793 else:
1794 for arg in self.args:
1795 arg.analyse_types(env)
1796 if self.self and func_type.args:
1797 # Coerce 'self' to the type expected by the method.
1798 expected_type = func_type.args[0].type
1799 self.coerced_self = CloneNode(self.self).coerce_to(
1800 expected_type, env)
1801 # Insert coerced 'self' argument into argument list.
1802 self.args.insert(0, self.coerced_self)
1803 self.analyse_c_function_call(env)
1805 def function_type(self):
1806 # Return the type of the function being called, coercing a function
1807 # pointer to a function if necessary.
1808 func_type = self.function.type
1809 if func_type.is_ptr:
1810 func_type = func_type.base_type
1811 return func_type
1813 def analyse_c_function_call(self, env):
1814 func_type = self.function_type()
1815 # Check function type
1816 if not func_type.is_cfunction:
1817 if not func_type.is_error:
1818 error(self.pos, "Calling non-function type '%s'" %
1819 func_type)
1820 self.type = PyrexTypes.error_type
1821 self.result_code = "<error>"
1822 return
1823 # Check no. of args
1824 max_nargs = len(func_type.args)
1825 expected_nargs = max_nargs - func_type.optional_arg_count
1826 actual_nargs = len(self.args)
1827 if actual_nargs < expected_nargs \
1828 or (not func_type.has_varargs and actual_nargs > max_nargs):
1829 expected_str = str(expected_nargs)
1830 if func_type.has_varargs:
1831 expected_str = "at least " + expected_str
1832 elif func_type.optional_arg_count:
1833 if actual_nargs < max_nargs:
1834 expected_str = "at least " + expected_str
1835 else:
1836 expected_str = "at most " + str(max_nargs)
1837 error(self.pos,
1838 "Call with wrong number of arguments (expected %s, got %s)"
1839 % (expected_str, actual_nargs))
1840 self.args = None
1841 self.type = PyrexTypes.error_type
1842 self.result_code = "<error>"
1843 return
1844 if func_type.optional_arg_count and expected_nargs != actual_nargs:
1845 self.has_optional_args = 1
1846 self.is_temp = 1
1847 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
1848 env.release_temp(self.opt_arg_struct)
1849 # Coerce arguments
1850 for i in range(min(max_nargs, actual_nargs)):
1851 formal_type = func_type.args[i].type
1852 self.args[i] = self.args[i].coerce_to(formal_type, env)
1853 for i in range(max_nargs, actual_nargs):
1854 if self.args[i].type.is_pyobject:
1855 error(self.args[i].pos,
1856 "Python object cannot be passed as a varargs parameter")
1857 # Calc result type and code fragment
1858 self.type = func_type.return_type
1859 if self.type.is_pyobject \
1860 or func_type.exception_value is not None \
1861 or func_type.exception_check:
1862 self.is_temp = 1
1863 if self.type.is_pyobject:
1864 self.result_ctype = py_object_type
1865 # C++ exception handler
1866 if func_type.exception_check == '+':
1867 if func_type.exception_value is None:
1868 env.use_utility_code(cpp_exception_utility_code)
1869 # Check gil
1870 if not func_type.nogil:
1871 self.gil_check(env)
1873 def calculate_result_code(self):
1874 return self.c_call_code()
1876 def c_call_code(self):
1877 func_type = self.function_type()
1878 if self.args is None or not func_type.is_cfunction:
1879 return "<error>"
1880 formal_args = func_type.args
1881 arg_list_code = []
1882 args = zip(formal_args, self.args)
1883 max_nargs = len(func_type.args)
1884 expected_nargs = max_nargs - func_type.optional_arg_count
1885 actual_nargs = len(self.args)
1886 for formal_arg, actual_arg in args[:expected_nargs]:
1887 arg_code = actual_arg.result_as(formal_arg.type)
1888 arg_list_code.append(arg_code)
1890 if func_type.optional_arg_count:
1891 if expected_nargs == actual_nargs:
1892 optional_args = 'NULL'
1893 else:
1894 optional_args = "&%s" % self.opt_arg_struct
1895 arg_list_code.append(optional_args)
1897 for actual_arg in self.args[len(formal_args):]:
1898 arg_list_code.append(actual_arg.result_code)
1899 result = "%s(%s)" % (self.function.result_code,
1900 join(arg_list_code, ", "))
1901 if self.wrapper_call or \
1902 self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
1903 result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
1904 return result
1906 def generate_result_code(self, code):
1907 func_type = self.function_type()
1908 if func_type.is_pyobject:
1909 arg_code = self.arg_tuple.py_result()
1910 code.putln(
1911 "%s = PyObject_Call(%s, %s, NULL); %s" % (
1912 self.result_code,
1913 self.function.py_result(),
1914 arg_code,
1915 code.error_goto_if_null(self.result_code, self.pos)))
1916 elif func_type.is_cfunction:
1917 if self.has_optional_args:
1918 actual_nargs = len(self.args)
1919 expected_nargs = len(func_type.args) - func_type.optional_arg_count
1920 code.putln("%s.%s = %s;" % (
1921 self.opt_arg_struct,
1922 Naming.pyrex_prefix + "n",
1923 len(self.args) - expected_nargs))
1924 args = zip(func_type.args, self.args)
1925 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
1926 code.putln("%s.%s = %s;" % (
1927 self.opt_arg_struct,
1928 formal_arg.name,
1929 actual_arg.result_as(formal_arg.type)))
1930 exc_checks = []
1931 if self.type.is_pyobject:
1932 exc_checks.append("!%s" % self.result_code)
1933 else:
1934 exc_val = func_type.exception_value
1935 exc_check = func_type.exception_check
1936 if exc_val is not None:
1937 exc_checks.append("%s == %s" % (self.result_code, exc_val))
1938 if exc_check:
1939 exc_checks.append("PyErr_Occurred()")
1940 if self.is_temp or exc_checks:
1941 rhs = self.c_call_code()
1942 if self.result_code:
1943 lhs = "%s = " % self.result_code
1944 if self.is_temp and self.type.is_pyobject:
1945 #return_type = self.type # func_type.return_type
1946 #print "SimpleCallNode.generate_result_code: casting", rhs, \
1947 # "from", return_type, "to pyobject" ###
1948 rhs = typecast(py_object_type, self.type, rhs)
1949 else:
1950 lhs = ""
1951 if func_type.exception_check == '+':
1952 if func_type.exception_value is None:
1953 raise_py_exception = "__Pyx_CppExn2PyErr()"
1954 elif func_type.exception_value.type.is_pyobject:
1955 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
1956 else:
1957 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
1958 code.putln(
1959 "try {%s%s;} catch(...) {%s; %s}" % (
1960 lhs,
1961 rhs,
1962 raise_py_exception,
1963 code.error_goto(self.pos)))
1964 else:
1965 if exc_checks:
1966 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
1967 else:
1968 goto_error = ""
1969 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
1971 class GeneralCallNode(CallNode):
1972 # General Python function call, including keyword,
1973 # * and ** arguments.
1974 #
1975 # function ExprNode
1976 # positional_args ExprNode Tuple of positional arguments
1977 # keyword_args ExprNode or None Dict of keyword arguments
1978 # starstar_arg ExprNode or None Dict of extra keyword args
1980 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
1982 def compile_time_value(self, denv):
1983 function = self.function.compile_time_value(denv)
1984 positional_args = self.positional_args.compile_time_value(denv)
1985 keyword_args = self.keyword_args.compile_time_value(denv)
1986 starstar_arg = self.starstar_arg.compile_time_value(denv)
1987 try:
1988 keyword_args.update(starstar_arg)
1989 return function(*positional_args, **keyword_args)
1990 except Exception, e:
1991 self.compile_time_value_error(e)
1993 def analyse_types(self, env):
1994 self.function.analyse_types(env)
1995 self.positional_args.analyse_types(env)
1996 if self.keyword_args:
1997 self.keyword_args.analyse_types(env)
1998 if self.starstar_arg:
1999 self.starstar_arg.analyse_types(env)
2000 self.function = self.function.coerce_to_pyobject(env)
2001 self.positional_args = \
2002 self.positional_args.coerce_to_pyobject(env)
2003 if self.starstar_arg:
2004 self.starstar_arg = \
2005 self.starstar_arg.coerce_to_pyobject(env)
2006 self.type = py_object_type
2007 self.gil_check(env)
2008 self.is_temp = 1
2010 def generate_result_code(self, code):
2011 if self.keyword_args and self.starstar_arg:
2012 code.put_error_if_neg(self.pos,
2013 "PyDict_Update(%s, %s)" % (
2014 self.keyword_args.py_result(),
2015 self.starstar_arg.py_result()))
2016 keyword_code = self.keyword_args.py_result()
2017 elif self.keyword_args:
2018 keyword_code = self.keyword_args.py_result()
2019 elif self.starstar_arg:
2020 keyword_code = self.starstar_arg.py_result()
2021 else:
2022 keyword_code = None
2023 if not keyword_code:
2024 call_code = "PyObject_Call(%s, %s, NULL)" % (
2025 self.function.py_result(),
2026 self.positional_args.py_result())
2027 else:
2028 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2029 self.function.py_result(),
2030 self.positional_args.py_result(),
2031 keyword_code)
2032 code.putln(
2033 "%s = %s; %s" % (
2034 self.result_code,
2035 call_code,
2036 code.error_goto_if_null(self.result_code, self.pos)))
2039 class AsTupleNode(ExprNode):
2040 # Convert argument to tuple. Used for normalising
2041 # the * argument of a function call.
2042 #
2043 # arg ExprNode
2045 subexprs = ['arg']
2047 def compile_time_value(self, denv):
2048 arg = self.arg.compile_time_value(denv)
2049 try:
2050 return tuple(arg)
2051 except Exception, e:
2052 self.compile_time_value_error(e)
2054 def analyse_types(self, env):
2055 self.arg.analyse_types(env)
2056 self.arg = self.arg.coerce_to_pyobject(env)
2057 self.type = py_object_type
2058 self.gil_check(env)
2059 self.is_temp = 1
2061 gil_message = "Constructing Python tuple"
2063 def generate_result_code(self, code):
2064 code.putln(
2065 "%s = PySequence_Tuple(%s); %s" % (
2066 self.result_code,
2067 self.arg.py_result(),
2068 code.error_goto_if_null(self.result_code, self.pos)))
2071 class AttributeNode(ExprNode):
2072 # obj.attribute
2073 #
2074 # obj ExprNode
2075 # attribute string
2076 #
2077 # Used internally:
2078 #
2079 # is_py_attr boolean Is a Python getattr operation
2080 # member string C name of struct member
2081 # is_called boolean Function call is being done on result
2082 # entry Entry Symbol table entry of attribute
2083 # interned_attr_cname string C name of interned attribute name
2085 is_attribute = 1
2086 subexprs = ['obj']
2088 type = PyrexTypes.error_type
2089 result = "<error>"
2090 entry = None
2091 is_called = 0
2093 def coerce_to(self, dst_type, env):
2094 # If coercing to a generic pyobject and this is a cpdef function
2095 # we can create the corresponding attribute
2096 if dst_type is py_object_type:
2097 entry = self.entry
2098 if entry and entry.is_cfunction and entry.as_variable:
2099 # must be a cpdef function
2100 self.is_temp = 1
2101 self.entry = entry.as_variable
2102 self.analyse_as_python_attribute(env)
2103 return self
2104 return ExprNode.coerce_to(self, dst_type, env)
2106 def compile_time_value(self, denv):
2107 attr = self.attribute
2108 if attr.beginswith("__") and attr.endswith("__"):
2109 self.error("Invalid attribute name '%s' in compile-time expression"
2110 % attr)
2111 return None
2112 obj = self.arg.compile_time_value(denv)
2113 try:
2114 return getattr(obj, attr)
2115 except Exception, e:
2116 self.compile_time_value_error(e)
2118 def analyse_target_declaration(self, env):
2119 pass
2121 def analyse_target_types(self, env):
2122 self.analyse_types(env, target = 1)
2124 def analyse_types(self, env, target = 0):
2125 if self.analyse_as_cimported_attribute(env, target):
2126 return
2127 if not target and self.analyse_as_unbound_cmethod(env):
2128 return
2129 self.analyse_as_ordinary_attribute(env, target)
2131 def analyse_as_cimported_attribute(self, env, target):
2132 # Try to interpret this as a reference to an imported
2133 # C const, type, var or function. If successful, mutates
2134 # this node into a NameNode and returns 1, otherwise
2135 # returns 0.
2136 module_scope = self.obj.analyse_as_module(env)
2137 if module_scope:
2138 entry = module_scope.lookup_here(self.attribute)
2139 if entry and (
2140 entry.is_cglobal or entry.is_cfunction
2141 or entry.is_type or entry.is_const):
2142 self.mutate_into_name_node(env, entry, target)
2143 return 1
2144 return 0
2146 def analyse_as_unbound_cmethod(self, env):
2147 # Try to interpret this as a reference to an unbound
2148 # C method of an extension type. If successful, mutates
2149 # this node into a NameNode and returns 1, otherwise
2150 # returns 0.
2151 type = self.obj.analyse_as_extension_type(env)
2152 if type:
2153 entry = type.scope.lookup_here(self.attribute)
2154 if entry and entry.is_cmethod:
2155 # Create a temporary entry describing the C method
2156 # as an ordinary function.
2157 ubcm_entry = Symtab.Entry(entry.name,
2158 "%s->%s" % (type.vtabptr_cname, entry.cname),
2159 entry.type)
2160 ubcm_entry.is_cfunction = 1
2161 ubcm_entry.func_cname = entry.func_cname
2162 ubcm_entry.is_unbound_cmethod = 1
2163 self.mutate_into_name_node(env, ubcm_entry, None)
2164 return 1
2165 return 0
2167 def analyse_as_extension_type(self, env):
2168 # Try to interpret this as a reference to an extension type
2169 # in a cimported module. Returns the extension type, or None.
2170 module_scope = self.obj.analyse_as_module(env)
2171 if module_scope:
2172 entry = module_scope.lookup_here(self.attribute)
2173 if entry and entry.is_type and entry.type.is_extension_type:
2174 return entry.type
2175 return None
2177 def analyse_as_module(self, env):
2178 # Try to interpret this as a reference to a cimported module
2179 # in another cimported module. Returns the module scope, or None.
2180 module_scope = self.obj.analyse_as_module(env)
2181 if module_scope:
2182 entry = module_scope.lookup_here(self.attribute)
2183 if entry and entry.as_module:
2184 return entry.as_module
2185 return None
2187 def mutate_into_name_node(self, env, entry, target):
2188 # Mutate this node into a NameNode and complete the
2189 # analyse_types phase.
2190 self.__class__ = NameNode
2191 self.name = self.attribute
2192 self.entry = entry
2193 del self.obj
2194 del self.attribute
2195 if target:
2196 NameNode.analyse_target_types(self, env)
2197 else:
2198 NameNode.analyse_rvalue_entry(self, env)
2200 def analyse_as_ordinary_attribute(self, env, target):
2201 self.obj.analyse_types(env)
2202 self.analyse_attribute(env)
2203 if self.entry and self.entry.is_cmethod and not self.is_called:
2204 # error(self.pos, "C method can only be called")
2205 pass
2206 ## Reference to C array turns into pointer to first element.
2207 #while self.type.is_array:
2208 # self.type = self.type.element_ptr_type()
2209 if self.is_py_attr:
2210 if not target:
2211 self.is_temp = 1
2212 self.result_ctype = py_object_type
2214 def analyse_attribute(self, env):
2215 # Look up attribute and set self.type and self.member.
2216 self.is_py_attr = 0
2217 self.member = self.attribute
2218 if self.obj.type.is_string:
2219 self.obj = self.obj.coerce_to_pyobject(env)
2220 obj_type = self.obj.type
2221 if obj_type.is_ptr or obj_type.is_array:
2222 obj_type = obj_type.base_type
2223 self.op = "->"
2224 elif obj_type.is_extension_type:
2225 self.op = "->"
2226 else:
2227 self.op = "."
2228 if obj_type.has_attributes:
2229 entry = None
2230 if obj_type.attributes_known():
2231 entry = obj_type.scope.lookup_here(self.attribute)
2232 if entry and entry.is_member:
2233 entry = None
2234 else:
2235 error(self.pos,
2236 "Cannot select attribute of incomplete type '%s'"
2237 % obj_type)
2238 self.type = PyrexTypes.error_type
2239 return
2240 self.entry = entry
2241 if entry:
2242 if obj_type.is_extension_type and entry.name == "__weakref__":
2243 error(self.pos, "Illegal use of special attribute __weakref__")
2244 # methods need the normal attribute lookup
2245 # because they do not have struct entries
2246 if entry.is_variable or entry.is_cmethod:
2247 self.type = entry.type
2248 self.member = entry.cname
2249 return
2250 else:
2251 # If it's not a variable or C method, it must be a Python
2252 # method of an extension type, so we treat it like a Python
2253 # attribute.
2254 pass
2255 # If we get here, the base object is not a struct/union/extension
2256 # type, or it is an extension type and the attribute is either not
2257 # declared or is declared as a Python method. Treat it as a Python
2258 # attribute reference.
2259 self.analyse_as_python_attribute(env)
2261 def analyse_as_python_attribute(self, env):
2262 obj_type = self.obj.type
2263 self.member = self.attribute
2264 if obj_type.is_pyobject:
2265 self.type = py_object_type
2266 self.is_py_attr = 1
2267 self.interned_attr_cname = env.intern_identifier(self.attribute)
2268 self.gil_check(env)
2269 else:
2270 if not obj_type.is_error:
2271 error(self.pos,
2272 "Object of type '%s' has no attribute '%s'" %
2273 (obj_type, self.attribute))
2275 gil_message = "Accessing Python attribute"
2277 def is_simple(self):
2278 if self.obj:
2279 return self.result_in_temp() or self.obj.is_simple()
2280 else:
2281 return NameNode.is_simple(self)
2283 def is_lvalue(self):
2284 if self.obj:
2285 return 1
2286 else:
2287 return NameNode.is_lvalue(self)
2289 def is_ephemeral(self):
2290 if self.obj:
2291 return self.obj.is_ephemeral()
2292 else:
2293 return NameNode.is_ephemeral(self)
2295 def calculate_result_code(self):
2296 #print "AttributeNode.calculate_result_code:", self.member ###
2297 #print "...obj node =", self.obj, "code", self.obj.result_code ###
2298 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2299 obj = self.obj
2300 obj_code = obj.result_as(obj.type)
2301 #print "...obj_code =", obj_code ###
2302 if self.entry and self.entry.is_cmethod:
2303 if obj.type.is_extension_type:
2304 return "((struct %s *)%s%s%s)->%s" % (
2305 obj.type.vtabstruct_cname, obj_code, self.op,
2306 obj.type.vtabslot_cname, self.member)
2307 else:
2308 return self.member
2309 else:
2310 return "%s%s%s" % (obj_code, self.op, self.member)
2312 def generate_result_code(self, code):
2313 if self.is_py_attr:
2314 code.putln(
2315 '%s = PyObject_GetAttr(%s, %s); %s' % (
2316 self.result_code,
2317 self.obj.py_result(),
2318 self.interned_attr_cname,
2319 code.error_goto_if_null(self.result_code, self.pos)))
2321 def generate_assignment_code(self, rhs, code):
2322 self.obj.generate_evaluation_code(code)
2323 if self.is_py_attr:
2324 code.put_error_if_neg(self.pos,
2325 'PyObject_SetAttr(%s, %s, %s)' % (
2326 self.obj.py_result(),
2327 self.interned_attr_cname,
2328 rhs.py_result()))
2329 rhs.generate_disposal_code(code)
2330 else:
2331 select_code = self.result_code
2332 if self.type.is_pyobject:
2333 rhs.make_owned_reference(code)
2334 code.put_decref(select_code, self.ctype())
2335 code.putln(
2336 "%s = %s;" % (
2337 select_code,
2338 rhs.result_as(self.ctype())))
2339 #rhs.result_code))
2340 rhs.generate_post_assignment_code(code)
2341 self.obj.generate_disposal_code(code)
2343 def generate_deletion_code(self, code):
2344 self.obj.generate_evaluation_code(code)
2345 if self.is_py_attr:
2346 code.put_error_if_neg(self.pos,
2347 'PyObject_DelAttr(%s, %s)' % (
2348 self.obj.py_result(),
2349 self.interned_attr_cname))
2350 else:
2351 error(self.pos, "Cannot delete C attribute of extension type")
2352 self.obj.generate_disposal_code(code)
2354 def annotate(self, code):
2355 if self.is_py_attr:
2356 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2357 else:
2358 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2360 #-------------------------------------------------------------------
2361 #
2362 # Constructor nodes
2363 #
2364 #-------------------------------------------------------------------
2366 class SequenceNode(ExprNode):
2367 # Base class for list and tuple constructor nodes.
2368 # Contains common code for performing sequence unpacking.
2369 #
2370 # args [ExprNode]
2371 # iterator ExprNode
2372 # unpacked_items [ExprNode] or None
2373 # coerced_unpacked_items [ExprNode] or None
2375 subexprs = ['args']
2377 is_sequence_constructor = 1
2378 unpacked_items = None
2380 def compile_time_value_list(self, denv):
2381 return [arg.compile_time_value(denv) for arg in self.args]
2383 def analyse_target_declaration(self, env):
2384 for arg in self.args:
2385 arg.analyse_target_declaration(env)
2387 def analyse_types(self, env, skip_children=False):
2388 for i in range(len(self.args)):
2389 arg = self.args[i]
2390 if not skip_children: arg.analyse_types(env)
2391 self.args[i] = arg.coerce_to_pyobject(env)
2392 self.type = py_object_type
2393 self.gil_check(env)
2394 self.is_temp = 1
2396 def analyse_target_types(self, env):
2397 self.iterator = PyTempNode(self.pos, env)
2398 self.unpacked_items = []
2399 self.coerced_unpacked_items = []
2400 for arg in self.args:
2401 arg.analyse_target_types(env)
2402 unpacked_item = PyTempNode(self.pos, env)
2403 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2404 self.unpacked_items.append(unpacked_item)
2405 self.coerced_unpacked_items.append(coerced_unpacked_item)
2406 self.type = py_object_type
2407 env.use_utility_code(unpacking_utility_code)
2409 def allocate_target_temps(self, env, rhs):
2410 self.iterator.allocate_temps(env)
2411 for arg, node in zip(self.args, self.coerced_unpacked_items):
2412 node.allocate_temps(env)
2413 arg.allocate_target_temps(env, node)
2414 #arg.release_target_temp(env)
2415 #node.release_temp(env)
2416 if rhs:
2417 rhs.release_temp(env)
2418 self.iterator.release_temp(env)
2420 # def release_target_temp(self, env):
2421 # #for arg in self.args:
2422 # # arg.release_target_temp(env)
2423 # #for node in self.coerced_unpacked_items:
2424 # # node.release_temp(env)
2425 # self.iterator.release_temp(env)
2427 def generate_result_code(self, code):
2428 self.generate_operation_code(code)
2430 def generate_assignment_code(self, rhs, code):
2431 code.putln(
2432 "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
2433 rhs.py_result(),
2434 rhs.py_result(),
2435 len(self.args)))
2436 code.putln("PyObject* tuple = %s;" % rhs.py_result())
2437 for i in range(len(self.args)):
2438 item = self.unpacked_items[i]
2439 code.putln(
2440 "%s = PyTuple_GET_ITEM(tuple, %s);" % (
2441 item.result_code,
2442 i))
2443 code.put_incref(item.result_code, item.ctype())
2444 value_node = self.coerced_unpacked_items[i]
2445 value_node.generate_evaluation_code(code)
2446 self.args[i].generate_assignment_code(value_node, code)
2448 rhs.generate_disposal_code(code)
2449 code.putln("}")
2450 code.putln("else {")
2452 code.putln(
2453 "%s = PyObject_GetIter(%s); %s" % (
2454 self.iterator.result_code,
2455 rhs.py_result(),
2456 code.error_goto_if_null(self.iterator.result_code, self.pos)))
2457 rhs.generate_disposal_code(code)
2458 for i in range(len(self.args)):
2459 item = self.unpacked_items[i]
2460 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
2461 self.iterator.py_result(), i)
2462 code.putln(
2463 "%s = %s; %s" % (
2464 item.result_code,
2465 typecast(item.ctype(), py_object_type, unpack_code),
2466 code.error_goto_if_null(item.result_code, self.pos)))
2467 value_node = self.coerced_unpacked_items[i]
2468 value_node.generate_evaluation_code(code)
2469 self.args[i].generate_assignment_code(value_node, code)
2470 code.put_error_if_neg(self.pos,
2471 "__Pyx_EndUnpack(%s)" % (
2472 self.iterator.py_result()))
2473 if debug_disposal_code:
2474 print("UnpackNode.generate_assignment_code:")
2475 print("...generating disposal code for %s" % self.iterator)
2476 self.iterator.generate_disposal_code(code)
2478 code.putln("}")
2480 def annotate(self, code):
2481 for arg in self.args:
2482 arg.annotate(code)
2483 if self.unpacked_items:
2484 for arg in self.unpacked_items:
2485 arg.annotate(code)
2486 for arg in self.coerced_unpacked_items:
2487 arg.annotate(code)
2490 class TupleNode(SequenceNode):
2491 # Tuple constructor.
2493 gil_message = "Constructing Python tuple"
2495 def analyse_types(self, env, skip_children=False):
2496 if len(self.args) == 0:
2497 self.is_temp = 0
2498 self.is_literal = 1
2499 else:
2500 SequenceNode.analyse_types(self, env, skip_children)
2501 self.type = tuple_type
2503 def calculate_result_code(self):
2504 if len(self.args) > 0:
2505 error(self.pos, "Positive length tuples must be constructed.")
2506 else:
2507 return Naming.empty_tuple
2509 def compile_time_value(self, denv):
2510 values = self.compile_time_value_list(denv)
2511 try:
2512 return tuple(values)
2513 except Exception, e:
2514 self.compile_time_value_error(e)
2516 def generate_operation_code(self, code):
2517 if len(self.args) == 0:
2518 # result_code is Naming.empty_tuple
2519 return
2520 code.putln(
2521 "%s = PyTuple_New(%s); %s" % (
2522 self.result_code,
2523 len(self.args),
2524 code.error_goto_if_null(self.result_code, self.pos)))
2525 for i in range(len(self.args)):
2526 arg = self.args[i]
2527 if not arg.result_in_temp():
2528 code.put_incref(arg.result_code, arg.ctype())
2529 code.putln(
2530 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2531 self.result_code,
2532 i,
2533 arg.py_result()))
2535 def generate_subexpr_disposal_code(self, code):
2536 # We call generate_post_assignment_code here instead
2537 # of generate_disposal_code, because values were stored
2538 # in the tuple using a reference-stealing operation.
2539 for arg in self.args:
2540 arg.generate_post_assignment_code(code)
2543 class ListNode(SequenceNode):
2544 # List constructor.
2546 gil_message = "Constructing Python list"
2548 def analyse_types(self, env):
2549 SequenceNode.analyse_types(self, env)
2550 self.type = list_type
2552 def compile_time_value(self, denv):
2553 return self.compile_time_value_list(denv)
2555 def generate_operation_code(self, code):
2556 code.putln("%s = PyList_New(%s); %s" %
2557 (self.result_code,
2558 len(self.args),
2559 code.error_goto_if_null(self.result_code, self.pos)))
2560 for i in range(len(self.args)):
2561 arg = self.args[i]
2562 #if not arg.is_temp:
2563 if not arg.result_in_temp():
2564 code.put_incref(arg.result_code, arg.ctype())
2565 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
2566 (self.result_code,
2567 i,
2568 arg.py_result()))
2570 def generate_subexpr_disposal_code(self, code):
2571 # We call generate_post_assignment_code here instead
2572 # of generate_disposal_code, because values were stored
2573 # in the list using a reference-stealing operation.
2574 for arg in self.args:
2575 arg.generate_post_assignment_code(code)
2578 class ListComprehensionNode(SequenceNode):
2580 subexprs = []
2581 is_sequence_constructor = 0 # not unpackable
2583 child_attrs = ["loop", "append"]
2585 def analyse_types(self, env):
2586 self.type = list_type
2587 self.is_temp = 1
2588 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
2590 def allocate_temps(self, env, result = None):
2591 if debug_temp_alloc:
2592 print("%s Allocating temps" % self)
2593 self.allocate_temp(env, result)
2594 self.loop.analyse_declarations(env)
2595 self.loop.analyse_expressions(env)
2597 def generate_operation_code(self, code):
2598 code.putln("%s = PyList_New(%s); %s" %
2599 (self.result_code,
2600 0,
2601 code.error_goto_if_null(self.result_code, self.pos)))
2602 self.loop.generate_execution_code(code)
2604 def annotate(self, code):
2605 self.loop.annotate(code)
2608 class ListComprehensionAppendNode(ExprNode):
2610 # Need to be careful to avoid infinite recursion:
2611 # target must not be in child_attrs/subexprs
2612 subexprs = ['expr']
2614 def analyse_types(self, env):
2615 self.expr.analyse_types(env)
2616 if self.expr.type != py_object_type:
2617 self.expr = self.expr.coerce_to_pyobject(env)
2618 self.type = PyrexTypes.c_int_type
2619 self.is_temp = 1
2621 def generate_result_code(self, code):
2622 code.putln("%s = PyList_Append(%s, %s); %s" %
2623 (self.result_code,
2624 self.target.result_code,
2625 self.expr.result_code,
2626 code.error_goto_if(self.result_code, self.pos)))
2629 class DictNode(ExprNode):
2630 # Dictionary constructor.
2631 #
2632 # key_value_pairs [DictItemNode]
2634 subexprs = ['key_value_pairs']
2636 def compile_time_value(self, denv):
2637 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
2638 for item in self.key_value_pairs]
2639 try:
2640 return dict(pairs)
2641 except Exception, e:
2642 self.compile_time_value_error(e)
2644 def analyse_types(self, env):
2645 for item in self.key_value_pairs:
2646 item.analyse_types(env)
2647 self.type = dict_type
2648 self.gil_check(env)
2649 self.is_temp = 1
2651 gil_message = "Constructing Python dict"
2653 def allocate_temps(self, env, result = None):
2654 # Custom method used here because key-value
2655 # pairs are evaluated and used one at a time.
2656 self.allocate_temp(env, result)
2657 for item in self.key_value_pairs:
2658 item.key.allocate_temps(env)
2659 item.value.allocate_temps(env)
2660 item.key.release_temp(env)
2661 item.value.release_temp(env)
2663 def generate_evaluation_code(self, code):
2664 # Custom method used here because key-value
2665 # pairs are evaluated and used one at a time.
2666 code.putln(
2667 "%s = PyDict_New(); %s" % (
2668 self.result_code,
2669 code.error_goto_if_null(self.result_code, self.pos)))
2670 for item in self.key_value_pairs:
2671 item.generate_evaluation_code(code)
2672 code.put_error_if_neg(self.pos,
2673 "PyDict_SetItem(%s, %s, %s)" % (
2674 self.result_code,
2675 item.key.py_result(),
2676 item.value.py_result()))
2677 item.generate_disposal_code(code)
2679 def annotate(self, code):
2680 for item in self.key_value_pairs:
2681 item.annotate(code)
2683 class DictItemNode(ExprNode):
2684 # Represents a single item in a DictNode
2685 #
2686 # key ExprNode
2687 # value ExprNode
2688 subexprs = ['key', 'value']
2690 def analyse_types(self, env):
2691 self.key.analyse_types(env)
2692 self.value.analyse_types(env)
2693 self.key = self.key.coerce_to_pyobject(env)
2694 self.value = self.value.coerce_to_pyobject(env)
2696 def generate_evaluation_code(self, code):
2697 self.key.generate_evaluation_code(code)
2698 self.value.generate_evaluation_code(code)
2700 def generate_disposal_code(self, code):
2701 self.key.generate_disposal_code(code)
2702 self.value.generate_disposal_code(code)
2705 class ClassNode(ExprNode):
2706 # Helper class used in the implementation of Python
2707 # class definitions. Constructs a class object given
2708 # a name, tuple of bases and class dictionary.
2709 #
2710 # name EncodedString Name of the class
2711 # cname string Class name as a Python string
2712 # bases ExprNode Base class tuple
2713 # dict ExprNode Class dict (not owned by this node)
2714 # doc ExprNode or None Doc string
2715 # module_name string Name of defining module
2717 subexprs = ['bases', 'doc']
2719 def analyse_types(self, env):
2720 self.cname = env.intern_identifier(self.name)
2721 self.bases.analyse_types(env)
2722 if self.doc:
2723 self.doc.analyse_types(env)
2724 self.doc = self.doc.coerce_to_pyobject(env)
2725 self.module_name = env.global_scope().qualified_name
2726 self.type = py_object_type
2727 self.gil_check(env)
2728 self.is_temp = 1
2729 env.use_utility_code(create_class_utility_code);
2731 gil_message = "Constructing Python class"
2733 def generate_result_code(self, code):
2734 if self.doc:
2735 code.put_error_if_neg(self.pos,
2736 'PyDict_SetItemString(%s, "__doc__", %s)' % (
2737 self.dict.py_result(),
2738 self.doc.py_result()))
2739 code.putln(
2740 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
2741 self.result_code,
2742 self.bases.py_result(),
2743 self.dict.py_result(),
2744 self.cname,
2745 self.module_name,
2746 code.error_goto_if_null(self.result_code, self.pos)))
2749 class UnboundMethodNode(ExprNode):
2750 # Helper class used in the implementation of Python
2751 # class definitions. Constructs an unbound method
2752 # object from a class and a function.
2753 #
2754 # class_cname string C var holding the class object
2755 # function ExprNode Function object
2757 subexprs = ['function']
2759 def analyse_types(self, env):
2760 self.function.analyse_types(env)
2761 self.type = py_object_type
2762 self.gil_check(env)
2763 self.is_temp = 1
2765 gil_message = "Constructing an unbound method"
2767 def generate_result_code(self, code):
2768 code.putln(
2769 "%s = PyMethod_New(%s, 0, %s); %s" % (
2770 self.result_code,
2771 self.function.py_result(),
2772 self.class_cname,
2773 code.error_goto_if_null(self.result_code, self.pos)))
2776 class PyCFunctionNode(AtomicExprNode):
2777 # Helper class used in the implementation of Python
2778 # class definitions. Constructs a PyCFunction object
2779 # from a PyMethodDef struct.
2780 #
2781 # pymethdef_cname string PyMethodDef structure
2783 def analyse_types(self, env):
2784 self.type = py_object_type
2785 self.gil_check(env)
2786 self.is_temp = 1
2788 gil_message = "Constructing Python function"
2790 def generate_result_code(self, code):
2791 code.putln(
2792 "%s = PyCFunction_New(&%s, 0); %s" % (
2793 self.result_code,
2794 self.pymethdef_cname,
2795 code.error_goto_if_null(self.result_code, self.pos)))
2797 #-------------------------------------------------------------------
2798 #
2799 # Unary operator nodes
2800 #
2801 #-------------------------------------------------------------------
2803 compile_time_unary_operators = {
2804 'not': operator.not_,
2805 '~': operator.inv,
2806 '-': operator.neg,
2807 '+': operator.pos,
2808 }
2810 class UnopNode(ExprNode):
2811 # operator string
2812 # operand ExprNode
2813 #
2814 # Processing during analyse_expressions phase:
2815 #
2816 # analyse_c_operation
2817 # Called when the operand is not a pyobject.
2818 # - Check operand type and coerce if needed.
2819 # - Determine result type and result code fragment.
2820 # - Allocate temporary for result if needed.
2822 subexprs = ['operand']
2824 def compile_time_value(self, denv):
2825 func = compile_time_unary_operators.get(self.operator)
2826 if not func:
2827 error(self.pos,
2828 "Unary '%s' not supported in compile-time expression"
2829 % self.operator)
2830 operand = self.operand.compile_time_value(denv)
2831 try:
2832 return func(operand)
2833 except Exception, e:
2834 self.compile_time_value_error(e)
2836 def analyse_types(self, env):
2837 self.operand.analyse_types(env)
2838 if self.is_py_operation():
2839 self.coerce_operand_to_pyobject(env)
2840 self.type = py_object_type
2841 self.gil_check(env)
2842 self.is_temp = 1
2843 else:
2844 self.analyse_c_operation(env)
2846 def check_const(self):
2847 self.operand.check_const()
2849 def is_py_operation(self):
2850 return self.operand.type.is_pyobject
2852 def coerce_operand_to_pyobject(self, env):
2853 self.operand = self.operand.coerce_to_pyobject(env)
2855 def generate_result_code(self, code):
2856 if self.operand.type.is_pyobject:
2857 self.generate_py_operation_code(code)
2858 else:
2859 if self.is_temp:
2860 self.generate_c_operation_code(code)
2862 def generate_py_operation_code(self, code):
2863 function = self.py_operation_function()
2864 code.putln(
2865 "%s = %s(%s); %s" % (
2866 self.result_code,
2867 function,
2868 self.operand.py_result(),
2869 code.error_goto_if_null(self.result_code, self.pos)))
2871 def type_error(self):
2872 if not self.operand.type.is_error:
2873 error(self.pos, "Invalid operand type for '%s' (%s)" %
2874 (self.operator, self.operand.type))
2875 self.type = PyrexTypes.error_type
2878 class NotNode(ExprNode):
2879 # 'not' operator
2880 #
2881 # operand ExprNode
2883 def compile_time_value(self, denv):
2884 operand = self.operand.compile_time_value(denv)
2885 try:
2886 return not operand
2887 except Exception, e:
2888 self.compile_time_value_error(e)
2890 subexprs = ['operand']
2892 def analyse_types(self, env):
2893 self.operand.analyse_types(env)
2894 self.operand = self.operand.coerce_to_boolean(env)
2895 self.type = PyrexTypes.c_bint_type
2897 def calculate_result_code(self):
2898 return "(!%s)" % self.operand.result_code
2900 def generate_result_code(self, code):
2901 pass
2904 class UnaryPlusNode(UnopNode):
2905 # unary '+' operator
2907 operator = '+'
2909 def analyse_c_operation(self, env):
2910 self.type = self.operand.type
2912 def py_operation_function(self):
2913 return "PyNumber_Positive"
2915 def calculate_result_code(self):
2916 return self.operand.result_code
2919 class UnaryMinusNode(UnopNode):
2920 # unary '-' operator
2922 operator = '-'
2924 def analyse_c_operation(self, env):
2925 if self.operand.type.is_numeric:
2926 self.type = self.operand.type
2927 else:
2928 self.type_error()
2930 def py_operation_function(self):
2931 return "PyNumber_Negative"
2933 def calculate_result_code(self):
2934 return "(-%s)" % self.operand.result_code
2937 class TildeNode(UnopNode):
2938 # unary '~' operator
2940 def analyse_c_operation(self, env):
2941 if self.operand.type.is_int:
2942 self.type = self.operand.type
2943 else:
2944 self.type_error()
2946 def py_operation_function(self):
2947 return "PyNumber_Invert"
2949 def calculate_result_code(self):
2950 return "(~%s)" % self.operand.result_code
2953 class AmpersandNode(ExprNode):
2954 # The C address-of operator.
2955 #
2956 # operand ExprNode
2958 subexprs = ['operand']
2960 def analyse_types(self, env):
2961 self.operand.analyse_types(env)
2962 argtype = self.operand.type
2963 if not (argtype.is_cfunction or self.operand.is_lvalue()):
2964 self.error("Taking address of non-lvalue")
2965 return
2966 if argtype.is_pyobject:
2967 self.error("Cannot take address of Python variable")
2968 return
2969 self.type = PyrexTypes.c_ptr_type(argtype)
2971 def check_const(self):
2972 self.operand.check_const_addr()
2974 def error(self, mess):
2975 error(self.pos, mess)
2976 self.type = PyrexTypes.error_type
2977 self.result_code = "<error>"
2979 def calculate_result_code(self):
2980 return "(&%s)" % self.operand.result_code
2982 def generate_result_code(self, code):
2983 pass
2986 unop_node_classes = {
2987 "+": UnaryPlusNode,
2988 "-": UnaryMinusNode,
2989 "~": TildeNode,
2990 }
2992 def unop_node(pos, operator, operand):
2993 # Construct unnop node of appropriate class for
2994 # given operator.
2995 if isinstance(operand, IntNode) and operator == '-':
2996 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
2997 elif isinstance(operand, UnopNode) and operand.operator == operator:
2998 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
2999 return unop_node_classes[operator](pos,
3000 operator = operator,
3001 operand = operand)
3004 class TypecastNode(ExprNode):
3005 # C type cast
3006 #
3007 # operand ExprNode
3008 # base_type CBaseTypeNode
3009 # declarator CDeclaratorNode
3010 #
3011 # If used from a transform, one can if wanted specify the attribute
3012 # "type" directly and leave base_type and declarator to None
3014 subexprs = ['operand']
3015 base_type = declarator = type = None
3017 def analyse_types(self, env):
3018 if self.type is None:
3019 base_type = self.base_type.analyse(env)
3020 _, self.type = self.declarator.analyse(base_type, env)
3021 if self.type.is_cfunction:
3022 error(self.pos,
3023 "Cannot cast to a function type")
3024 self.type = PyrexTypes.error_type
3025 self.operand.analyse_types(env)
3026 to_py = self.type.is_pyobject
3027 from_py = self.operand.type.is_pyobject
3028 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3029 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3030 if to_py and not from_py:
3031 if self.operand.type.to_py_function:
3032 self.result_ctype = py_object_type
3033 self.operand = self.operand.coerce_to_pyobject(env)
3034 else:
3035 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3036 self.operand = self.operand.coerce_to_simple(env)
3037 elif from_py and not to_py:
3038 if self.type.from_py_function:
3039 self.operand = self.operand.coerce_to(self.type, env)
3040 else:
3041 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3042 elif from_py and to_py:
3043 if self.typecheck and self.type.is_extension_type:
3044 self.operand = PyTypeTestNode(self.operand, self.type, env)
3046 def check_const(self):
3047 self.operand.check_const()
3049 def calculate_result_code(self):
3050 opnd = self.operand
3051 result_code = self.type.cast_code(opnd.result_code)
3052 return result_code
3054 def result_as(self, type):
3055 if self.type.is_pyobject and not self.is_temp:
3056 # Optimise away some unnecessary casting
3057 return self.operand.result_as(type)
3058 else:
3059 return ExprNode.result_as(self, type)
3061 def generate_result_code(self, code):
3062 if self.is_temp:
3063 code.putln(
3064 "%s = (PyObject *)%s;" % (
3065 self.result_code,
3066 self.operand.result_code))
3067 code.put_incref(self.result_code, self.ctype())
3070 class SizeofNode(ExprNode):
3071 # Abstract base class for sizeof(x) expression nodes.
3073 def check_const(self):
3074 pass
3076 def generate_result_code(self, code):
3077 pass
3080 class SizeofTypeNode(SizeofNode):
3081 # C sizeof function applied to a type
3082 #
3083 # base_type CBaseTypeNode
3084 # declarator CDeclaratorNode
3086 subexprs = []
3088 def analyse_types(self, env):
3089 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
3090 # this could be better handled by more uniformly treating types as runtime-available objects
3091 if self.base_type.module_path:
3092 path = self.base_type.module_path
3093 obj = env.lookup(path[0])
3094 if obj.as_module is None:
3095 operand = NameNode(pos=self.pos, name=path[0])
3096 for attr in path[1:]:
3097 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
3098 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
3099 self.operand = operand
3100 self.__class__ = SizeofVarNode
3101 self.analyse_types(env)
3102 return
3103 base_type = self.base_type.analyse(env)
3104 _, arg_type = self.declarator.analyse(base_type, env)
3105 self.arg_type = arg_type
3106 if arg_type.is_pyobject and not arg_type.is_extension_type:
3107 error(self.pos, "Cannot take sizeof Python object")
3108 elif arg_type.is_void:
3109 error(self.pos, "Cannot take sizeof void")
3110 elif not arg_type.is_complete():
3111 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
3112 self.type = PyrexTypes.c_int_type
3114 def calculate_result_code(self):
3115 if self.arg_type.is_extension_type:
3116 # the size of the pointer is boring
3117 # we want the size of the actual struct
3118 arg_code = self.arg_type.declaration_code("", deref=1)
3119 else:
3120 arg_code = self.arg_type.declaration_code("")
3121 return "(sizeof(%s))" % arg_code
3124 class SizeofVarNode(SizeofNode):
3125 # C sizeof function applied to a variable
3126 #
3127 # operand ExprNode
3129 subexprs = ['operand']
3131 def analyse_types(self, env):
3132 self.operand.analyse_types(env)
3133 self.type = PyrexTypes.c_int_type
3135 def calculate_result_code(self):
3136 return "(sizeof(%s))" % self.operand.result_code
3138 def generate_result_code(self, code):
3139 pass
3142 #-------------------------------------------------------------------
3143 #
3144 # Binary operator nodes
3145 #
3146 #-------------------------------------------------------------------
3148 def _not_in(x, seq):
3149 return x not in seq
3151 compile_time_binary_operators = {
3152 '<': operator.lt,
3153 '<=': operator.le,
3154 '==': operator.eq,
3155 '!=': operator.ne,
3156 '>=': operator.ge,
3157 '>': operator.gt,
3158 'is': operator.is_,
3159 'is_not': operator.is_not,
3160 '+': operator.add,
3161 '&': operator.and_,
3162 '/': operator.div,
3163 '//': operator.floordiv,
3164 '<<': operator.lshift,
3165 '%': operator.mod,
3166 '*': operator.mul,
3167 '|': operator.or_,
3168 '**': operator.pow,
3169 '>>': operator.rshift,
3170 '-': operator.sub,
3171 #'/': operator.truediv,
3172 '^': operator.xor,
3173 'in': operator.contains,
3174 'not_in': _not_in,
3175 }
3177 def get_compile_time_binop(node):
3178 func = compile_time_binary_operators.get(node.operator)
3179 if not func:
3180 error(node.pos,
3181 "Binary '%s' not supported in compile-time expression"
3182 % node.operator)
3183 return func
3185 class BinopNode(ExprNode):
3186 # operator string
3187 # operand1 ExprNode
3188 # operand2 ExprNode
3189 #
3190 # Processing during analyse_expressions phase:
3191 #
3192 # analyse_c_operation
3193 # Called when neither operand is a pyobject.
3194 # - Check operand types and coerce if needed.
3195 # - Determine result type and result code fragment.
3196 # - Allocate temporary for result if needed.
3198 subexprs = ['operand1', 'operand2']
3200 def compile_time_value(self, denv):
3201 func = get_compile_time_binop(self)
3202 operand1 = self.operand1.compile_time_value(denv)
3203 operand2 = self.operand2.compile_time_value(denv)
3204 try:
3205 return func(operand1, operand2)
3206 except Exception, e:
3207 self.compile_time_value_error(e)
3209 def analyse_types(self, env):
3210 self.operand1.analyse_types(env)
3211 self.operand2.analyse_types(env)
3212 if self.is_py_operation():
3213 self.coerce_operands_to_pyobjects(env)
3214 self.type = py_object_type
3215 self.gil_check(env)
3216 self.is_temp = 1
3217 if Options.incref_local_binop and self.operand1.type.is_pyobject:
3218 self.operand1 = self.operand1.coerce_to_temp(env)
3219 else:
3220 self.analyse_c_operation(env)
3222 def is_py_operation(self):
3223 return (self.operand1.type.is_pyobject
3224 or self.operand2.type.is_pyobject)
3226 def coerce_operands_to_pyobjects(self, env):
3227 self.operand1 = self.operand1.coerce_to_pyobject(env)
3228 self.operand2 = self.operand2.coerce_to_pyobject(env)
3230 def check_const(self):
3231 self.operand1.check_const()
3232 self.operand2.check_const()
3234 def generate_result_code(self, code):
3235 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
3236 if self.operand1.type.is_pyobject:
3237 function = self.py_operation_function()
3238 if function == "PyNumber_Power":
3239 extra_args = ", Py_None"
3240 else:
3241 extra_args = ""
3242 code.putln(
3243 "%s = %s(%s, %s%s); %s" % (
3244 self.result_code,
3245 function,
3246 self.operand1.py_result(),
3247 self.operand2.py_result(),
3248 extra_args,
3249 code.error_goto_if_null(self.result_code, self.pos)))
3250 else:
3251 if self.is_temp:
3252 self.generate_c_operation_code(code)
3254 def type_error(self):
3255 if not (self.operand1.type.is_error
3256 or self.operand2.type.is_error):
3257 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
3258 (self.operator, self.operand1.type,
3259 self.operand2.type))
3260 self.type = PyrexTypes.error_type
3263 class NumBinopNode(BinopNode):
3264 # Binary operation taking numeric arguments.
3266 def analyse_c_operation(self, env):
3267 type1 = self.operand1.type
3268 type2 = self.operand2.type
3269 if self.operator == "**" and type1.is_int and type2.is_int:
3270 error(self.pos, "** with two C int types is ambiguous")
3271 self.type = error_type
3272 return
3273 self.type = self.compute_c_result_type(type1, type2)
3274 if not self.type:
3275 self.type_error()
3277 def compute_c_result_type(self, type1, type2):
3278 if self.c_types_okay(type1, type2):
3279 return PyrexTypes.widest_numeric_type(type1, type2)
3280 else:
3281 return None
3283 def c_types_okay(self, type1, type2):
3284 #print "NumBinopNode.c_types_okay:", type1, type2 ###
3285 return (type1.is_numeric or type1.is_enum) \
3286 and (type2.is_numeric or type2.is_enum)
3288 def calculate_result_code(self):
3289 return "(%s %s %s)" % (
3290 self.operand1.result_code,
3291 self.operator,
3292 self.operand2.result_code)
3294 def py_operation_function(self):
3295 return self.py_functions[self.operator]
3297 py_functions = {
3298 "|": "PyNumber_Or",
3299 "^": "PyNumber_Xor",
3300 "&": "PyNumber_And",
3301 "<<": "PyNumber_Lshift",
3302 ">>": "PyNumber_Rshift",
3303 "+": "PyNumber_Add",
3304 "-": "PyNumber_Subtract",
3305 "*": "PyNumber_Multiply",
3306 "/": "__Pyx_PyNumber_Divide",
3307 "//": "PyNumber_FloorDivide",
3308 "%": "PyNumber_Remainder",
3309 "**": "PyNumber_Power"
3310 }
3313 class IntBinopNode(NumBinopNode):
3314 # Binary operation taking integer arguments.
3316 def c_types_okay(self, type1, type2):
3317 #print "IntBinopNode.c_types_okay:", type1, type2 ###
3318 return (type1.is_int or type1.is_enum) \
3319 and (type2.is_int or type2.is_enum)
3322 class AddNode(NumBinopNode):
3323 # '+' operator.
3325 def is_py_operation(self):
3326 if self.operand1.type.is_string \
3327 and self.operand2.type.is_string:
3328 return 1
3329 else:
3330 return NumBinopNode.is_py_operation(self)
3332 def compute_c_result_type(self, type1, type2):
3333 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
3334 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3335 return type1
3336 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
3337 return type2
3338 else:
3339 return NumBinopNode.compute_c_result_type(
3340 self, type1, type2)
3343 class SubNode(NumBinopNode):
3344 # '-' operator.
3346 def compute_c_result_type(self, type1, type2):
3347 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3348 return type1
3349 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
3350 return PyrexTypes.c_int_type
3351 else:
3352 return NumBinopNode.compute_c_result_type(
3353 self, type1, type2)
3356 class MulNode(NumBinopNode):
3357 # '*' operator.
3359 def is_py_operation(self):
3360 type1 = self.operand1.type
3361 type2 = self.operand2.type
3362 if (type1.is_string and type2.is_int) \
3363 or (type2.is_string and type1.is_int):
3364 return 1
3365 else:
3366 return NumBinopNode.is_py_operation(self)
3369 class FloorDivNode(NumBinopNode):
3370 # '//' operator.
3372 def calculate_result_code(self):
3373 return "(%s %s %s)" % (
3374 self.operand1.result_code,
3375 "/", # c division is by default floor-div
3376 self.operand2.result_code)
3379 class ModNode(IntBinopNode):
3380 # '%' operator.
3382 def is_py_operation(self):
3383 return (self.operand1.type.is_string
3384 or self.operand2.type.is_string
3385 or IntBinopNode.is_py_operation(self))
3388 class PowNode(NumBinopNode):
3389 # '**' operator.
3391 def analyse_types(self, env):
3392 env.pow_function_used = 1
3393 NumBinopNode.analyse_types(self, env)
3395 def compute_c_result_type(self, type1, type2):
3396 if self.c_types_okay(type1, type2):
3397 return PyrexTypes.c_double_type
3398 else:
3399 return None
3401 def c_types_okay(self, type1, type2):
3402 return (type1.is_float or type2.is_float) and \
3403 NumBinopNode.c_types_okay(self, type1, type2)
3405 def type_error(self):
3406 if not (self.operand1.type.is_error or self.operand2.type.is_error):
3407 if self.operand1.type.is_int and self.operand2.type.is_int:
3408 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
3409 (self.operator, self.operand1.type, self.operand2.type))
3410 else:
3411 NumBinopNode.type_error(self)
3412 self.type = PyrexTypes.error_type
3414 def calculate_result_code(self):
3415 return "pow(%s, %s)" % (
3416 self.operand1.result_code, self.operand2.result_code)
3419 class BoolBinopNode(ExprNode):
3420 # Short-circuiting boolean operation.
3421 #
3422 # operator string
3423 # operand1 ExprNode
3424 # operand2 ExprNode
3425 # temp_bool ExprNode used internally
3427 temp_bool = None
3429 subexprs = ['operand1', 'operand2', 'temp_bool']
3431 def compile_time_value(self, denv):
3432 if self.operator == 'and':
3433 return self.operand1.compile_time_value(denv) \
3434 and self.operand2.compile_time_value(denv)
3435 else:
3436 return self.operand1.compile_time_value(denv) \
3437 or self.operand2.compile_time_value(denv)
3439 def analyse_types(self, env):
3440 self.operand1.analyse_types(env)
3441 self.operand2.analyse_types(env)
3442 if self.operand1.type.is_pyobject or \
3443 self.operand2.type.is_pyobject:
3444 self.operand1 = self.operand1.coerce_to_pyobject(env)
3445 self.operand2 = self.operand2.coerce_to_pyobject(env)
3446 self.temp_bool = TempNode(self.pos, PyrexTypes.c_bint_type, env)
3447 self.type = py_object_type
3448 self.gil_check(env)
3449 else:
3450 self.operand1 = self.operand1.coerce_to_boolean(env)
3451 self.operand2 = self.operand2.coerce_to_boolean(env)
3452 self.type = PyrexTypes.c_bint_type
3453 # For what we're about to do, it's vital that
3454 # both operands be temp nodes.
3455 self.operand1 = self.operand1.coerce_to_temp(env) #CTT
3456 self.operand2 = self.operand2.coerce_to_temp(env)
3457 self.is_temp = 1
3459 gil_message = "Truth-testing Python object"
3461 def allocate_temps(self, env, result_code = None):
3462 # We don't need both operands at the same time, and
3463 # one of the operands will also be our result. So we
3464 # use an allocation strategy here which results in
3465 # this node and both its operands sharing the same
3466 # result variable. This allows us to avoid some
3467 # assignments and increfs/decrefs that would otherwise
3468 # be necessary.
3469 self.allocate_temp(env, result_code)
3470 self.operand1.allocate_temps(env, self.result_code)
3471 if self.temp_bool:
3472 self.temp_bool.allocate_temp(env)
3473 self.temp_bool.release_temp(env)
3474 self.operand2.allocate_temps(env, self.result_code)
3475 # We haven't called release_temp on either operand,
3476 # because although they are temp nodes, they don't own
3477 # their result variable. And because they are temp
3478 # nodes, any temps in their subnodes will have been
3479 # released before their allocate_temps returned.
3480 # Therefore, they contain no temp vars that need to
3481 # be released.
3483 def check_const(self):
3484 self.operand1.check_const()
3485 self.operand2.check_const()
3487 def calculate_result_code(self):
3488 return "(%s %s %s)" % (
3489 self.operand1.result_code,
3490 self.py_to_c_op[self.operator],
3491 self.operand2.result_code)
3493 py_to_c_op = {'and': "&&", 'or': "||"}
3495 def generate_evaluation_code(self, code):
3496 self.operand1.generate_evaluation_code(code)
3497 test_result = self.generate_operand1_test(code)
3498 if self.operator == 'and':
3499 sense = ""
3500 else:
3501 sense = "!"
3502 code.putln(
3503 "if (%s%s) {" % (
3504 sense,
3505 test_result))
3506 self.operand1.generate_disposal_code(code)
3507 self.operand2.generate_evaluation_code(code)
3508 code.putln(
3509 "}")
3511 def generate_operand1_test(self, code):
3512 # Generate code to test the truth of the first operand.
3513 if self.type.is_pyobject:
3514 test_result = self.temp_bool.result_code
3515 code.putln(
3516 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3517 test_result,
3518 self.operand1.py_result(),
3519 code.error_goto_if_neg(test_result, self.pos)))
3520 else:
3521 test_result = self.operand1.result_code
3522 return test_result
3525 class CondExprNode(ExprNode):
3526 # Short-circuiting conditional expression.
3527 #
3528 # test ExprNode
3529 # true_val ExprNode
3530 # false_val ExprNode
3532 temp_bool = None
3533 true_val = None
3534 false_val = None
3536 subexprs = ['test', 'true_val', 'false_val']
3538 def analyse_types(self, env):
3539 self.test.analyse_types(env)
3540 self.test = self.test.coerce_to_boolean(env)
3541 self.true_val.analyse_types(env)
3542 self.false_val.analyse_types(env)
3543 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
3544 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
3545 self.true_val = self.true_val.coerce_to(self.type, env)
3546 self.false_val = self.false_val.coerce_to(self.type, env)
3547 # must be tmp variables so they can share a result
3548 self.true_val = self.true_val.coerce_to_temp(env)
3549 self.false_val = self.false_val.coerce_to_temp(env)
3550 self.is_temp = 1
3551 if self.type == PyrexTypes.error_type:
3552 self.type_error()
3554 def allocate_temps(self, env, result_code = None):
3555 # We only ever evaluate one side, and this is
3556 # after evaluating the truth value, so we may
3557 # use an allocation strategy here which results in
3558 # this node and both its operands sharing the same
3559 # result variable. This allows us to avoid some
3560 # assignments and increfs/decrefs that would otherwise
3561 # be necessary.
3562 self.allocate_temp(env, result_code)
3563 self.test.allocate_temps(env, result_code)
3564 self.true_val.allocate_temps(env, self.result_code)
3565 self.false_val.allocate_temps(env, self.result_code)
3566 # We haven't called release_temp on either value,
3567 # because although they are temp nodes, they don't own
3568 # their result variable. And because they are temp
3569 # nodes, any temps in their subnodes will have been
3570 # released before their allocate_temps returned.
3571 # Therefore, they contain no temp vars that need to
3572 # be released.
3574 def compute_result_type(self, type1, type2):
3575 if type1 == type2:
3576 return type1
3577 elif type1.is_numeric and type2.is_numeric:
3578 return PyrexTypes.widest_numeric_type(type1, type2)
3579 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
3580 return type2
3581 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
3582 return type1
3583 elif type1.is_pyobject or type2.is_pyobject:
3584 return py_object_type
3585 elif type1.assignable_from(type2):
3586 return type1
3587 elif type2.assignable_from(type1):
3588 return type2
3589 else:
3590 return PyrexTypes.error_type
3592 def type_error(self):
3593 if not (self.true_val.type.is_error or self.false_val.type.is_error):
3594 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
3595 (self.true_val.type, self.false_val.type))
3596 self.type = PyrexTypes.error_type
3598 def check_const(self):
3599 self.test.check_const()
3600 self.true_val.check_const()
3601 self.false_val.check_const()
3603 def generate_evaluation_code(self, code):
3604 self.test.generate_evaluation_code(code)
3605 code.putln("if (%s) {" % self.test.result_code )
3606 self.true_val.generate_evaluation_code(code)
3607 code.putln("} else {")
3608 self.false_val.generate_evaluation_code(code)
3609 code.putln("}")
3610 self.test.generate_disposal_code(code)
3612 richcmp_constants = {
3613 "<" : "Py_LT",
3614 "<=": "Py_LE",
3615 "==": "Py_EQ",
3616 "!=": "Py_NE",
3617 "<>": "Py_NE",
3618 ">" : "Py_GT",
3619 ">=": "Py_GE",
3620 }
3622 class CmpNode:
3623 # Mixin class containing code common to PrimaryCmpNodes
3624 # and CascadedCmpNodes.
3626 def cascaded_compile_time_value(self, operand1, denv):
3627 func = get_compile_time_binop(self)
3628 operand2 = self.operand2.compile_time_value(denv)
3629 try:
3630 result = func(operand1, operand2)
3631 except Exception, e:
3632 self.compile_time_value_error(e)
3633 result = None
3634 if result:
3635 cascade = self.cascade
3636 if cascade:
3637 result = result and cascade.compile_time_value(operand2, denv)
3638 return result
3640 def is_python_comparison(self):
3641 return (self.has_python_operands()
3642 or (self.cascade and self.cascade.is_python_comparison())
3643 or self.operator in ('in', 'not_in'))
3645 def is_python_result(self):
3646 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
3647 or (self.cascade and self.cascade.is_python_result()))
3649 def check_types(self, env, operand1, op, operand2):
3650 if not self.types_okay(operand1, op, operand2):
3651 error(self.pos, "Invalid types for '%s' (%s, %s)" %
3652 (self.operator, operand1.type, operand2.type))
3654 def types_okay(self, operand1, op, operand2):
3655 type1 = operand1.type
3656 type2 = operand2.type
3657 if type1.is_error or type2.is_error:
3658 return 1
3659 if type1.is_pyobject: # type2 will be, too
3660 return 1
3661 elif type1.is_ptr or type1.is_array:
3662 return type1.is_null_ptr or type2.is_null_ptr \
3663 or ((type2.is_ptr or type2.is_array)
3664 and type1.base_type.same_as(type2.base_type))
3665 elif ((type1.is_numeric and type2.is_numeric
3666 or type1.is_enum and (type1 is type2 or type2.is_int)
3667 or type1.is_int and type2.is_enum)
3668 and op not in ('is', 'is_not')):
3669 return 1
3670 else:
3671 return type1.is_cfunction and type1.is_cfunction and type1 == type2
3673 def generate_operation_code(self, code, result_code,
3674 operand1, op , operand2):
3675 if self.type is PyrexTypes.py_object_type:
3676 coerce_result = "__Pyx_PyBool_FromLong"
3677 else:
3678 coerce_result = ""
3679 if 'not' in op: negation = "!"
3680 else: negation = ""
3681 if op == 'in' or op == 'not_in':
3682 code.putln(
3683 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
3684 result_code,
3685 coerce_result,
3686 negation,
3687 operand2.py_result(),
3688 operand1.py_result(),
3689 code.error_goto_if_neg(result_code, self.pos)))
3690 elif (operand1.type.is_pyobject
3691 and op not in ('is', 'is_not')):
3692 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
3693 result_code,
3694 operand1.py_result(),
3695 operand2.py_result(),
3696 richcmp_constants[op],
3697 code.error_goto_if_null(result_code, self.pos)))
3698 else:
3699 type1 = operand1.type
3700 type2 = operand2.type
3701 if (type1.is_extension_type or type2.is_extension_type) \
3702 and not type1.same_as(type2):
3703 common_type = py_object_type
3704 elif type1.is_numeric:
3705 common_type = PyrexTypes.widest_numeric_type(type1, type2)
3706 else:
3707 common_type = type1
3708 code1 = operand1.result_as(common_type)
3709 code2 = operand2.result_as(common_type)
3710 code.putln("%s = %s(%s %s %s);" % (
3711 result_code,
3712 coerce_result,
3713 code1,
3714 self.c_operator(op),
3715 code2))
3717 def c_operator(self, op):
3718 if op == 'is':
3719 return "=="
3720 elif op == 'is_not':
3721 return "!="
3722 else:
3723 return op
3726 class PrimaryCmpNode(ExprNode, CmpNode):
3727 # Non-cascaded comparison or first comparison of
3728 # a cascaded sequence.
3729 #
3730 # operator string
3731 # operand1 ExprNode
3732 # operand2 ExprNode
3733 # cascade CascadedCmpNode
3735 # We don't use the subexprs mechanism, because
3736 # things here are too complicated for it to handle.
3737 # Instead, we override all the framework methods
3738 # which use it.
3740 child_attrs = ['operand1', 'operand2', 'cascade']
3742 cascade = None
3744 def compile_time_value(self, denv):
3745 operand1 = self.operand1.compile_time_value(denv)
3746 return self.cascaded_compile_time_value(operand1, denv)
3748 def analyse_types(self, env):
3749 self.operand1.analyse_types(env)
3750 self.operand2.analyse_types(env)
3751 if self.cascade:
3752 self.cascade.analyse_types(env, self.operand2)
3753 self.is_pycmp = self.is_python_comparison()
3754 if self.is_pycmp:
3755 self.coerce_operands_to_pyobjects(env)
3756 if self.has_int_operands():
3757 self.coerce_chars_to_ints(env)
3758 if self.cascade:
3759 self.operand2 = self.operand2.coerce_to_simple(env)
3760 self.cascade.coerce_cascaded_operands_to_temp(env)
3761 self.check_operand_types(env)
3762 if self.is_python_result():
3763 self.type = PyrexTypes.py_object_type
3764 else:
3765 self.type = PyrexTypes.c_bint_type
3766 cdr = self.cascade
3767 while cdr:
3768 cdr.type = self.type
3769 cdr = cdr.cascade
3770 if self.is_pycmp or self.cascade:
3771 self.is_temp = 1
3773 def check_operand_types(self, env):
3774 self.check_types(env,
3775 self.operand1, self.operator, self.operand2)
3776 if self.cascade:
3777 self.cascade.check_operand_types(env, self.operand2)
3779 def has_python_operands(self):
3780 return (self.operand1.type.is_pyobject
3781 or self.operand2.type.is_pyobject)
3783 def coerce_operands_to_pyobjects(self, env):
3784 self.operand1 = self.operand1.coerce_to_pyobject(env)
3785 self.operand2 = self.operand2.coerce_to_pyobject(env)
3786 if self.cascade:
3787 self.cascade.coerce_operands_to_pyobjects(env)
3789 def has_int_operands(self):
3790 return (self.operand1.type.is_int or self.operand2.type.is_int) \
3791 or (self.cascade and self.cascade.has_int_operands())
3793 def coerce_chars_to_ints(self, env):
3794 # coerce literal single-char strings to c chars
3795 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
3796 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
3797 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
3798 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3799 if self.cascade:
3800 self.cascade.coerce_chars_to_ints(env)
3802 def allocate_subexpr_temps(self, env):
3803 self.operand1.allocate_temps(env)
3804 self.operand2.allocate_temps(env)
3805 if self.cascade:
3806 self.cascade.allocate_subexpr_temps(env)
3808 def release_subexpr_temps(self, env):
3809 self.operand1.release_temp(env)
3810 self.operand2.release_temp(env)
3811 if self.cascade:
3812 self.cascade.release_subexpr_temps(env)
3814 def check_const(self):
3815 self.operand1.check_const()
3816 self.operand2.check_const()
3817 if self.cascade:
3818 self.not_const()
3820 def calculate_result_code(self):
3821 return "(%s %s %s)" % (
3822 self.operand1.result_code,
3823 self.c_operator(self.operator),
3824 self.operand2.result_code)
3826 def generate_evaluation_code(self, code):
3827 self.operand1.generate_evaluation_code(code)
3828 self.operand2.generate_evaluation_code(code)
3829 if self.is_temp:
3830 self.generate_operation_code(code, self.result_code,
3831 self.operand1, self.operator, self.operand2)
3832 if self.cascade:
3833 self.cascade.generate_evaluation_code(code,
3834 self.result_code, self.operand2)
3835 self.operand1.generate_disposal_code(code)
3836 self.operand2.generate_disposal_code(code)
3838 def generate_subexpr_disposal_code(self, code):
3839 # If this is called, it is a non-cascaded cmp,
3840 # so only need to dispose of the two main operands.
3841 self.operand1.generate_disposal_code(code)
3842 self.operand2.generate_disposal_code(code)
3844 def annotate(self, code):
3845 self.operand1.annotate(code)
3846 self.operand2.annotate(code)
3847 if self.cascade:
3848 self.cascade.annotate(code)
3851 class CascadedCmpNode(Node, CmpNode):
3852 # A CascadedCmpNode is not a complete expression node. It
3853 # hangs off the side of another comparison node, shares
3854 # its left operand with that node, and shares its result
3855 # with the PrimaryCmpNode at the head of the chain.
3856 #
3857 # operator string
3858 # operand2 ExprNode
3859 # cascade CascadedCmpNode
3861 child_attrs = ['operand2', 'cascade']
3863 cascade = None
3865 def analyse_types(self, env, operand1):
3866 self.operand2.analyse_types(env)
3867 if self.cascade:
3868 self.cascade.analyse_types(env, self.operand2)
3870 def check_operand_types(self, env, operand1):
3871 self.check_types(env,
3872 operand1, self.operator, self.operand2)
3873 if self.cascade:
3874 self.cascade.check_operand_types(env, self.operand2)
3876 def has_python_operands(self):
3877 return self.operand2.type.is_pyobject
3879 def coerce_operands_to_pyobjects(self, env):
3880 self.operand2 = self.operand2.coerce_to_pyobject(env)
3881 if self.cascade:
3882 self.cascade.coerce_operands_to_pyobjects(env)
3884 def has_int_operands(self):
3885 return self.operand2.type.is_int
3887 def coerce_chars_to_ints(self, env):
3888 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
3889 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3891 def coerce_cascaded_operands_to_temp(self, env):
3892 if self.cascade:
3893 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
3894 self.operand2 = self.operand2.coerce_to_simple(env)
3895 self.cascade.coerce_cascaded_operands_to_temp(env)
3897 def allocate_subexpr_temps(self, env):
3898 self.operand2.allocate_temps(env)
3899 if self.cascade:
3900 self.cascade.allocate_subexpr_temps(env)
3902 def release_subexpr_temps(self, env):
3903 self.operand2.release_temp(env)
3904 if self.cascade:
3905 self.cascade.release_subexpr_temps(env)
3907 def generate_evaluation_code(self, code, result, operand1):
3908 if self.type.is_pyobject:
3909 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
3910 else:
3911 code.putln("if (%s) {" % result)
3912 self.operand2.generate_evaluation_code(code)
3913 self.generate_operation_code(code, result,
3914 operand1, self.operator, self.operand2)
3915 if self.cascade:
3916 self.cascade.generate_evaluation_code(
3917 code, result, self.operand2)
3918 # Cascaded cmp result is always temp
3919 self.operand2.generate_disposal_code(code)
3920 code.putln("}")
3922 def annotate(self, code):
3923 self.operand2.annotate(code)
3924 if self.cascade:
3925 self.cascade.annotate(code)
3928 binop_node_classes = {
3929 "or": BoolBinopNode,
3930 "and": BoolBinopNode,
3931 "|": IntBinopNode,
3932 "^": IntBinopNode,
3933 "&": IntBinopNode,
3934 "<<": IntBinopNode,
3935 ">>": IntBinopNode,
3936 "+": AddNode,
3937 "-": SubNode,
3938 "*": MulNode,
3939 "/": NumBinopNode,
3940 "//": FloorDivNode,
3941 "%": ModNode,
3942 "**": PowNode
3943 }
3945 def binop_node(pos, operator, operand1, operand2):
3946 # Construct binop node of appropriate class for
3947 # given operator.
3948 return binop_node_classes[operator](pos,
3949 operator = operator,
3950 operand1 = operand1,
3951 operand2 = operand2)
3953 #-------------------------------------------------------------------
3954 #
3955 # Coercion nodes
3956 #
3957 # Coercion nodes are special in that they are created during
3958 # the analyse_types phase of parse tree processing.
3959 # Their __init__ methods consequently incorporate some aspects
3960 # of that phase.
3961 #
3962 #-------------------------------------------------------------------
3964 class CoercionNode(ExprNode):
3965 # Abstract base class for coercion nodes.
3966 #
3967 # arg ExprNode node being coerced
3969 subexprs = ['arg']
3971 def __init__(self, arg):
3972 self.pos = arg.pos
3973 self.arg = arg
3974 self.options = arg.options
3975 if debug_coercion:
3976 print("%s Coercing %s" % (self, self.arg))
3978 def annotate(self, code):
3979 self.arg.annotate(code)
3980 if self.arg.type != self.type:
3981 file, line, col = self.pos
3982 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
3985 class CastNode(CoercionNode):
3986 # Wrap a node in a C type cast.
3988 def __init__(self, arg, new_type):
3989 CoercionNode.__init__(self, arg)
3990 self.type = new_type
3992 def calculate_result_code(self):
3993 return self.arg.result_as(self.type)
3995 def generate_result_code(self, code):
3996 self.arg.generate_result_code(code)
3999 class PyTypeTestNode(CoercionNode):
4000 # This node is used to check that a generic Python
4001 # object is an instance of a particular extension type.
4002 # This node borrows the result of its argument node.
4004 def __init__(self, arg, dst_type, env):
4005 # The arg is know to be a Python object, and
4006 # the dst_type is known to be an extension type.
4007 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
4008 CoercionNode.__init__(self, arg)
4009 self.type = dst_type
4010 self.gil_check(env)
4011 self.result_ctype = arg.ctype()
4012 env.use_utility_code(type_test_utility_code)
4014 gil_message = "Python type test"
4016 def analyse_types(self, env):
4017 pass
4019 def result_in_temp(self):
4020 return self.arg.result_in_temp()
4022 def is_ephemeral(self):
4023 return self.arg.is_ephemeral()
4025 def calculate_result_code(self):
4026 return self.arg.result_code
4028 def generate_result_code(self, code):
4029 if self.type.typeobj_is_available():
4030 code.putln(
4031 "if (!(%s)) %s" % (
4032 self.type.type_test_code(self.arg.py_result()),
4033 code.error_goto(self.pos)))
4034 else:
4035 error(self.pos, "Cannot test type of extern C class "
4036 "without type object name specification")
4038 def generate_post_assignment_code(self, code):
4039 self.arg.generate_post_assignment_code(code)
4042 class CoerceToPyTypeNode(CoercionNode):
4043 # This node is used to convert a C data type
4044 # to a Python object.
4046 def __init__(self, arg, env):
4047 CoercionNode.__init__(self, arg)
4048 self.type = py_object_type
4049 self.gil_check(env)
4050 self.is_temp = 1
4051 if not arg.type.to_py_function:
4052 error(arg.pos,
4053 "Cannot convert '%s' to Python object" % arg.type)
4055 gil_message = "Converting to Python object"
4057 def analyse_types(self, env):
4058 # The arg is always already analysed
4059 pass
4061 def generate_result_code(self, code):
4062 function = self.arg.type.to_py_function
4063 code.putln('%s = %s(%s); %s' % (
4064 self.result_code,
4065 function,
4066 self.arg.result_code,
4067 code.error_goto_if_null(self.result_code, self.pos)))
4070 class CoerceFromPyTypeNode(CoercionNode):
4071 # This node is used to convert a Python object
4072 # to a C data type.
4074 def __init__(self, result_type, arg, env):
4075 CoercionNode.__init__(self, arg)
4076 self.type = result_type
4077 self.is_temp = 1
4078 if not result_type.from_py_function:
4079 error(arg.pos,
4080 "Cannot convert Python object to '%s'" % result_type)
4081 if self.type.is_string and self.arg.is_ephemeral():
4082 error(arg.pos,
4083 "Obtaining char * from temporary Python value")
4085 def analyse_types(self, env):
4086 # The arg is always already analysed
4087 pass
4089 def generate_result_code(self, code):
4090 function = self.type.from_py_function
4091 operand = self.arg.py_result()
4092 rhs = "%s(%s)" % (function, operand)
4093 if self.type.is_enum:
4094 rhs = typecast(self.type, c_long_type, rhs)
4095 code.putln('%s = %s; %s' % (
4096 self.result_code,
4097 rhs,
4098 code.error_goto_if(self.type.error_condition(self.result_code), self.pos)))
4101 class CoerceToBooleanNode(CoercionNode):
4102 # This node is used when a result needs to be used
4103 # in a boolean context.
4105 def __init__(self, arg, env):
4106 CoercionNode.__init__(self, arg)
4107 self.type = PyrexTypes.c_bint_type
4108 if arg.type.is_pyobject:
4109 if env.nogil:
4110 self.gil_error()
4111 self.is_temp = 1
4113 gil_message = "Truth-testing Python object"
4115 def check_const(self):
4116 if self.is_temp:
4117 self.not_const()
4118 self.arg.check_const()
4120 def calculate_result_code(self):
4121 return "(%s != 0)" % self.arg.result_code
4123 def generate_result_code(self, code):
4124 if self.arg.type.is_pyobject:
4125 code.putln(
4126 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4127 self.result_code,
4128 self.arg.py_result(),
4129 code.error_goto_if_neg(self.result_code, self.pos)))
4132 class CoerceToTempNode(CoercionNode):
4133 # This node is used to force the result of another node
4134 # to be stored in a temporary. It is only used if the
4135 # argument node's result is not already in a temporary.
4137 def __init__(self, arg, env):
4138 CoercionNode.__init__(self, arg)
4139 self.type = self.arg.type
4140 self.is_temp = 1
4141 if self.type.is_pyobject:
4142 self.gil_check(env)
4143 self.result_ctype = py_object_type
4145 gil_message = "Creating temporary Python reference"
4147 def analyse_types(self, env):
4148 # The arg is always already analysed
4149 pass
4151 def generate_result_code(self, code):
4152 #self.arg.generate_evaluation_code(code) # Already done
4153 # by generic generate_subexpr_evaluation_code!
4154 code.putln("%s = %s;" % (
4155 self.result_code, self.arg.result_as(self.ctype())))
4156 if self.type.is_pyobject:
4157 code.put_incref(self.result_code, self.ctype())
4160 class CloneNode(CoercionNode):
4161 # This node is employed when the result of another node needs
4162 # to be used multiple times. The argument node's result must
4163 # be in a temporary. This node "borrows" the result from the
4164 # argument node, and does not generate any evaluation or
4165 # disposal code for it. The original owner of the argument
4166 # node is responsible for doing those things.
4168 subexprs = [] # Arg is not considered a subexpr
4170 def __init__(self, arg):
4171 CoercionNode.__init__(self, arg)
4172 if hasattr(arg, 'type'):
4173 self.type = arg.type
4174 self.result_ctype = arg.result_ctype
4175 if hasattr(arg, 'entry'):
4176 self.entry = arg.entry
4178 def calculate_result_code(self):
4179 return self.arg.result_code
4181 def analyse_types(self, env):
4182 self.type = self.arg.type
4183 self.result_ctype = self.arg.result_ctype
4184 self.is_temp = 1
4185 if hasattr(self.arg, 'entry'):
4186 self.entry = self.arg.entry
4188 def generate_evaluation_code(self, code):
4189 pass
4191 def generate_result_code(self, code):
4192 pass
4194 def generate_disposal_code(self, code):
4195 pass
4197 def allocate_temps(self, env):
4198 self.result_code = self.calculate_result_code()
4200 def release_temp(self, env):
4201 pass
4203 class PersistentNode(ExprNode):
4204 # A PersistentNode is like a CloneNode except it handles the temporary
4205 # allocation itself by keeping track of the number of times it has been
4206 # used.
4208 subexprs = ["arg"]
4209 temp_counter = 0
4210 generate_counter = 0
4211 analyse_counter = 0
4212 result_code = None
4214 def __init__(self, arg, uses):
4215 self.pos = arg.pos
4216 self.arg = arg
4217 self.uses = uses
4219 def analyse_types(self, env):
4220 if self.analyse_counter == 0:
4221 self.arg.analyse_types(env)
4222 self.type = self.arg.type
4223 self.result_ctype = self.arg.result_ctype
4224 self.is_temp = 1
4225 self.analyse_counter += 1
4227 def calculate_result_code(self):
4228 return self.result_code
4230 def generate_evaluation_code(self, code):
4231 if self.generate_counter == 0:
4232 self.arg.generate_evaluation_code(code)
4233 code.putln("%s = %s;" % (
4234 self.result_code, self.arg.result_as(self.ctype())))
4235 if self.type.is_pyobject:
4236 code.put_incref(self.result_code, self.ctype())
4237 self.arg.generate_disposal_code(code)
4238 self.generate_counter += 1
4240 def generate_disposal_code(self, code):
4241 if self.generate_counter == self.uses:
4242 if self.type.is_pyobject:
4243 code.put_decref_clear(self.result_code, self.ctype())
4245 def allocate_temps(self, env, result=None):
4246 if self.temp_counter == 0:
4247 self.arg.allocate_temps(env)
4248 self.allocate_temp(env, result)
4249 self.arg.release_temp(env)
4250 self.temp_counter += 1
4252 def allocate_temp(self, env, result=None):
4253 if result is None:
4254 self.result_code = env.allocate_temp(self.type)
4255 else:
4256 self.result_code = result
4258 def release_temp(self, env):
4259 if self.temp_counter == self.uses:
4260 env.release_temp(self.result_code)
4262 #------------------------------------------------------------------------------------
4263 #
4264 # Runtime support code
4265 #
4266 #------------------------------------------------------------------------------------
4268 get_name_interned_utility_code = [
4269 """
4270 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
4271 ""","""
4272 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
4273 PyObject *result;
4274 result = PyObject_GetAttr(dict, name);
4275 if (!result)
4276 PyErr_SetObject(PyExc_NameError, name);
4277 return result;
4278 }
4279 """]
4281 #------------------------------------------------------------------------------------
4283 import_utility_code = [
4284 """
4285 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
4286 ""","""
4287 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
4288 PyObject *__import__ = 0;
4289 PyObject *empty_list = 0;
4290 PyObject *module = 0;
4291 PyObject *global_dict = 0;
4292 PyObject *empty_dict = 0;
4293 PyObject *list;
4294 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
4295 if (!__import__)
4296 goto bad;
4297 if (from_list)
4298 list = from_list;
4299 else {
4300 empty_list = PyList_New(0);
4301 if (!empty_list)
4302 goto bad;
4303 list = empty_list;
4304 }
4305 global_dict = PyModule_GetDict(%(GLOBALS)s);
4306 if (!global_dict)
4307 goto bad;
4308 empty_dict = PyDict_New();
4309 if (!empty_dict)
4310 goto bad;
4311 module = PyObject_CallFunction(__import__, "OOOO",
4312 name, global_dict, empty_dict, list);
4313 bad:
4314 Py_XDECREF(empty_list);
4315 Py_XDECREF(__import__);
4316 Py_XDECREF(empty_dict);
4317 return module;
4318 }
4319 """ % {
4320 "BUILTINS": Naming.builtins_cname,
4321 "GLOBALS": Naming.module_cname,
4322 }]
4324 #------------------------------------------------------------------------------------
4326 get_exception_utility_code = [
4327 """
4328 static PyObject *__Pyx_GetExcValue(void); /*proto*/
4329 ""","""
4330 static PyObject *__Pyx_GetExcValue(void) {
4331 PyObject *type = 0, *value = 0, *tb = 0;
4332 PyObject *tmp_type, *tmp_value, *tmp_tb;
4333 PyObject *result = 0;
4334 PyThreadState *tstate = PyThreadState_Get();
4335 PyErr_Fetch(&type, &value, &tb);
4336 PyErr_NormalizeException(&type, &value, &tb);
4337 if (PyErr_Occurred())
4338 goto bad;
4339 if (!value) {
4340 value = Py_None;
4341 Py_INCREF(value);
4342 }
4343 tmp_type = tstate->exc_type;
4344 tmp_value = tstate->exc_value;
4345 tmp_tb = tstate->exc_traceback;
4346 tstate->exc_type = type;
4347 tstate->exc_value = value;
4348 tstate->exc_traceback = tb;
4349 /* Make sure tstate is in a consistent state when we XDECREF
4350 these objects (XDECREF may run arbitrary code). */
4351 Py_XDECREF(tmp_type);
4352 Py_XDECREF(tmp_value);
4353 Py_XDECREF(tmp_tb);
4354 result = value;
4355 Py_XINCREF(result);
4356 type = 0;
4357 value = 0;
4358 tb = 0;
4359 bad:
4360 Py_XDECREF(type);
4361 Py_XDECREF(value);
4362 Py_XDECREF(tb);
4363 return result;
4364 }
4365 """]
4367 #------------------------------------------------------------------------------------
4369 unpacking_utility_code = [
4370 """
4371 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
4372 static int __Pyx_EndUnpack(PyObject *); /*proto*/
4373 ""","""
4374 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
4375 PyObject *item;
4376 if (!(item = PyIter_Next(iter))) {
4377 if (!PyErr_Occurred()) {
4378 PyErr_Format(PyExc_ValueError,
4379 #if PY_VERSION_HEX < 0x02050000
4380 "need more than %d values to unpack", (int)index);
4381 #else
4382 "need more than %zd values to unpack", index);
4383 #endif
4384 }
4385 }
4386 return item;
4387 }
4389 static int __Pyx_EndUnpack(PyObject *iter) {
4390 PyObject *item;
4391 if ((item = PyIter_Next(iter))) {
4392 Py_DECREF(item);
4393 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
4394 return -1;
4395 }
4396 else if (!PyErr_Occurred())
4397 return 0;
4398 else
4399 return -1;
4400 }
4401 """]
4403 #------------------------------------------------------------------------------------
4405 type_test_utility_code = [
4406 """
4407 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
4408 ""","""
4409 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
4410 if (!type) {
4411 PyErr_Format(PyExc_SystemError, "Missing type object");
4412 return 0;
4413 }
4414 if (obj == Py_None || PyObject_TypeCheck(obj, type))
4415 return 1;
4416 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
4417 Py_TYPE(obj)->tp_name, type->tp_name);
4418 return 0;
4419 }
4420 """]
4422 #------------------------------------------------------------------------------------
4424 create_class_utility_code = [
4425 """
4426 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
4427 ""","""
4428 static PyObject *__Pyx_CreateClass(
4429 PyObject *bases, PyObject *dict, PyObject *name, char *modname)
4430 {
4431 PyObject *py_modname;
4432 PyObject *result = 0;
4434 #if PY_MAJOR_VERSION < 3
4435 py_modname = PyString_FromString(modname);
4436 #else
4437 py_modname = PyUnicode_FromString(modname);
4438 #endif
4439 if (!py_modname)
4440 goto bad;
4441 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
4442 goto bad;
4443 #if PY_MAJOR_VERSION < 3
4444 result = PyClass_New(bases, dict, name);
4445 #else
4446 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
4447 #endif
4448 bad:
4449 Py_XDECREF(py_modname);
4450 return result;
4451 }
4452 """]
4454 #------------------------------------------------------------------------------------
4456 cpp_exception_utility_code = [
4457 """
4458 #ifndef __Pyx_CppExn2PyErr
4459 static void __Pyx_CppExn2PyErr() {
4460 try {
4461 if (PyErr_Occurred())
4462 ; // let the latest Python exn pass through and ignore the current one
4463 else
4464 throw;
4465 } catch (const std::out_of_range& exn) {
4466 // catch out_of_range explicitly so the proper Python exn may be raised
4467 PyErr_SetString(PyExc_IndexError, exn.what());
4468 } catch (const std::exception& exn) {
4469 PyErr_SetString(PyExc_RuntimeError, exn.what());
4470 }
4471 catch (...)
4472 {
4473 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
4474 }
4475 }
4476 #endif
4477 """,""]
4479 #------------------------------------------------------------------------------------
4481 append_utility_code = [
4482 """
4483 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
4484 if (likely(PyList_CheckExact(L))) {
4485 if (PyList_Append(L, x) < 0) return NULL;
4486 Py_INCREF(Py_None);
4487 return Py_None; // this is just to have an accurate signature
4488 }
4489 else {
4490 return PyObject_CallMethod(L, "append", "(O)", x);
4491 }
4492 }
4493 """,""
4494 ]
4496 #------------------------------------------------------------------------------------
4498 # If the is_unsigned flag is set, we need to do some extra work to make
4499 # sure the index doesn't become negative.
4501 getitem_int_utility_code = [
4502 """
4503 static INLINE PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
4504 PyObject *r;
4505 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
4506 r = PyList_GET_ITEM(o, i);
4507 Py_INCREF(r);
4508 }
4509 else if (PyTuple_CheckExact(o) && 0 <= i && i < PyTuple_GET_SIZE(o)) {
4510 r = PyTuple_GET_ITEM(o, i);
4511 Py_INCREF(r);
4512 }
4513 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0) || !is_unsigned))
4514 r = PySequence_GetItem(o, i);
4515 else {
4516 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);
4517 if (!j)
4518 return 0;
4519 r = PyObject_GetItem(o, j);
4520 Py_DECREF(j);
4521 }
4522 return r;
4523 }
4524 """,
4525 """
4526 """]
4528 #------------------------------------------------------------------------------------
4530 setitem_int_utility_code = [
4531 """
4532 static INLINE int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v, int is_unsigned) {
4533 int r;
4534 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
4535 Py_DECREF(PyList_GET_ITEM(o, i));
4536 Py_INCREF(v);
4537 PyList_SET_ITEM(o, i, v);
4538 return 1;
4539 }
4540 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
4541 r = PySequence_SetItem(o, i, v);
4542 else {
4543 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);
4544 if (!j)
4545 return -1;
4546 r = PyObject_SetItem(o, j, v);
4547 Py_DECREF(j);
4548 }
4549 return r;
4550 }
4551 """,
4552 """
4553 """]
