2 # Pyrex - Parse tree nodes for expressions
6 from string import join
8 from Errors import error, warning, InternalError
10 from Nodes import Node
12 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
13 from Builtin import list_type, tuple_type, dict_type
16 from Annotate import AnnotationItem
18 from Cython.Debugging import print_call_chain
19 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
24 # subexprs [string] Class var holding names of subexpr node attrs
25 # type PyrexType Type of the result
26 # result_code string Code fragment
27 # result_ctype string C type of result_code if different from type
28 # is_temp boolean Result is in a temporary variable
29 # is_sequence_constructor
30 # boolean Is a list or tuple constructor expression
32 # [ExprNode or [ExprNode or None] or None]
33 # Cached result of subexpr_nodes()
38 # The Analyse Expressions phase for expressions is split
39 # into two sub-phases:
42 # Determines the result type of the expression based
43 # on the types of its sub-expressions, and inserts
44 # coercion nodes into the expression tree where needed.
45 # Marks nodes which will need to have temporary variables
49 # Allocates temporary variables where needed, and fills
50 # in the result_code field of each node.
52 # ExprNode provides some convenience routines which
53 # perform both of the above phases. These should only
54 # be called from statement nodes, and only when no
55 # coercion nodes need to be added around the expression
56 # being analysed. In that case, the above two phases
57 # should be invoked separately.
59 # Framework code in ExprNode provides much of the common
60 # processing for the various phases. It makes use of the
61 # 'subexprs' class attribute of ExprNodes, which should
62 # contain a list of the names of attributes which can
63 # hold sub-nodes or sequences of sub-nodes.
65 # The framework makes use of a number of abstract methods.
66 # Their responsibilities are as follows.
68 # Declaration Analysis phase
70 # analyse_target_declaration
71 # Called during the Analyse Declarations phase to analyse
72 # the LHS of an assignment or argument of a del statement.
73 # Nodes which cannot be the LHS of an assignment need not
76 # Expression Analysis phase
79 # - Call analyse_types on all sub-expressions.
80 # - Check operand types, and wrap coercion nodes around
81 # sub-expressions where needed.
82 # - Set the type of this node.
83 # - If a temporary variable will be required for the
84 # result, set the is_temp flag of this node.
86 # analyse_target_types
87 # Called during the Analyse Types phase to analyse
88 # the LHS of an assignment or argument of a del
89 # statement. Similar responsibilities to analyse_types.
92 # - Call allocate_temps for all sub-nodes.
93 # - Call allocate_temp for this node.
94 # - If a temporary was allocated, call release_temp on
95 # all sub-expressions.
97 # allocate_target_temps
98 # - Call allocate_temps on sub-nodes and allocate any other
99 # temps used during assignment.
100 # - Fill in result_code with a C lvalue if needed.
101 # - If a rhs node is supplied, call release_temp on it.
102 # - Call release_temp on sub-nodes and release any other
103 # temps used during assignment.
105 # calculate_result_code
106 # - Called during the Allocate Temps phase. Should return a
107 # C code fragment evaluating to the result. This is only
108 # called when the result is not a temporary.
111 # Called by the default implementation of allocate_target_temps.
112 # Should return a C lvalue for assigning to the node. The default
113 # implementation calls calculate_result_code.
116 # - Check that this node and its subnodes form a
117 # legal constant expression. If so, do nothing,
118 # otherwise call not_const.
120 # The default implementation of check_const
121 # assumes that the expression is not constant.
124 # - Same as check_const, except check that the
125 # expression is a C lvalue whose address is
126 # constant. Otherwise, call addr_not_const.
128 # The default implementation of calc_const_addr
129 # assumes that the expression is not a constant
132 # Code Generation phase
134 # generate_evaluation_code
135 # - Call generate_evaluation_code for sub-expressions.
136 # - Perform the functions of generate_result_code
138 # - If result is temporary, call generate_disposal_code
139 # on all sub-expressions.
141 # A default implementation of generate_evaluation_code
142 # is provided which uses the following abstract method:
144 # generate_result_code
145 # - Generate any C statements necessary to calculate
146 # the result of this node from the results of its
149 # generate_assignment_code
150 # Called on the LHS of an assignment.
151 # - Call generate_evaluation_code for sub-expressions.
152 # - Generate code to perform the assignment.
153 # - If the assignment absorbed a reference, call
154 # generate_post_assignment_code on the RHS,
155 # otherwise call generate_disposal_code on it.
157 # generate_deletion_code
158 # Called on an argument of a del statement.
159 # - Call generate_evaluation_code for sub-expressions.
160 # - Generate code to perform the deletion.
161 # - Call generate_disposal_code on all sub-expressions.
165 is_sequence_constructor = 0
168 saved_subexpr_nodes = None
171 def get_child_attrs(self):
172 """Automatically provide the contents of subexprs as children, unless child_attr
173 has been declared. See Nodes.Node.get_child_accessors."""
174 if self.child_attrs is not None:
175 return self.child_attrs
176 elif self.subexprs is not None:
179 def not_implemented(self, method_name):
180 print_call_chain(method_name, "not implemented") ###
182 "%s.%s not implemented" %
183 (self.__class__.__name__, method_name))
188 def is_ephemeral(self):
189 # An ephemeral node is one whose result is in
190 # a Python temporary and we suspect there are no
191 # other references to it. Certain operations are
192 # disallowed on such values, since they are
193 # likely to result in a dangling pointer.
194 return self.type.is_pyobject and self.is_temp
196 def subexpr_nodes(self):
197 # Extract a list of subexpression nodes based
198 # on the contents of the subexprs class attribute.
199 if self.saved_subexpr_nodes is None:
201 for name in self.subexprs:
202 item = getattr(self, name)
204 if isinstance(item, ExprNode):
208 self.saved_subexpr_nodes = nodes
209 return self.saved_subexpr_nodes
211 def result_as(self, type = None):
212 # Return the result code cast to the specified C type.
213 return typecast(type, self.ctype(), self.result_code)
216 # Return the result code cast to PyObject *.
217 return self.result_as(py_object_type)
220 # Return the native C type of the result (i.e. the
221 # C type of the result_code expression).
222 return self.result_ctype or self.type
224 def compile_time_value(self, denv):
225 # Return value of compile-time expression, or report error.
226 error(self.pos, "Invalid compile-time expression")
228 def compile_time_value_error(self, e):
229 error(self.pos, "Error in compile-time expression: %s: %s" % (
230 e.__class__.__name__, e))
232 # ------------- Declaration Analysis ----------------
234 def analyse_target_declaration(self, env):
235 error(self.pos, "Cannot assign to or delete this")
237 # ------------- Expression Analysis ----------------
239 def analyse_const_expression(self, env):
240 # Called during the analyse_declarations phase of a
241 # constant expression. Analyses the expression's type,
242 # checks whether it is a legal const expression,
243 # and determines its value.
244 self.analyse_types(env)
245 self.allocate_temps(env)
248 def analyse_expressions(self, env):
249 # Convenience routine performing both the Type
250 # Analysis and Temp Allocation phases for a whole
252 self.analyse_types(env)
253 self.allocate_temps(env)
255 def analyse_target_expression(self, env, rhs):
256 # Convenience routine performing both the Type
257 # Analysis and Temp Allocation phases for the LHS of
259 self.analyse_target_types(env)
260 self.allocate_target_temps(env, rhs)
262 def analyse_boolean_expression(self, env):
263 # Analyse expression and coerce to a boolean.
264 self.analyse_types(env)
265 bool = self.coerce_to_boolean(env)
266 bool.allocate_temps(env)
269 def analyse_temp_boolean_expression(self, env):
270 # Analyse boolean expression and coerce result into
271 # a temporary. This is used when a branch is to be
272 # performed on the result and we won't have an
273 # opportunity to ensure disposal code is executed
274 # afterwards. By forcing the result into a temporary,
275 # we ensure that all disposal has been done by the
276 # time we get the result.
277 self.analyse_types(env)
278 bool = self.coerce_to_boolean(env)
279 temp_bool = bool.coerce_to_temp(env)
280 temp_bool.allocate_temps(env)
283 # --------------- Type Analysis ------------------
285 def analyse_as_module(self, env):
286 # If this node can be interpreted as a reference to a
287 # cimported module, return its scope, else None.
290 def analyse_as_extension_type(self, env):
291 # If this node can be interpreted as a reference to an
292 # extension type, return its type, else None.
295 def analyse_types(self, env):
296 self.not_implemented("analyse_types")
298 def analyse_target_types(self, env):
299 self.analyse_types(env)
301 def check_const(self):
305 error(self.pos, "Not allowed in a constant expression")
307 def check_const_addr(self):
308 self.addr_not_const()
310 def addr_not_const(self):
311 error(self.pos, "Address is not constant")
313 # ----------------- Result Allocation -----------------
315 def result_in_temp(self):
316 # Return true if result is in a temporary owned by
317 # this node or one of its subexpressions. Overridden
318 # by certain nodes which can share the result of
322 def allocate_target_temps(self, env, rhs):
323 # Perform temp allocation for the LHS of an assignment.
325 print("%s Allocating target temps" % self)
326 self.allocate_subexpr_temps(env)
327 self.result_code = self.target_code()
329 rhs.release_temp(env)
330 self.release_subexpr_temps(env)
332 def allocate_temps(self, env, result = None):
333 # Allocate temporary variables for this node and
334 # all its sub-expressions. If a result is specified,
335 # this must be a temp node and the specified variable
336 # is used as the result instead of allocating a new
339 print("%s Allocating temps" % self)
340 self.allocate_subexpr_temps(env)
341 self.allocate_temp(env, result)
343 self.release_subexpr_temps(env)
345 def allocate_subexpr_temps(self, env):
346 # Allocate temporary variables for all sub-expressions
349 print("%s Allocating temps for: %s" % (self, self.subexprs))
350 for node in self.subexpr_nodes():
353 print("%s Allocating temps for %s" % (self, node))
354 node.allocate_temps(env)
356 def allocate_temp(self, env, result = None):
357 # If this node requires a temporary variable for its
358 # result, allocate one, otherwise set the result to
359 # a C code fragment. If a result is specified,
360 # this must be a temp node and the specified variable
361 # is used as the result instead of allocating a new
364 print("%s Allocating temp" % self)
367 raise InternalError("Result forced on non-temp node")
368 self.result_code = result
373 type = PyrexTypes.py_object_type
374 self.result_code = env.allocate_temp(type)
376 self.result_code = None
378 print("%s Allocated result %s" % (self, self.result_code))
380 self.result_code = self.calculate_result_code()
382 def target_code(self):
383 # Return code fragment for use as LHS of a C assignment.
384 return self.calculate_result_code()
386 def calculate_result_code(self):
387 self.not_implemented("calculate_result_code")
389 # def release_target_temp(self, env):
390 # # Release temporaries used by LHS of an assignment.
391 # self.release_subexpr_temps(env)
393 def release_temp(self, env):
394 # If this node owns a temporary result, release it,
395 # otherwise release results of its sub-expressions.
398 print("%s Releasing result %s" % (self, self.result_code))
399 env.release_temp(self.result_code)
401 self.release_subexpr_temps(env)
403 def release_subexpr_temps(self, env):
404 # Release the results of all sub-expressions of
406 for node in self.subexpr_nodes():
408 node.release_temp(env)
410 # ---------------- Code Generation -----------------
412 def make_owned_reference(self, code):
413 # If result is a pyobject, make sure we own
415 if self.type.is_pyobject and not self.result_in_temp():
416 code.put_incref(self.result_code, self.ctype())
418 def generate_evaluation_code(self, code):
419 code.mark_pos(self.pos)
420 # Generate code to evaluate this node and
421 # its sub-expressions, and dispose of any
422 # temporary results of its sub-expressions.
423 self.generate_subexpr_evaluation_code(code)
424 self.generate_result_code(code)
426 self.generate_subexpr_disposal_code(code)
428 def generate_subexpr_evaluation_code(self, code):
429 for node in self.subexpr_nodes():
430 node.generate_evaluation_code(code)
432 def generate_result_code(self, code):
433 self.not_implemented("generate_result_code")
435 def generate_disposal_code(self, code):
436 # If necessary, generate code to dispose of
437 # temporary Python reference.
439 if self.type.is_pyobject:
440 code.put_decref_clear(self.result_code, self.ctype())
442 self.generate_subexpr_disposal_code(code)
444 def generate_subexpr_disposal_code(self, code):
445 # Generate code to dispose of temporary results
446 # of all sub-expressions.
447 for node in self.subexpr_nodes():
448 node.generate_disposal_code(code)
450 def generate_post_assignment_code(self, code):
451 # Same as generate_disposal_code except that
452 # assignment will have absorbed a reference to
453 # the result if it is a Python object.
455 if self.type.is_pyobject:
456 code.putln("%s = 0;" % self.result_code)
458 self.generate_subexpr_disposal_code(code)
460 def generate_assignment_code(self, rhs, code):
461 # Stub method for nodes which are not legal as
462 # the LHS of an assignment. An error will have
463 # been reported earlier.
466 def generate_deletion_code(self, code):
467 # Stub method for nodes that are not legal as
468 # the argument of a del statement. An error
469 # will have been reported earlier.
472 # ---------------- Annotation ---------------------
474 def annotate(self, code):
475 for node in self.subexpr_nodes():
478 # ----------------- Coercion ----------------------
480 def coerce_to(self, dst_type, env):
481 # Coerce the result so that it can be assigned to
482 # something of type dst_type. If processing is necessary,
483 # wraps this node in a coercion node and returns that.
484 # Otherwise, returns this node unchanged.
486 # This method is called during the analyse_expressions
487 # phase of the src_node's processing.
490 src_is_py_type = src_type.is_pyobject
491 dst_is_py_type = dst_type.is_pyobject
493 if dst_type.is_pyobject:
494 if not src.type.is_pyobject:
495 src = CoerceToPyTypeNode(src, env)
496 if not src.type.subtype_of(dst_type):
497 if not isinstance(src, NoneNode):
498 src = PyTypeTestNode(src, dst_type, env)
499 elif src.type.is_pyobject:
500 src = CoerceFromPyTypeNode(dst_type, src, env)
501 else: # neither src nor dst are py types
502 # Added the string comparison, since for c types that
503 # is enough, but Cython gets confused when the types are
504 # in different files.
505 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
506 error(self.pos, "Cannot assign type '%s' to '%s'" %
507 (src.type, dst_type))
510 def coerce_to_pyobject(self, env):
511 return self.coerce_to(PyrexTypes.py_object_type, env)
513 def coerce_to_boolean(self, env):
514 # Coerce result to something acceptable as
517 if type.is_pyobject or type.is_ptr or type.is_float:
518 return CoerceToBooleanNode(self, env)
520 if not type.is_int and not type.is_error:
522 "Type '%s' not acceptable as a boolean" % type)
525 def coerce_to_integer(self, env):
526 # If not already some C integer type, coerce to longint.
530 return self.coerce_to(PyrexTypes.c_long_type, env)
532 def coerce_to_temp(self, env):
533 # Ensure that the result is in a temporary.
534 if self.result_in_temp():
537 return CoerceToTempNode(self, env)
539 def coerce_to_simple(self, env):
540 # Ensure that the result is simple (see is_simple).
544 return self.coerce_to_temp(env)
547 # A node is simple if its result is something that can
548 # be referred to without performing any operations, e.g.
549 # a constant, local var, C global var, struct member
550 # reference, or temporary.
551 return self.result_in_temp()
554 class AtomicExprNode(ExprNode):
555 # Abstract base class for expression nodes which have
556 # no sub-expressions.
561 class PyConstNode(AtomicExprNode):
562 # Abstract base class for constant Python values.
569 def analyse_types(self, env):
570 self.type = py_object_type
572 def calculate_result_code(self):
575 def generate_result_code(self, code):
579 class NoneNode(PyConstNode):
580 # The constant value None
584 def compile_time_value(self, denv):
587 class BoolNode(PyConstNode):
588 # The constant value True or False
590 def compile_time_value(self, denv):
593 def calculate_result_code(self):
599 def coerce_to(self, dst_type, env):
601 if dst_type.is_numeric:
602 return IntNode(self.pos, value=int(self.value)).coerce_to(dst_type, env)
604 return PyConstNode.coerce_to(self, dst_type, env)
606 class EllipsisNode(PyConstNode):
607 # '...' in a subscript list.
609 value = "Py_Ellipsis"
611 def compile_time_value(self, denv):
615 class ConstNode(AtomicExprNode):
616 # Abstract base type for literal constant nodes.
618 # value string C code fragment
625 def analyse_types(self, env):
626 pass # Types are held in class variables
628 def check_const(self):
631 def calculate_result_code(self):
632 return str(self.value)
634 def generate_result_code(self, code):
638 class NullNode(ConstNode):
639 type = PyrexTypes.c_null_ptr_type
643 class CharNode(ConstNode):
644 type = PyrexTypes.c_char_type
646 def compile_time_value(self, denv):
647 return ord(self.value)
649 def calculate_result_code(self):
650 return "'%s'" % self.value
653 class IntNode(ConstNode):
654 type = PyrexTypes.c_long_type
656 def coerce_to(self, dst_type, env):
657 # Arrange for a Python version of the string to be pre-allocated
658 # when coercing to a Python type.
659 if dst_type.is_pyobject:
660 self.entry = env.get_py_num(self.value)
661 self.type = PyrexTypes.py_object_type
662 # We still need to perform normal coerce_to processing on the
663 # result, because we might be coercing to an extension type,
664 # in which case a type test node will be needed.
665 return ConstNode.coerce_to(self, dst_type, env)
667 def calculate_result_code(self):
668 if self.type.is_pyobject:
669 return self.entry.cname
671 return str(self.value)
673 def compile_time_value(self, denv):
674 return int(self.value, 0)
677 class FloatNode(ConstNode):
678 type = PyrexTypes.c_double_type
680 def compile_time_value(self, denv):
681 return float(self.value)
683 def calculate_result_code(self):
684 strval = str(self.value)
686 return "(Py_HUGE_VAL * 0)"
687 elif strval == 'inf':
689 elif strval == '-inf':
690 return "(-Py_HUGE_VAL)"
695 class StringNode(ConstNode):
698 type = PyrexTypes.c_char_ptr_type
700 def compile_time_value(self, denv):
703 def analyse_types(self, env):
704 self.entry = env.add_string_const(self.value)
706 def coerce_to(self, dst_type, env):
708 if not self.type.is_pyobject and len(self.entry.init) == 1:
709 # we use the *encoded* value here
710 return CharNode(self.pos, value=self.entry.init)
712 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
714 # Arrange for a Python version of the string to be pre-allocated
715 # when coercing to a Python type.
716 if dst_type.is_pyobject and not self.type.is_pyobject:
717 node = self.as_py_string_node(env)
720 # We still need to perform normal coerce_to processing on the
721 # result, because we might be coercing to an extension type,
722 # in which case a type test node will be needed.
723 return ConstNode.coerce_to(node, dst_type, env)
725 def as_py_string_node(self, env):
726 # Return a new StringNode with the same entry as this node
727 # but whose type is a Python type instead of a C type.
729 env.add_py_string(entry)
730 return StringNode(self.pos, entry = entry, type = py_object_type)
732 def calculate_result_code(self):
733 if self.type.is_pyobject:
734 return self.entry.pystring_cname
736 return self.entry.cname
739 class IdentifierStringNode(ConstNode):
740 # A Python string that behaves like an identifier, e.g. for
741 # keyword arguments in a call, or for imported names
742 type = PyrexTypes.py_object_type
744 def analyse_types(self, env):
745 self.cname = env.intern_identifier(self.value)
747 def calculate_result_code(self):
751 class LongNode(AtomicExprNode):
752 # Python long integer literal
756 def compile_time_value(self, denv):
757 return long(self.value)
759 def analyse_types(self, env):
760 self.type = py_object_type
763 def generate_evaluation_code(self, code):
765 '%s = PyLong_FromString("%s", 0, 0); %s' % (
768 code.error_goto_if_null(self.result_code, self.pos)))
771 class ImagNode(AtomicExprNode):
772 # Imaginary number literal
774 # value float imaginary part
776 def compile_time_value(self, denv):
777 return complex(0.0, self.value)
779 def analyse_types(self, env):
780 self.type = py_object_type
783 def generate_evaluation_code(self, code):
785 "%s = PyComplex_FromDoubles(0.0, %s); %s" % (
788 code.error_goto_if_null(self.result_code, self.pos)))
791 class NameNode(AtomicExprNode):
792 # Reference to a local or global variable name.
794 # name string Python name of the variable
796 # entry Entry Symbol table entry
797 # interned_cname string
801 def compile_time_value(self, denv):
803 return denv.lookup(self.name)
805 error(self.pos, "Compile-time name '%s' not defined" % self.name)
807 def coerce_to(self, dst_type, env):
808 # If coercing to a generic pyobject and this is a builtin
809 # C function with a Python equivalent, manufacture a NameNode
810 # referring to the Python builtin.
811 #print "NameNode.coerce_to:", self.name, dst_type ###
812 if dst_type is py_object_type:
814 if entry and entry.is_cfunction:
815 var_entry = entry.as_variable
817 if var_entry.is_builtin and Options.cache_builtins:
818 var_entry = env.declare_builtin(var_entry.name, self.pos)
819 node = NameNode(self.pos, name = self.name)
820 node.entry = var_entry
821 node.analyse_rvalue_entry(env)
823 return AtomicExprNode.coerce_to(self, dst_type, env)
825 def analyse_as_module(self, env):
826 # Try to interpret this as a reference to a cimported module.
827 # Returns the module scope, or None.
828 entry = env.lookup(self.name)
829 if entry and entry.as_module:
830 return entry.as_module
833 def analyse_as_extension_type(self, env):
834 # Try to interpret this as a reference to an extension type.
835 # Returns the extension type, or None.
836 entry = env.lookup(self.name)
837 if entry and entry.is_type and entry.type.is_extension_type:
842 def analyse_target_declaration(self, env):
843 self.entry = env.lookup_here(self.name)
845 self.entry = env.declare_var(self.name, py_object_type, self.pos)
846 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
847 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
848 if self.entry.is_declared_generic:
849 self.result_ctype = py_object_type
850 if self.entry.is_pyglobal and self.entry.is_member:
851 env.use_utility_code(type_cache_invalidation_code)
853 def analyse_types(self, env):
854 self.entry = env.lookup(self.name)
856 self.entry = env.declare_builtin(self.name, self.pos)
858 self.type = PyrexTypes.error_type
860 self.analyse_rvalue_entry(env)
862 def analyse_target_types(self, env):
863 self.analyse_entry(env)
864 if not self.is_lvalue():
865 error(self.pos, "Assignment to non-lvalue '%s'"
867 self.type = PyrexTypes.error_type
870 def analyse_rvalue_entry(self, env):
871 #print "NameNode.analyse_rvalue_entry:", self.name ###
872 #print "Entry:", self.entry.__dict__ ###
873 self.analyse_entry(env)
875 if entry.is_declared_generic:
876 self.result_ctype = py_object_type
877 if entry.is_pyglobal or entry.is_builtin:
878 if Options.cache_builtins and entry.is_builtin:
882 env.use_utility_code(get_name_interned_utility_code)
884 def analyse_entry(self, env):
885 #print "NameNode.analyse_entry:", self.name ###
886 self.check_identifier_kind()
890 if entry.is_pyglobal or entry.is_builtin:
891 assert type.is_pyobject, "Python global or builtin not a Python object"
892 self.interned_cname = self.entry.interned_cname = \
893 env.intern_identifier(self.entry.name)
895 def check_identifier_kind(self):
896 #print "NameNode.check_identifier_kind:", self.entry.name ###
897 #print self.entry.__dict__ ###
900 if not (entry.is_const or entry.is_variable
901 or entry.is_builtin or entry.is_cfunction):
902 if self.entry.as_variable:
903 self.entry = self.entry.as_variable
906 "'%s' is not a constant, variable or function identifier" % self.name)
909 # If it's not a C variable, it'll be in a temp.
912 def calculate_target_results(self, env):
915 def check_const(self):
917 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
920 def check_const_addr(self):
922 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
923 self.addr_not_const()
926 return self.entry.is_variable and \
927 not self.entry.type.is_array and \
928 not self.entry.is_readonly
930 def is_ephemeral(self):
931 # Name nodes are never ephemeral, even if the
932 # result is in a temporary.
935 def allocate_temp(self, env, result = None):
936 AtomicExprNode.allocate_temp(self, env, result)
940 if entry.utility_code:
941 env.use_utility_code(entry.utility_code)
943 def calculate_result_code(self):
946 return "<error>" # There was an error earlier
949 def generate_result_code(self, code):
950 assert hasattr(self, 'entry')
953 return # There was an error earlier
954 if entry.is_builtin and Options.cache_builtins:
955 return # Lookup already cached
956 elif entry.is_pyglobal or entry.is_builtin:
958 namespace = Naming.builtins_cname
959 else: # entry.is_pyglobal
960 namespace = entry.namespace_cname
962 '%s = __Pyx_GetName(%s, %s); %s' % (
966 code.error_goto_if_null(self.result_code, self.pos)))
967 elif entry.is_local and False:
968 # control flow not good enough yet
969 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
970 if assigned is False:
971 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
972 elif not Options.init_local_none and assigned is None:
973 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
974 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
976 def generate_assignment_code(self, rhs, code):
977 #print "NameNode.generate_assignment_code:", self.name ###
980 return # There was an error earlier
982 # is_pyglobal seems to be True for module level-globals only.
983 # We use this to access class->tp_dict if necessary.
984 if entry.is_pyglobal:
985 namespace = self.entry.namespace_cname
987 # if the entry is a member we have to cheat: SetAttr does not work
988 # on types, so we create a descriptor which is then added to tp_dict
989 code.put_error_if_neg(self.pos,
990 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
994 # in Py2.6+, we need to invalidate the method cache
995 code.putln("__Pyx_TypeModified((PyTypeObject*)%s);" %
996 entry.scope.parent_type.typeptr_cname)
998 code.put_error_if_neg(self.pos,
999 'PyObject_SetAttr(%s, %s, %s)' % (
1001 self.interned_cname,
1003 if debug_disposal_code:
1004 print("NameNode.generate_assignment_code:")
1005 print("...generating disposal code for %s" % rhs)
1006 rhs.generate_disposal_code(code)
1009 if self.type.is_pyobject:
1010 #print "NameNode.generate_assignment_code: to", self.name ###
1011 #print "...from", rhs ###
1012 #print "...LHS type", self.type, "ctype", self.ctype() ###
1013 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1014 rhs.make_owned_reference(code)
1015 if entry.is_local and not Options.init_local_none:
1016 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1017 if initalized is True:
1018 code.put_decref(self.result_code, self.ctype())
1019 elif initalized is None:
1020 code.put_xdecref(self.result_code, self.ctype())
1022 code.put_decref(self.result_code, self.ctype())
1023 code.putln('%s = %s;' % (self.result_code, rhs.result_as(self.ctype())))
1024 if debug_disposal_code:
1025 print("NameNode.generate_assignment_code:")
1026 print("...generating post-assignment code for %s" % rhs)
1027 rhs.generate_post_assignment_code(code)
1029 def generate_deletion_code(self, code):
1030 if self.entry is None:
1031 return # There was an error earlier
1032 if not self.entry.is_pyglobal:
1033 error(self.pos, "Deletion of local or C global name not supported")
1035 code.put_error_if_neg(self.pos,
1036 'PyObject_DelAttrString(%s, "%s")' % (
1037 Naming.module_cname,
1040 def annotate(self, code):
1041 if hasattr(self, 'is_called') and self.is_called:
1042 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1043 if self.type.is_pyobject:
1044 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1046 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1049 class BackquoteNode(ExprNode):
1056 def analyse_types(self, env):
1057 self.arg.analyse_types(env)
1058 self.arg = self.arg.coerce_to_pyobject(env)
1059 self.type = py_object_type
1062 def generate_result_code(self, code):
1064 "%s = PyObject_Repr(%s); %s" % (
1066 self.arg.py_result(),
1067 code.error_goto_if_null(self.result_code, self.pos)))
1070 class ImportNode(ExprNode):
1071 # Used as part of import statement implementation.
1072 # Implements result =
1073 # __import__(module_name, globals(), None, name_list)
1075 # module_name IdentifierStringNode dotted name of module
1076 # name_list ListNode or None list of names to be imported
1078 subexprs = ['module_name', 'name_list']
1080 def analyse_types(self, env):
1081 self.module_name.analyse_types(env)
1082 self.module_name = self.module_name.coerce_to_pyobject(env)
1084 self.name_list.analyse_types(env)
1085 self.type = py_object_type
1087 env.use_utility_code(import_utility_code)
1089 def generate_result_code(self, code):
1091 name_list_code = self.name_list.py_result()
1093 name_list_code = "0"
1095 "%s = __Pyx_Import(%s, %s); %s" % (
1097 self.module_name.py_result(),
1099 code.error_goto_if_null(self.result_code, self.pos)))
1102 class IteratorNode(ExprNode):
1103 # Used as part of for statement implementation.
1104 # Implements result = iter(sequence)
1108 subexprs = ['sequence']
1110 def analyse_types(self, env):
1111 self.sequence.analyse_types(env)
1112 self.sequence = self.sequence.coerce_to_pyobject(env)
1113 self.type = py_object_type
1116 self.counter = TempNode(self.pos, PyrexTypes.c_py_ssize_t_type, env)
1117 self.counter.allocate_temp(env)
1119 def release_temp(self, env):
1120 env.release_temp(self.result_code)
1121 self.counter.release_temp(env)
1123 def generate_result_code(self, code):
1125 "if (PyList_CheckExact(%s)) { %s = 0; %s = %s; Py_INCREF(%s); }" % (
1126 self.sequence.py_result(),
1127 self.counter.result_code,
1129 self.sequence.py_result(),
1131 code.putln("else { %s = PyObject_GetIter(%s); %s }" % (
1133 self.sequence.py_result(),
1134 code.error_goto_if_null(self.result_code, self.pos)))
1137 class NextNode(AtomicExprNode):
1138 # Used as part of for statement implementation.
1139 # Implements result = iterator.next()
1140 # Created during analyse_types phase.
1141 # The iterator is not owned by this node.
1145 def __init__(self, iterator, env):
1146 self.pos = iterator.pos
1147 self.iterator = iterator
1148 self.type = py_object_type
1151 def generate_result_code(self, code):
1153 "if (PyList_CheckExact(%s)) { if (%s >= PyList_GET_SIZE(%s)) break; %s = PyList_GET_ITEM(%s, %s++); Py_INCREF(%s); }" % (
1154 self.iterator.py_result(),
1155 self.iterator.counter.result_code,
1156 self.iterator.py_result(),
1158 self.iterator.py_result(),
1159 self.iterator.counter.result_code,
1161 code.putln("else {")
1163 "%s = PyIter_Next(%s);" % (
1165 self.iterator.py_result()))
1169 code.error_goto_if_PyErr(self.pos)
1170 code.putln("break;")
1175 class ExcValueNode(AtomicExprNode):
1176 # Node created during analyse_types phase
1177 # of an ExceptClauseNode to fetch the current
1180 def __init__(self, pos, env, var):
1181 ExprNode.__init__(self, pos)
1182 self.type = py_object_type
1185 def calculate_result_code(self):
1188 def generate_result_code(self, code):
1192 class TempNode(AtomicExprNode):
1193 # Node created during analyse_types phase
1194 # of some nodes to hold a temporary value.
1196 def __init__(self, pos, type, env):
1197 ExprNode.__init__(self, pos)
1199 if type.is_pyobject:
1200 self.result_ctype = py_object_type
1203 def analyse_types(self, env):
1206 def generate_result_code(self, code):
1210 class PyTempNode(TempNode):
1211 # TempNode holding a Python value.
1213 def __init__(self, pos, env):
1214 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1217 #-------------------------------------------------------------------
1221 #-------------------------------------------------------------------
1223 class IndexNode(ExprNode):
1224 # Sequence indexing.
1229 subexprs = ['base', 'index', 'py_index']
1231 def compile_time_value(self, denv):
1232 base = self.base.compile_time_value(denv)
1233 index = self.index.compile_time_value(denv)
1236 except Exception, e:
1237 self.compile_time_value_error(e)
1239 def is_ephemeral(self):
1240 return self.base.is_ephemeral()
1242 def analyse_target_declaration(self, env):
1245 def analyse_types(self, env):
1246 self.base.analyse_types(env)
1247 self.index.analyse_types(env)
1248 if self.base.type.is_pyobject:
1249 if self.index.type.is_int:
1250 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1251 self.py_index = CloneNode(self.index).coerce_to_pyobject(env)
1253 self.index = self.index.coerce_to_pyobject(env)
1254 self.py_index = CloneNode(self.index)
1255 self.type = py_object_type
1258 self.py_index = CloneNode(self.index) # so that it exists for subexpr processing
1259 if self.base.type.is_ptr or self.base.type.is_array:
1260 self.type = self.base.type.base_type
1263 "Attempting to index non-array type '%s'" %
1265 self.type = PyrexTypes.error_type
1266 if self.index.type.is_pyobject:
1267 self.index = self.index.coerce_to(
1268 PyrexTypes.c_py_ssize_t_type, env)
1269 if not self.index.type.is_int:
1271 "Invalid index type '%s'" %
1274 def check_const_addr(self):
1275 self.base.check_const_addr()
1276 self.index.check_const()
1278 def is_lvalue(self):
1281 def calculate_result_code(self):
1282 return "(%s[%s])" % (
1283 self.base.result_code, self.index.result_code)
1285 def generate_subexpr_evaluation_code(self, code):
1286 # do not evaluate self.py_index in case we don't need it
1287 self.base.generate_evaluation_code(code)
1288 self.index.generate_evaluation_code(code)
1290 def generate_subexpr_disposal_code(self, code):
1291 # if we used self.py_index, it will be disposed of manually
1292 self.base.generate_disposal_code(code)
1293 self.index.generate_disposal_code(code)
1295 def generate_result_code(self, code):
1296 if self.type.is_pyobject:
1297 if self.index.type.is_int:
1298 code.putln("if (PyList_CheckExact(%s) && 0 <= %s && %s < PyList_GET_SIZE(%s)) {" % (
1299 self.base.py_result(),
1300 self.index.result_code,
1301 self.index.result_code,
1302 self.base.py_result()))
1303 code.putln("%s = PyList_GET_ITEM(%s, %s); Py_INCREF(%s);" % (
1305 self.base.py_result(),
1306 self.index.result_code,
1308 code.putln("} else if (PyTuple_CheckExact(%s) && 0 <= %s && %s < PyTuple_GET_SIZE(%s)) {" % (
1309 self.base.py_result(),
1310 self.index.result_code,
1311 self.index.result_code,
1312 self.base.py_result()))
1313 code.putln("%s = PyTuple_GET_ITEM(%s, %s); Py_INCREF(%s);" % (
1315 self.base.py_result(),
1316 self.index.result_code,
1318 code.putln("} else {")
1319 self.generate_generic_code_result(code)
1322 self.generate_generic_code_result(code)
1324 def generate_generic_code_result(self, code):
1325 self.py_index.generate_result_code(code)
1327 "%s = PyObject_GetItem(%s, %s); %s" % (
1329 self.base.py_result(),
1330 self.py_index.py_result(),
1331 code.error_goto_if_null(self.result_code, self.pos)))
1333 self.py_index.generate_disposal_code(code)
1335 def generate_assignment_code(self, rhs, code):
1336 self.generate_subexpr_evaluation_code(code)
1337 if self.type.is_pyobject:
1338 if self.index.type.is_int:
1339 code.putln("if (PyList_CheckExact(%s) && 0 <= %s && %s < PyList_GET_SIZE(%s)) {" % (
1340 self.base.py_result(),
1341 self.index.result_code,
1342 self.index.result_code,
1343 self.base.py_result()))
1344 code.putln("Py_DECREF(PyList_GET_ITEM(%s, %s)); Py_INCREF(%s);" % (
1345 self.base.py_result(),
1346 self.index.result_code,
1348 code.putln("PyList_SET_ITEM(%s, %s, %s);" % (
1349 self.base.py_result(),
1350 self.index.result_code,
1352 code.putln("} else {")
1353 self.generate_generic_assignment_code(rhs, code)
1356 self.generate_generic_assignment_code(rhs, code)
1360 self.result_code, rhs.result_code))
1361 self.generate_subexpr_disposal_code(code)
1362 rhs.generate_disposal_code(code)
1364 def generate_generic_assignment_code(self, rhs, code):
1365 self.py_index.generate_result_code(code)
1366 code.put_error_if_neg(self.pos,
1367 "PyObject_SetItem(%s, %s, %s)" % (
1368 self.base.py_result(),
1369 self.py_index.py_result(),
1372 self.py_index.generate_disposal_code(code)
1374 def generate_deletion_code(self, code):
1375 self.generate_subexpr_evaluation_code(code)
1376 self.py_index.generate_evaluation_code(code)
1377 code.put_error_if_neg(self.pos,
1378 "PyObject_DelItem(%s, %s)" % (
1379 self.base.py_result(),
1380 self.py_index.py_result()))
1381 self.generate_subexpr_disposal_code(code)
1382 self.py_index.generate_disposal_code(code)
1385 class SliceIndexNode(ExprNode):
1386 # 2-element slice indexing
1389 # start ExprNode or None
1390 # stop ExprNode or None
1392 subexprs = ['base', 'start', 'stop']
1394 def compile_time_value(self, denv):
1395 base = self.base.compile_time_value(denv)
1396 start = self.start.compile_time_value(denv)
1397 stop = self.stop.compile_time_value(denv)
1399 return base[start:stop]
1400 except Exception, e:
1401 self.compile_time_value_error(e)
1403 def analyse_target_declaration(self, env):
1406 def analyse_types(self, env):
1407 self.base.analyse_types(env)
1409 self.start.analyse_types(env)
1411 self.stop.analyse_types(env)
1412 self.base = self.base.coerce_to_pyobject(env)
1413 c_int = PyrexTypes.c_py_ssize_t_type
1415 self.start = self.start.coerce_to(c_int, env)
1417 self.stop = self.stop.coerce_to(c_int, env)
1418 self.type = py_object_type
1421 def generate_result_code(self, code):
1423 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1425 self.base.py_result(),
1428 code.error_goto_if_null(self.result_code, self.pos)))
1430 def generate_assignment_code(self, rhs, code):
1431 self.generate_subexpr_evaluation_code(code)
1432 code.put_error_if_neg(self.pos,
1433 "PySequence_SetSlice(%s, %s, %s, %s)" % (
1434 self.base.py_result(),
1438 self.generate_subexpr_disposal_code(code)
1439 rhs.generate_disposal_code(code)
1441 def generate_deletion_code(self, code):
1442 self.generate_subexpr_evaluation_code(code)
1443 code.put_error_if_neg(self.pos,
1444 "PySequence_DelSlice(%s, %s, %s)" % (
1445 self.base.py_result(),
1448 self.generate_subexpr_disposal_code(code)
1450 def start_code(self):
1452 return self.start.result_code
1456 def stop_code(self):
1458 return self.stop.result_code
1460 return "PY_SSIZE_T_MAX"
1462 def calculate_result_code(self):
1463 # self.result_code is not used, but this method must exist
1467 class SliceNode(ExprNode):
1468 # start:stop:step in subscript list
1474 def compile_time_value(self, denv):
1475 start = self.start.compile_time_value(denv)
1476 stop = self.stop.compile_time_value(denv)
1477 step = step.step.compile_time_value(denv)
1479 return slice(start, stop, step)
1480 except Exception, e:
1481 self.compile_time_value_error(e)
1483 subexprs = ['start', 'stop', 'step']
1485 def analyse_types(self, env):
1486 self.start.analyse_types(env)
1487 self.stop.analyse_types(env)
1488 self.step.analyse_types(env)
1489 self.start = self.start.coerce_to_pyobject(env)
1490 self.stop = self.stop.coerce_to_pyobject(env)
1491 self.step = self.step.coerce_to_pyobject(env)
1492 self.type = py_object_type
1495 def generate_result_code(self, code):
1497 "%s = PySlice_New(%s, %s, %s); %s" % (
1499 self.start.py_result(),
1500 self.stop.py_result(),
1501 self.step.py_result(),
1502 code.error_goto_if_null(self.result_code, self.pos)))
1504 class SimpleCallNode(ExprNode):
1505 # Function call without keyword, * or ** args.
1509 # arg_tuple ExprNode or None used internally
1510 # self ExprNode or None used internally
1511 # coerced_self ExprNode or None used internally
1512 # wrapper_call bool used internally
1514 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
1519 wrapper_call = False
1521 def compile_time_value(self, denv):
1522 function = self.function.compile_time_value(denv)
1523 args = [arg.compile_time_value(denv) for arg in self.args]
1525 return function(*args)
1526 except Exception, e:
1527 self.compile_time_value_error(e)
1529 def analyse_types(self, env):
1530 function = self.function
1531 function.is_called = 1
1532 self.function.analyse_types(env)
1533 if function.is_attribute and function.is_py_attr and \
1534 function.attribute == "append" and len(self.args) == 1:
1535 # L.append(x) is almost always applied to a list
1536 self.py_func = self.function
1537 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
1538 self.function.analyse_types(env)
1539 self.self = self.py_func.obj
1540 function.obj = CloneNode(self.self)
1541 env.use_utility_code(append_utility_code)
1542 if function.is_attribute and function.entry and function.entry.is_cmethod:
1543 # Take ownership of the object from which the attribute
1544 # was obtained, because we need to pass it as 'self'.
1545 self.self = function.obj
1546 function.obj = CloneNode(self.self)
1547 func_type = self.function_type()
1548 if func_type.is_pyobject:
1549 self.arg_tuple = TupleNode(self.pos, args = self.args)
1550 self.arg_tuple.analyse_types(env)
1552 self.type = py_object_type
1555 for arg in self.args:
1556 arg.analyse_types(env)
1557 if self.self and func_type.args:
1558 # Coerce 'self' to the type expected by the method.
1559 expected_type = func_type.args[0].type
1560 self.coerced_self = CloneNode(self.self).coerce_to(
1562 # Insert coerced 'self' argument into argument list.
1563 self.args.insert(0, self.coerced_self)
1564 self.analyse_c_function_call(env)
1566 def function_type(self):
1567 # Return the type of the function being called, coercing a function
1568 # pointer to a function if necessary.
1569 func_type = self.function.type
1570 if func_type.is_ptr:
1571 func_type = func_type.base_type
1574 def analyse_c_function_call(self, env):
1575 func_type = self.function_type()
1576 # Check function type
1577 if not func_type.is_cfunction:
1578 if not func_type.is_error:
1579 error(self.pos, "Calling non-function type '%s'" %
1581 self.type = PyrexTypes.error_type
1582 self.result_code = "<error>"
1585 max_nargs = len(func_type.args)
1586 expected_nargs = max_nargs - func_type.optional_arg_count
1587 actual_nargs = len(self.args)
1588 if actual_nargs < expected_nargs \
1589 or (not func_type.has_varargs and actual_nargs > max_nargs):
1590 expected_str = str(expected_nargs)
1591 if func_type.has_varargs:
1592 expected_str = "at least " + expected_str
1593 elif func_type.optional_arg_count:
1594 if actual_nargs < max_nargs:
1595 expected_str = "at least " + expected_str
1597 expected_str = "at most " + str(max_nargs)
1599 "Call with wrong number of arguments (expected %s, got %s)"
1600 % (expected_str, actual_nargs))
1602 self.type = PyrexTypes.error_type
1603 self.result_code = "<error>"
1606 for i in range(min(max_nargs, actual_nargs)):
1607 formal_type = func_type.args[i].type
1608 self.args[i] = self.args[i].coerce_to(formal_type, env)
1609 for i in range(max_nargs, actual_nargs):
1610 if self.args[i].type.is_pyobject:
1611 error(self.args[i].pos,
1612 "Python object cannot be passed as a varargs parameter")
1613 # Calc result type and code fragment
1614 self.type = func_type.return_type
1615 if self.type.is_pyobject \
1616 or func_type.exception_value is not None \
1617 or func_type.exception_check:
1619 if self.type.is_pyobject:
1620 self.result_ctype = py_object_type
1621 # C++ exception handler
1622 if func_type.exception_check == '+':
1623 if func_type.exception_value is None:
1624 env.use_utility_code(cpp_exception_utility_code)
1626 def calculate_result_code(self):
1627 return self.c_call_code()
1629 def c_call_code(self):
1630 func_type = self.function_type()
1631 if self.args is None or not func_type.is_cfunction:
1633 formal_args = func_type.args
1635 args = zip(formal_args, self.args)
1636 max_nargs = len(func_type.args)
1637 expected_nargs = max_nargs - func_type.optional_arg_count
1638 actual_nargs = len(self.args)
1639 for formal_arg, actual_arg in args[:expected_nargs]:
1640 arg_code = actual_arg.result_as(formal_arg.type)
1641 arg_list_code.append(arg_code)
1643 if func_type.optional_arg_count:
1644 if expected_nargs == actual_nargs:
1645 optional_args = 'NULL'
1647 optional_arg_code = [str(actual_nargs - expected_nargs)]
1648 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
1649 arg_code = actual_arg.result_as(formal_arg.type)
1650 optional_arg_code.append(arg_code)
1651 # for formal_arg in formal_args[actual_nargs:max_nargs]:
1652 # optional_arg_code.append(formal_arg.type.cast_code('0'))
1653 optional_arg_struct = '{%s}' % ','.join(optional_arg_code)
1654 optional_args = PyrexTypes.c_void_ptr_type.cast_code(
1655 '&' + func_type.op_arg_struct.base_type.cast_code(optional_arg_struct))
1656 arg_list_code.append(optional_args)
1658 for actual_arg in self.args[len(formal_args):]:
1659 arg_list_code.append(actual_arg.result_code)
1660 result = "%s(%s)" % (self.function.result_code,
1661 join(arg_list_code, ", "))
1662 if self.wrapper_call or \
1663 self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
1664 result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
1667 def generate_result_code(self, code):
1668 func_type = self.function_type()
1669 if func_type.is_pyobject:
1670 arg_code = self.arg_tuple.py_result()
1672 "%s = PyObject_Call(%s, %s, NULL); %s" % (
1674 self.function.py_result(),
1676 code.error_goto_if_null(self.result_code, self.pos)))
1677 elif func_type.is_cfunction:
1679 if self.type.is_pyobject:
1680 exc_checks.append("!%s" % self.result_code)
1682 exc_val = func_type.exception_value
1683 exc_check = func_type.exception_check
1684 if exc_val is not None:
1685 exc_checks.append("%s == %s" % (self.result_code, exc_val))
1687 exc_checks.append("PyErr_Occurred()")
1688 if self.is_temp or exc_checks:
1689 rhs = self.c_call_code()
1690 if self.result_code:
1691 lhs = "%s = " % self.result_code
1692 if self.is_temp and self.type.is_pyobject:
1693 #return_type = self.type # func_type.return_type
1694 #print "SimpleCallNode.generate_result_code: casting", rhs, \
1695 # "from", return_type, "to pyobject" ###
1696 rhs = typecast(py_object_type, self.type, rhs)
1699 if func_type.exception_check == '+':
1700 if func_type.exception_value is None:
1701 raise_py_exception = "__Pyx_CppExn2PyErr()"
1702 elif func_type.exception_value.type.is_pyobject:
1703 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
1705 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
1707 "try {%s%s;} catch(...) {%s; %s}" % (
1711 code.error_goto(self.pos)))
1717 code.error_goto_if(" && ".join(exc_checks), self.pos)))
1719 class GeneralCallNode(ExprNode):
1720 # General Python function call, including keyword,
1721 # * and ** arguments.
1724 # positional_args ExprNode Tuple of positional arguments
1725 # keyword_args ExprNode or None Dict of keyword arguments
1726 # starstar_arg ExprNode or None Dict of extra keyword args
1728 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
1730 def compile_time_value(self, denv):
1731 function = self.function.compile_time_value(denv)
1732 positional_args = self.positional_args.compile_time_value(denv)
1733 keyword_args = self.keyword_args.compile_time_value(denv)
1734 starstar_arg = self.starstar_arg.compile_time_value(denv)
1736 keyword_args.update(starstar_arg)
1737 return function(*positional_args, **keyword_args)
1738 except Exception, e:
1739 self.compile_time_value_error(e)
1741 def analyse_types(self, env):
1742 self.function.analyse_types(env)
1743 self.positional_args.analyse_types(env)
1744 if self.keyword_args:
1745 self.keyword_args.analyse_types(env)
1746 if self.starstar_arg:
1747 self.starstar_arg.analyse_types(env)
1748 self.function = self.function.coerce_to_pyobject(env)
1749 self.positional_args = \
1750 self.positional_args.coerce_to_pyobject(env)
1751 if self.starstar_arg:
1752 self.starstar_arg = \
1753 self.starstar_arg.coerce_to_pyobject(env)
1754 self.type = py_object_type
1757 def generate_result_code(self, code):
1758 if self.keyword_args and self.starstar_arg:
1759 code.put_error_if_neg(self.pos,
1760 "PyDict_Update(%s, %s)" % (
1761 self.keyword_args.py_result(),
1762 self.starstar_arg.py_result()))
1763 keyword_code = self.keyword_args.py_result()
1764 elif self.keyword_args:
1765 keyword_code = self.keyword_args.py_result()
1766 elif self.starstar_arg:
1767 keyword_code = self.starstar_arg.py_result()
1770 if not keyword_code:
1771 call_code = "PyObject_Call(%s, %s, NULL)" % (
1772 self.function.py_result(),
1773 self.positional_args.py_result())
1775 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
1776 self.function.py_result(),
1777 self.positional_args.py_result(),
1783 code.error_goto_if_null(self.result_code, self.pos)))
1786 class AsTupleNode(ExprNode):
1787 # Convert argument to tuple. Used for normalising
1788 # the * argument of a function call.
1794 def compile_time_value(self, denv):
1795 arg = self.arg.compile_time_value(denv)
1798 except Exception, e:
1799 self.compile_time_value_error(e)
1801 def analyse_types(self, env):
1802 self.arg.analyse_types(env)
1803 self.arg = self.arg.coerce_to_pyobject(env)
1804 self.type = py_object_type
1807 def generate_result_code(self, code):
1809 "%s = PySequence_Tuple(%s); %s" % (
1811 self.arg.py_result(),
1812 code.error_goto_if_null(self.result_code, self.pos)))
1815 class AttributeNode(ExprNode):
1823 # is_py_attr boolean Is a Python getattr operation
1824 # member string C name of struct member
1825 # is_called boolean Function call is being done on result
1826 # entry Entry Symbol table entry of attribute
1827 # interned_attr_cname string C name of interned attribute name
1832 type = PyrexTypes.error_type
1837 def coerce_to(self, dst_type, env):
1838 # If coercing to a generic pyobject and this is a cpdef function
1839 # we can create the corresponding attribute
1840 if dst_type is py_object_type:
1842 if entry and entry.is_cfunction and entry.as_variable:
1843 # must be a cpdef function
1845 self.entry = entry.as_variable
1846 self.analyse_as_python_attribute(env)
1848 return ExprNode.coerce_to(self, dst_type, env)
1850 def compile_time_value(self, denv):
1851 attr = self.attribute
1852 if attr.beginswith("__") and attr.endswith("__"):
1853 self.error("Invalid attribute name '%s' in compile-time expression"
1856 obj = self.arg.compile_time_value(denv)
1858 return getattr(obj, attr)
1859 except Exception, e:
1860 self.compile_time_value_error(e)
1862 def analyse_target_declaration(self, env):
1865 def analyse_target_types(self, env):
1866 self.analyse_types(env, target = 1)
1868 def analyse_types(self, env, target = 0):
1869 if self.analyse_as_cimported_attribute(env, target):
1871 if not target and self.analyse_as_unbound_cmethod(env):
1873 self.analyse_as_ordinary_attribute(env, target)
1875 def analyse_as_cimported_attribute(self, env, target):
1876 # Try to interpret this as a reference to an imported
1877 # C const, type, var or function. If successful, mutates
1878 # this node into a NameNode and returns 1, otherwise
1880 module_scope = self.obj.analyse_as_module(env)
1882 entry = module_scope.lookup_here(self.attribute)
1884 entry.is_cglobal or entry.is_cfunction
1885 or entry.is_type or entry.is_const):
1886 self.mutate_into_name_node(env, entry, target)
1890 def analyse_as_unbound_cmethod(self, env):
1891 # Try to interpret this as a reference to an unbound
1892 # C method of an extension type. If successful, mutates
1893 # this node into a NameNode and returns 1, otherwise
1895 type = self.obj.analyse_as_extension_type(env)
1897 entry = type.scope.lookup_here(self.attribute)
1898 if entry and entry.is_cmethod:
1899 # Create a temporary entry describing the C method
1900 # as an ordinary function.
1901 ubcm_entry = Symtab.Entry(entry.name,
1902 "%s->%s" % (type.vtabptr_cname, entry.cname),
1904 ubcm_entry.is_cfunction = 1
1905 ubcm_entry.func_cname = entry.func_cname
1906 ubcm_entry.is_unbound_cmethod = 1
1907 self.mutate_into_name_node(env, ubcm_entry, None)
1911 def analyse_as_extension_type(self, env):
1912 # Try to interpret this as a reference to an extension type
1913 # in a cimported module. Returns the extension type, or None.
1914 module_scope = self.obj.analyse_as_module(env)
1916 entry = module_scope.lookup_here(self.attribute)
1917 if entry and entry.is_type and entry.type.is_extension_type:
1921 def analyse_as_module(self, env):
1922 # Try to interpret this as a reference to a cimported module
1923 # in another cimported module. Returns the module scope, or None.
1924 module_scope = self.obj.analyse_as_module(env)
1926 entry = module_scope.lookup_here(self.attribute)
1927 if entry and entry.as_module:
1928 return entry.as_module
1931 def mutate_into_name_node(self, env, entry, target):
1932 # Mutate this node into a NameNode and complete the
1933 # analyse_types phase.
1934 self.__class__ = NameNode
1935 self.name = self.attribute
1940 NameNode.analyse_target_types(self, env)
1942 NameNode.analyse_rvalue_entry(self, env)
1944 def analyse_as_ordinary_attribute(self, env, target):
1945 self.obj.analyse_types(env)
1946 self.analyse_attribute(env)
1947 if self.entry and self.entry.is_cmethod and not self.is_called:
1948 # error(self.pos, "C method can only be called")
1950 ## Reference to C array turns into pointer to first element.
1951 #while self.type.is_array:
1952 # self.type = self.type.element_ptr_type()
1956 self.result_ctype = py_object_type
1958 def analyse_attribute(self, env):
1959 # Look up attribute and set self.type and self.member.
1961 self.member = self.attribute
1962 if self.obj.type.is_string:
1963 self.obj = self.obj.coerce_to_pyobject(env)
1964 obj_type = self.obj.type
1965 if obj_type.is_ptr or obj_type.is_array:
1966 obj_type = obj_type.base_type
1968 elif obj_type.is_extension_type:
1972 if obj_type.has_attributes:
1974 if obj_type.attributes_known():
1975 entry = obj_type.scope.lookup_here(self.attribute)
1976 if entry and entry.is_member:
1980 "Cannot select attribute of incomplete type '%s'"
1982 obj_type = PyrexTypes.error_type
1985 if obj_type.is_extension_type and entry.name == "__weakref__":
1986 error(self.pos, "Illegal use of special attribute __weakref__")
1987 # methods need the normal attribute lookup
1988 # because they do not have struct entries
1989 if entry.is_variable or entry.is_cmethod:
1990 self.type = entry.type
1991 self.member = entry.cname
1994 # If it's not a variable or C method, it must be a Python
1995 # method of an extension type, so we treat it like a Python
1998 # If we get here, the base object is not a struct/union/extension
1999 # type, or it is an extension type and the attribute is either not
2000 # declared or is declared as a Python method. Treat it as a Python
2001 # attribute reference.
2002 self.analyse_as_python_attribute(env)
2004 def analyse_as_python_attribute(self, env):
2005 obj_type = self.obj.type
2006 self.member = self.attribute
2007 if obj_type.is_pyobject:
2008 self.type = py_object_type
2010 self.interned_attr_cname = env.intern_identifier(self.attribute)
2012 if not obj_type.is_error:
2014 "Object of type '%s' has no attribute '%s'" %
2015 (obj_type, self.attribute))
2017 def is_simple(self):
2019 return self.result_in_temp() or self.obj.is_simple()
2021 return NameNode.is_simple(self)
2023 def is_lvalue(self):
2027 return NameNode.is_lvalue(self)
2029 def is_ephemeral(self):
2031 return self.obj.is_ephemeral()
2033 return NameNode.is_ephemeral(self)
2035 def calculate_result_code(self):
2036 #print "AttributeNode.calculate_result_code:", self.member ###
2037 #print "...obj node =", self.obj, "code", self.obj.result_code ###
2038 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2040 obj_code = obj.result_as(obj.type)
2041 #print "...obj_code =", obj_code ###
2042 if self.entry and self.entry.is_cmethod:
2043 if obj.type.is_extension_type:
2044 return "((struct %s *)%s%s%s)->%s" % (
2045 obj.type.vtabstruct_cname, obj_code, self.op,
2046 obj.type.vtabslot_cname, self.member)
2050 return "%s%s%s" % (obj_code, self.op, self.member)
2052 def generate_result_code(self, code):
2055 '%s = PyObject_GetAttr(%s, %s); %s' % (
2057 self.obj.py_result(),
2058 self.interned_attr_cname,
2059 code.error_goto_if_null(self.result_code, self.pos)))
2061 def generate_assignment_code(self, rhs, code):
2062 self.obj.generate_evaluation_code(code)
2064 code.put_error_if_neg(self.pos,
2065 'PyObject_SetAttr(%s, %s, %s)' % (
2066 self.obj.py_result(),
2067 self.interned_attr_cname,
2069 rhs.generate_disposal_code(code)
2071 select_code = self.result_code
2072 if self.type.is_pyobject:
2073 rhs.make_owned_reference(code)
2074 code.put_decref(select_code, self.ctype())
2078 rhs.result_as(self.ctype())))
2080 rhs.generate_post_assignment_code(code)
2081 self.obj.generate_disposal_code(code)
2083 def generate_deletion_code(self, code):
2084 self.obj.generate_evaluation_code(code)
2086 code.put_error_if_neg(self.pos,
2087 'PyObject_DelAttr(%s, %s)' % (
2088 self.obj.py_result(),
2089 self.interned_attr_cname))
2091 error(self.pos, "Cannot delete C attribute of extension type")
2092 self.obj.generate_disposal_code(code)
2094 def annotate(self, code):
2096 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2098 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2100 #-------------------------------------------------------------------
2104 #-------------------------------------------------------------------
2106 class SequenceNode(ExprNode):
2107 # Base class for list and tuple constructor nodes.
2108 # Contains common code for performing sequence unpacking.
2112 # unpacked_items [ExprNode] or None
2113 # coerced_unpacked_items [ExprNode] or None
2117 is_sequence_constructor = 1
2118 unpacked_items = None
2120 def compile_time_value_list(self, denv):
2121 return [arg.compile_time_value(denv) for arg in self.args]
2123 def analyse_target_declaration(self, env):
2124 for arg in self.args:
2125 arg.analyse_target_declaration(env)
2127 def analyse_types(self, env):
2128 for i in range(len(self.args)):
2130 arg.analyse_types(env)
2131 self.args[i] = arg.coerce_to_pyobject(env)
2132 self.type = py_object_type
2135 def analyse_target_types(self, env):
2136 self.iterator = PyTempNode(self.pos, env)
2137 self.unpacked_items = []
2138 self.coerced_unpacked_items = []
2139 for arg in self.args:
2140 arg.analyse_target_types(env)
2141 unpacked_item = PyTempNode(self.pos, env)
2142 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2143 self.unpacked_items.append(unpacked_item)
2144 self.coerced_unpacked_items.append(coerced_unpacked_item)
2145 self.type = py_object_type
2146 env.use_utility_code(unpacking_utility_code)
2148 def allocate_target_temps(self, env, rhs):
2149 self.iterator.allocate_temps(env)
2150 for arg, node in zip(self.args, self.coerced_unpacked_items):
2151 node.allocate_temps(env)
2152 arg.allocate_target_temps(env, node)
2153 #arg.release_target_temp(env)
2154 #node.release_temp(env)
2156 rhs.release_temp(env)
2157 self.iterator.release_temp(env)
2159 # def release_target_temp(self, env):
2160 # #for arg in self.args:
2161 # # arg.release_target_temp(env)
2162 # #for node in self.coerced_unpacked_items:
2163 # # node.release_temp(env)
2164 # self.iterator.release_temp(env)
2166 def generate_result_code(self, code):
2167 self.generate_operation_code(code)
2169 def generate_assignment_code(self, rhs, code):
2171 "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
2175 code.putln("PyObject* tuple = %s;" % rhs.py_result())
2176 for i in range(len(self.args)):
2177 item = self.unpacked_items[i]
2179 "%s = PyTuple_GET_ITEM(tuple, %s);" % (
2182 code.put_incref(item.result_code, item.ctype())
2183 value_node = self.coerced_unpacked_items[i]
2184 value_node.generate_evaluation_code(code)
2185 self.args[i].generate_assignment_code(value_node, code)
2187 rhs.generate_disposal_code(code)
2189 code.putln("else {")
2192 "%s = PyObject_GetIter(%s); %s" % (
2193 self.iterator.result_code,
2195 code.error_goto_if_null(self.iterator.result_code, self.pos)))
2196 rhs.generate_disposal_code(code)
2197 for i in range(len(self.args)):
2198 item = self.unpacked_items[i]
2199 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
2200 self.iterator.py_result(), i)
2204 typecast(item.ctype(), py_object_type, unpack_code),
2205 code.error_goto_if_null(item.result_code, self.pos)))
2206 value_node = self.coerced_unpacked_items[i]
2207 value_node.generate_evaluation_code(code)
2208 self.args[i].generate_assignment_code(value_node, code)
2209 code.put_error_if_neg(self.pos,
2210 "__Pyx_EndUnpack(%s)" % (
2211 self.iterator.py_result()))
2212 if debug_disposal_code:
2213 print("UnpackNode.generate_assignment_code:")
2214 print("...generating disposal code for %s" % self.iterator)
2215 self.iterator.generate_disposal_code(code)
2219 def annotate(self, code):
2220 for arg in self.args:
2222 if self.unpacked_items:
2223 for arg in self.unpacked_items:
2225 for arg in self.coerced_unpacked_items:
2229 class TupleNode(SequenceNode):
2230 # Tuple constructor.
2232 def analyse_types(self, env):
2233 if len(self.args) == 0:
2237 SequenceNode.analyse_types(self, env)
2238 self.type = tuple_type
2240 def calculate_result_code(self):
2241 if len(self.args) > 0:
2242 error(self.pos, "Positive length tuples must be constructed.")
2244 return Naming.empty_tuple
2246 def compile_time_value(self, denv):
2247 values = self.compile_time_value_list(denv)
2249 return tuple(values)
2250 except Exception, e:
2251 self.compile_time_value_error(e)
2253 def generate_operation_code(self, code):
2254 if len(self.args) == 0:
2255 # result_code is Naming.empty_tuple
2258 "%s = PyTuple_New(%s); %s" % (
2261 code.error_goto_if_null(self.result_code, self.pos)))
2262 for i in range(len(self.args)):
2264 if not arg.result_in_temp():
2265 code.put_incref(arg.result_code, arg.ctype())
2267 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2272 def generate_subexpr_disposal_code(self, code):
2273 # We call generate_post_assignment_code here instead
2274 # of generate_disposal_code, because values were stored
2275 # in the tuple using a reference-stealing operation.
2276 for arg in self.args:
2277 arg.generate_post_assignment_code(code)
2280 class ListNode(SequenceNode):
2283 def analyse_types(self, env):
2284 SequenceNode.analyse_types(self, env)
2285 self.type = list_type
2287 def compile_time_value(self, denv):
2288 return self.compile_time_value_list(denv)
2290 def generate_operation_code(self, code):
2291 code.putln("%s = PyList_New(%s); %s" %
2294 code.error_goto_if_null(self.result_code, self.pos)))
2295 for i in range(len(self.args)):
2297 #if not arg.is_temp:
2298 if not arg.result_in_temp():
2299 code.put_incref(arg.result_code, arg.ctype())
2300 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
2305 def generate_subexpr_disposal_code(self, code):
2306 # We call generate_post_assignment_code here instead
2307 # of generate_disposal_code, because values were stored
2308 # in the list using a reference-stealing operation.
2309 for arg in self.args:
2310 arg.generate_post_assignment_code(code)
2313 class ListComprehensionNode(SequenceNode):
2316 is_sequence_constructor = 0 # not unpackable
2318 def analyse_types(self, env):
2319 self.type = list_type
2321 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
2323 def allocate_temps(self, env, result = None):
2324 if debug_temp_alloc:
2325 print("%s Allocating temps" % self)
2326 self.allocate_temp(env, result)
2327 self.loop.analyse_declarations(env)
2328 self.loop.analyse_expressions(env)
2330 def generate_operation_code(self, code):
2331 code.putln("%s = PyList_New(%s); %s" %
2334 code.error_goto_if_null(self.result_code, self.pos)))
2335 self.loop.generate_execution_code(code)
2337 def annotate(self, code):
2338 self.loop.annotate(code)
2341 class ListComprehensionAppendNode(ExprNode):
2345 def analyse_types(self, env):
2346 self.expr.analyse_types(env)
2347 if self.expr.type != py_object_type:
2348 self.expr = self.expr.coerce_to_pyobject(env)
2349 self.type = PyrexTypes.c_int_type
2352 def generate_result_code(self, code):
2353 code.putln("%s = PyList_Append(%s, %s); %s" %
2355 self.target.result_code,
2356 self.expr.result_code,
2357 code.error_goto_if(self.result_code, self.pos)))
2360 class DictNode(ExprNode):
2361 # Dictionary constructor.
2363 # key_value_pairs [DictItemNode]
2365 subexprs = ['key_value_pairs']
2367 def compile_time_value(self, denv):
2368 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
2369 for item in self.key_value_pairs]
2372 except Exception, e:
2373 self.compile_time_value_error(e)
2375 def analyse_types(self, env):
2376 for item in self.key_value_pairs:
2377 item.analyse_types(env)
2378 self.type = dict_type
2381 def allocate_temps(self, env, result = None):
2382 # Custom method used here because key-value
2383 # pairs are evaluated and used one at a time.
2384 self.allocate_temp(env, result)
2385 for item in self.key_value_pairs:
2386 item.key.allocate_temps(env)
2387 item.value.allocate_temps(env)
2388 item.key.release_temp(env)
2389 item.value.release_temp(env)
2391 def generate_evaluation_code(self, code):
2392 # Custom method used here because key-value
2393 # pairs are evaluated and used one at a time.
2395 "%s = PyDict_New(); %s" % (
2397 code.error_goto_if_null(self.result_code, self.pos)))
2398 for item in self.key_value_pairs:
2399 item.generate_evaluation_code(code)
2400 code.put_error_if_neg(self.pos,
2401 "PyDict_SetItem(%s, %s, %s)" % (
2403 item.key.py_result(),
2404 item.value.py_result()))
2405 item.generate_disposal_code(code)
2407 def annotate(self, code):
2408 for item in self.key_value_pairs:
2411 class DictItemNode(ExprNode):
2412 # Represents a single item in a DictNode
2416 subexprs = ['key', 'value']
2418 def analyse_types(self, env):
2419 self.key.analyse_types(env)
2420 self.value.analyse_types(env)
2421 self.key = self.key.coerce_to_pyobject(env)
2422 self.value = self.value.coerce_to_pyobject(env)
2424 def generate_evaluation_code(self, code):
2425 self.key.generate_evaluation_code(code)
2426 self.value.generate_evaluation_code(code)
2428 def generate_disposal_code(self, code):
2429 self.key.generate_disposal_code(code)
2430 self.value.generate_disposal_code(code)
2433 class ClassNode(ExprNode):
2434 # Helper class used in the implementation of Python
2435 # class definitions. Constructs a class object given
2436 # a name, tuple of bases and class dictionary.
2438 # name EncodedString Name of the class
2439 # cname string Class name as a Python string
2440 # bases ExprNode Base class tuple
2441 # dict ExprNode Class dict (not owned by this node)
2442 # doc ExprNode or None Doc string
2443 # module_name string Name of defining module
2445 subexprs = ['bases', 'doc']
2447 def analyse_types(self, env):
2448 self.cname = env.intern_identifier(self.name)
2449 self.bases.analyse_types(env)
2451 self.doc.analyse_types(env)
2452 self.doc = self.doc.coerce_to_pyobject(env)
2453 self.module_name = env.global_scope().qualified_name
2454 self.type = py_object_type
2456 env.use_utility_code(create_class_utility_code);
2458 def generate_result_code(self, code):
2460 code.put_error_if_neg(self.pos,
2461 'PyDict_SetItemString(%s, "__doc__", %s)' % (
2462 self.dict.py_result(),
2463 self.doc.py_result()))
2465 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
2467 self.bases.py_result(),
2468 self.dict.py_result(),
2471 code.error_goto_if_null(self.result_code, self.pos)))
2474 class UnboundMethodNode(ExprNode):
2475 # Helper class used in the implementation of Python
2476 # class definitions. Constructs an unbound method
2477 # object from a class and a function.
2479 # class_cname string C var holding the class object
2480 # function ExprNode Function object
2482 subexprs = ['function']
2484 def analyse_types(self, env):
2485 self.function.analyse_types(env)
2486 self.type = py_object_type
2489 def generate_result_code(self, code):
2491 "%s = PyMethod_New(%s, 0, %s); %s" % (
2493 self.function.py_result(),
2495 code.error_goto_if_null(self.result_code, self.pos)))
2498 class PyCFunctionNode(AtomicExprNode):
2499 # Helper class used in the implementation of Python
2500 # class definitions. Constructs a PyCFunction object
2501 # from a PyMethodDef struct.
2503 # pymethdef_cname string PyMethodDef structure
2505 def analyse_types(self, env):
2506 self.type = py_object_type
2509 def generate_result_code(self, code):
2511 "%s = PyCFunction_New(&%s, 0); %s" % (
2513 self.pymethdef_cname,
2514 code.error_goto_if_null(self.result_code, self.pos)))
2516 #-------------------------------------------------------------------
2518 # Unary operator nodes
2520 #-------------------------------------------------------------------
2522 compile_time_unary_operators = {
2523 'not': operator.not_,
2529 class UnopNode(ExprNode):
2533 # Processing during analyse_expressions phase:
2535 # analyse_c_operation
2536 # Called when the operand is not a pyobject.
2537 # - Check operand type and coerce if needed.
2538 # - Determine result type and result code fragment.
2539 # - Allocate temporary for result if needed.
2541 subexprs = ['operand']
2543 def compile_time_value(self, denv):
2544 func = compile_time_unary_operators.get(self.operator)
2547 "Unary '%s' not supported in compile-time expression"
2549 operand = self.operand.compile_time_value(denv)
2551 return func(operand)
2552 except Exception, e:
2553 self.compile_time_value_error(e)
2555 def analyse_types(self, env):
2556 self.operand.analyse_types(env)
2557 if self.is_py_operation():
2558 self.coerce_operand_to_pyobject(env)
2559 self.type = py_object_type
2562 self.analyse_c_operation(env)
2564 def check_const(self):
2565 self.operand.check_const()
2567 def is_py_operation(self):
2568 return self.operand.type.is_pyobject
2570 def coerce_operand_to_pyobject(self, env):
2571 self.operand = self.operand.coerce_to_pyobject(env)
2573 def generate_result_code(self, code):
2574 if self.operand.type.is_pyobject:
2575 self.generate_py_operation_code(code)
2578 self.generate_c_operation_code(code)
2580 def generate_py_operation_code(self, code):
2581 function = self.py_operation_function()
2583 "%s = %s(%s); %s" % (
2586 self.operand.py_result(),
2587 code.error_goto_if_null(self.result_code, self.pos)))
2589 def type_error(self):
2590 if not self.operand.type.is_error:
2591 error(self.pos, "Invalid operand type for '%s' (%s)" %
2592 (self.operator, self.operand.type))
2593 self.type = PyrexTypes.error_type
2596 class NotNode(ExprNode):
2601 def compile_time_value(self, denv):
2602 operand = self.operand.compile_time_value(denv)
2605 except Exception, e:
2606 self.compile_time_value_error(e)
2608 subexprs = ['operand']
2610 def analyse_types(self, env):
2611 self.operand.analyse_types(env)
2612 self.operand = self.operand.coerce_to_boolean(env)
2613 self.type = PyrexTypes.c_bint_type
2615 def calculate_result_code(self):
2616 return "(!%s)" % self.operand.result_code
2618 def generate_result_code(self, code):
2622 class UnaryPlusNode(UnopNode):
2623 # unary '+' operator
2627 def analyse_c_operation(self, env):
2628 self.type = self.operand.type
2630 def py_operation_function(self):
2631 return "PyNumber_Positive"
2633 def calculate_result_code(self):
2634 return self.operand.result_code
2637 class UnaryMinusNode(UnopNode):
2638 # unary '-' operator
2642 def analyse_c_operation(self, env):
2643 if self.operand.type.is_numeric:
2644 self.type = self.operand.type
2648 def py_operation_function(self):
2649 return "PyNumber_Negative"
2651 def calculate_result_code(self):
2652 return "(-%s)" % self.operand.result_code
2655 class TildeNode(UnopNode):
2656 # unary '~' operator
2658 def analyse_c_operation(self, env):
2659 if self.operand.type.is_int:
2660 self.type = self.operand.type
2664 def py_operation_function(self):
2665 return "PyNumber_Invert"
2667 def calculate_result_code(self):
2668 return "(~%s)" % self.operand.result_code
2671 class AmpersandNode(ExprNode):
2672 # The C address-of operator.
2676 subexprs = ['operand']
2678 def analyse_types(self, env):
2679 self.operand.analyse_types(env)
2680 argtype = self.operand.type
2681 if not (argtype.is_cfunction or self.operand.is_lvalue()):
2682 self.error("Taking address of non-lvalue")
2684 if argtype.is_pyobject:
2685 self.error("Cannot take address of Python variable")
2687 self.type = PyrexTypes.c_ptr_type(argtype)
2689 def check_const(self):
2690 self.operand.check_const_addr()
2692 def error(self, mess):
2693 error(self.pos, mess)
2694 self.type = PyrexTypes.error_type
2695 self.result_code = "<error>"
2697 def calculate_result_code(self):
2698 return "(&%s)" % self.operand.result_code
2700 def generate_result_code(self, code):
2704 unop_node_classes = {
2706 "-": UnaryMinusNode,
2710 def unop_node(pos, operator, operand):
2711 # Construct unnop node of appropriate class for
2713 if isinstance(operand, IntNode) and operator == '-':
2714 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
2715 elif isinstance(operand, UnopNode) and operand.operator == operator:
2716 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
2717 return unop_node_classes[operator](pos,
2718 operator = operator,
2722 class TypecastNode(ExprNode):
2725 # base_type CBaseTypeNode
2726 # declarator CDeclaratorNode
2729 subexprs = ['operand']
2731 def analyse_types(self, env):
2732 base_type = self.base_type.analyse(env)
2733 _, self.type = self.declarator.analyse(base_type, env)
2734 self.operand.analyse_types(env)
2735 to_py = self.type.is_pyobject
2736 from_py = self.operand.type.is_pyobject
2737 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
2738 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
2739 if to_py and not from_py:
2740 self.result_ctype = py_object_type
2742 if self.operand.type.to_py_function:
2743 self.operand = self.operand.coerce_to_pyobject(env)
2745 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
2746 elif from_py and not to_py:
2747 if self.type.from_py_function:
2748 self.operand = self.operand.coerce_to(self.type, env)
2750 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
2751 elif from_py and to_py:
2752 if self.typecheck and self.type.is_extension_type:
2753 self.operand = PyTypeTestNode(self.operand, self.type, env)
2755 def check_const(self):
2756 self.operand.check_const()
2758 def calculate_result_code(self):
2760 result_code = self.type.cast_code(opnd.result_code)
2763 def result_as(self, type):
2764 if self.type.is_pyobject and not self.is_temp:
2765 # Optimise away some unnecessary casting
2766 return self.operand.result_as(type)
2768 return ExprNode.result_as(self, type)
2770 def generate_result_code(self, code):
2773 "%s = (PyObject *)%s;" % (
2775 self.operand.result_code))
2776 code.put_incref(self.result_code, self.ctype())
2779 class SizeofNode(ExprNode):
2780 # Abstract base class for sizeof(x) expression nodes.
2782 def check_const(self):
2785 def generate_result_code(self, code):
2789 class SizeofTypeNode(SizeofNode):
2790 # C sizeof function applied to a type
2792 # base_type CBaseTypeNode
2793 # declarator CDeclaratorNode
2797 def analyse_types(self, env):
2798 base_type = self.base_type.analyse(env)
2799 _, arg_type = self.declarator.analyse(base_type, env)
2800 self.arg_type = arg_type
2801 if arg_type.is_pyobject and not arg_type.is_extension_type:
2802 error(self.pos, "Cannot take sizeof Python object")
2803 elif arg_type.is_void:
2804 error(self.pos, "Cannot take sizeof void")
2805 elif not arg_type.is_complete():
2806 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
2807 self.type = PyrexTypes.c_int_type
2809 def calculate_result_code(self):
2810 if self.arg_type.is_extension_type:
2811 # the size of the pointer is boring
2812 # we want the size of the actual struct
2813 arg_code = self.arg_type.declaration_code("", deref=1)
2815 arg_code = self.arg_type.declaration_code("")
2816 return "(sizeof(%s))" % arg_code
2819 class SizeofVarNode(SizeofNode):
2820 # C sizeof function applied to a variable
2824 subexprs = ['operand']
2826 def analyse_types(self, env):
2827 self.operand.analyse_types(env)
2828 self.type = PyrexTypes.c_int_type
2830 def calculate_result_code(self):
2831 return "(sizeof(%s))" % self.operand.result_code
2833 def generate_result_code(self, code):
2837 #-------------------------------------------------------------------
2839 # Binary operator nodes
2841 #-------------------------------------------------------------------
2843 def _not_in(x, seq):
2846 compile_time_binary_operators = {
2854 'is_not': operator.is_not,
2858 '//': operator.floordiv,
2859 '<<': operator.lshift,
2864 '>>': operator.rshift,
2866 #'/': operator.truediv,
2868 'in': operator.contains,
2872 def get_compile_time_binop(node):
2873 func = compile_time_binary_operators.get(node.operator)
2876 "Binary '%s' not supported in compile-time expression"
2880 class BinopNode(ExprNode):
2885 # Processing during analyse_expressions phase:
2887 # analyse_c_operation
2888 # Called when neither operand is a pyobject.
2889 # - Check operand types and coerce if needed.
2890 # - Determine result type and result code fragment.
2891 # - Allocate temporary for result if needed.
2893 subexprs = ['operand1', 'operand2']
2895 def compile_time_value(self, denv):
2896 func = get_compile_time_binop(self)
2897 operand1 = self.operand1.compile_time_value(denv)
2898 operand2 = self.operand2.compile_time_value(denv)
2900 return func(operand1, operand2)
2901 except Exception, e:
2902 self.compile_time_value_error(e)
2904 def analyse_types(self, env):
2905 self.operand1.analyse_types(env)
2906 self.operand2.analyse_types(env)
2907 if self.is_py_operation():
2908 self.coerce_operands_to_pyobjects(env)
2909 self.type = py_object_type
2911 if Options.incref_local_binop and self.operand1.type.is_pyobject:
2912 self.operand1 = self.operand1.coerce_to_temp(env)
2914 self.analyse_c_operation(env)
2916 def is_py_operation(self):
2917 return (self.operand1.type.is_pyobject
2918 or self.operand2.type.is_pyobject)
2920 def coerce_operands_to_pyobjects(self, env):
2921 self.operand1 = self.operand1.coerce_to_pyobject(env)
2922 self.operand2 = self.operand2.coerce_to_pyobject(env)
2924 def check_const(self):
2925 self.operand1.check_const()
2926 self.operand2.check_const()
2928 def generate_result_code(self, code):
2929 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
2930 if self.operand1.type.is_pyobject:
2931 function = self.py_operation_function()
2932 if function == "PyNumber_Power":
2933 extra_args = ", Py_None"
2937 "%s = %s(%s, %s%s); %s" % (
2940 self.operand1.py_result(),
2941 self.operand2.py_result(),
2943 code.error_goto_if_null(self.result_code, self.pos)))
2946 self.generate_c_operation_code(code)
2948 def type_error(self):
2949 if not (self.operand1.type.is_error
2950 or self.operand2.type.is_error):
2951 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
2952 (self.operator, self.operand1.type,
2953 self.operand2.type))
2954 self.type = PyrexTypes.error_type
2957 class NumBinopNode(BinopNode):
2958 # Binary operation taking numeric arguments.
2960 def analyse_c_operation(self, env):
2961 type1 = self.operand1.type
2962 type2 = self.operand2.type
2963 if self.operator == "**" and type1.is_int and type2.is_int:
2964 error(self.pos, "** with two C int types is ambiguous")
2965 self.type = error_type
2967 self.type = self.compute_c_result_type(type1, type2)
2971 def compute_c_result_type(self, type1, type2):
2972 if self.c_types_okay(type1, type2):
2973 return PyrexTypes.widest_numeric_type(type1, type2)
2977 def c_types_okay(self, type1, type2):
2978 #print "NumBinopNode.c_types_okay:", type1, type2 ###
2979 return (type1.is_numeric or type1.is_enum) \
2980 and (type2.is_numeric or type2.is_enum)
2982 def calculate_result_code(self):
2983 return "(%s %s %s)" % (
2984 self.operand1.result_code,
2986 self.operand2.result_code)
2988 def py_operation_function(self):
2989 return self.py_functions[self.operator]
2993 "^": "PyNumber_Xor",
2994 "&": "PyNumber_And",
2995 "<<": "PyNumber_Lshift",
2996 ">>": "PyNumber_Rshift",
2997 "+": "PyNumber_Add",
2998 "-": "PyNumber_Subtract",
2999 "*": "PyNumber_Multiply",
3000 "/": "PyNumber_Divide",
3001 "//": "PyNumber_FloorDivide",
3002 "%": "PyNumber_Remainder",
3003 "**": "PyNumber_Power"
3007 class IntBinopNode(NumBinopNode):
3008 # Binary operation taking integer arguments.
3010 def c_types_okay(self, type1, type2):
3011 #print "IntBinopNode.c_types_okay:", type1, type2 ###
3012 return (type1.is_int or type1.is_enum) \
3013 and (type2.is_int or type2.is_enum)
3016 class AddNode(NumBinopNode):
3019 def is_py_operation(self):
3020 if self.operand1.type.is_string \
3021 and self.operand2.type.is_string:
3024 return NumBinopNode.is_py_operation(self)
3026 def compute_c_result_type(self, type1, type2):
3027 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
3028 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3030 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
3033 return NumBinopNode.compute_c_result_type(
3037 class SubNode(NumBinopNode):
3040 def compute_c_result_type(self, type1, type2):
3041 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3043 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
3044 return PyrexTypes.c_int_type
3046 return NumBinopNode.compute_c_result_type(
3050 class MulNode(NumBinopNode):
3053 def is_py_operation(self):
3054 type1 = self.operand1.type
3055 type2 = self.operand2.type
3056 if (type1.is_string and type2.is_int) \
3057 or (type2.is_string and type1.is_int):
3060 return NumBinopNode.is_py_operation(self)
3063 class FloorDivNode(NumBinopNode):
3066 def calculate_result_code(self):
3067 return "(%s %s %s)" % (
3068 self.operand1.result_code,
3069 "/", # c division is by default floor-div
3070 self.operand2.result_code)
3073 class ModNode(IntBinopNode):
3076 def is_py_operation(self):
3077 return (self.operand1.type.is_string
3078 or self.operand2.type.is_string
3079 or IntBinopNode.is_py_operation(self))
3082 class PowNode(NumBinopNode):
3085 def analyse_types(self, env):
3086 env.pow_function_used = 1
3087 NumBinopNode.analyse_types(self, env)
3089 def compute_c_result_type(self, type1, type2):
3090 if self.c_types_okay(type1, type2):
3091 return PyrexTypes.c_double_type
3095 def c_types_okay(self, type1, type2):
3096 return type1.is_float or type2.is_float
3098 def type_error(self):
3099 if not (self.operand1.type.is_error or self.operand2.type.is_error):
3100 if self.operand1.type.is_int and self.operand2.type.is_int:
3101 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
3102 (self.operator, self.operand1.type, self.operand2.type))
3104 NumBinopNode.type_error(self)
3105 self.type = PyrexTypes.error_type
3107 def calculate_result_code(self):
3108 return "pow(%s, %s)" % (
3109 self.operand1.result_code, self.operand2.result_code)
3112 class BoolBinopNode(ExprNode):
3113 # Short-circuiting boolean operation.
3118 # temp_bool ExprNode used internally
3122 subexprs = ['operand1', 'operand2', 'temp_bool']
3124 def compile_time_value(self, denv):
3125 if self.operator == 'and':
3126 return self.operand1.compile_time_value(denv) \
3127 and self.operand2.compile_time_value(denv)
3129 return self.operand1.compile_time_value(denv) \
3130 or self.operand2.compile_time_value(denv)
3132 def analyse_types(self, env):
3133 self.operand1.analyse_types(env)
3134 self.operand2.analyse_types(env)
3135 if self.operand1.type.is_pyobject or \
3136 self.operand2.type.is_pyobject:
3137 self.operand1 = self.operand1.coerce_to_pyobject(env)
3138 self.operand2 = self.operand2.coerce_to_pyobject(env)
3139 self.temp_bool = TempNode(self.pos, PyrexTypes.c_bint_type, env)
3140 self.type = py_object_type
3142 self.operand1 = self.operand1.coerce_to_boolean(env)
3143 self.operand2 = self.operand2.coerce_to_boolean(env)
3144 self.type = PyrexTypes.c_bint_type
3145 # For what we're about to do, it's vital that
3146 # both operands be temp nodes.
3147 self.operand1 = self.operand1.coerce_to_temp(env) #CTT
3148 self.operand2 = self.operand2.coerce_to_temp(env)
3149 # coerce_to_simple does not seem to be sufficient
3150 #self.operand1 = self.operand1.coerce_to_simple(env)
3151 #self.operand2 = self.operand2.coerce_to_simple(env)
3154 def allocate_temps(self, env, result_code = None):
3155 # We don't need both operands at the same time, and
3156 # one of the operands will also be our result. So we
3157 # use an allocation strategy here which results in
3158 # this node and both its operands sharing the same
3159 # result variable. This allows us to avoid some
3160 # assignments and increfs/decrefs that would otherwise
3162 self.allocate_temp(env, result_code)
3163 self.operand1.allocate_temps(env, self.result_code)
3165 self.temp_bool.allocate_temp(env)
3166 self.temp_bool.release_temp(env)
3167 self.operand2.allocate_temps(env, self.result_code)
3168 # We haven't called release_temp on either operand,
3169 # because although they are temp nodes, they don't own
3170 # their result variable. And because they are temp
3171 # nodes, any temps in their subnodes will have been
3172 # released before their allocate_temps returned.
3173 # Therefore, they contain no temp vars that need to
3176 def check_const(self):
3177 self.operand1.check_const()
3178 self.operand2.check_const()
3180 def calculate_result_code(self):
3181 return "(%s %s %s)" % (
3182 self.operand1.result_code,
3183 self.py_to_c_op[self.operator],
3184 self.operand2.result_code)
3186 py_to_c_op = {'and': "&&", 'or': "||"}
3188 def generate_evaluation_code(self, code):
3189 self.operand1.generate_evaluation_code(code)
3190 test_result = self.generate_operand1_test(code)
3191 if self.operator == 'and':
3199 self.operand1.generate_disposal_code(code)
3200 self.operand2.generate_evaluation_code(code)
3204 def generate_operand1_test(self, code):
3205 # Generate code to test the truth of the first operand.
3206 if self.type.is_pyobject:
3207 test_result = self.temp_bool.result_code
3209 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3211 self.operand1.py_result(),
3212 code.error_goto_if_neg(test_result, self.pos)))
3214 test_result = self.operand1.result_code
3218 class CondExprNode(ExprNode):
3219 # Short-circuiting conditional expression.
3223 # false_val ExprNode
3227 subexprs = ['test', 'true_val', 'false_val']
3229 def analyse_types(self, env):
3230 self.test.analyse_types(env)
3231 self.test = self.test.coerce_to_boolean(env)
3232 self.true_val.analyse_types(env)
3233 self.false_val.analyse_types(env)
3234 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
3235 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
3236 self.true_val = self.true_val.coerce_to(self.type, env)
3237 self.false_val = self.false_val.coerce_to(self.type, env)
3238 # must be tmp variables so they can share a result
3239 self.true_val = self.true_val.coerce_to_temp(env)
3240 self.false_val = self.false_val.coerce_to_temp(env)
3242 if self.type == PyrexTypes.error_type:
3245 def allocate_temps(self, env, result_code = None):
3246 # We only ever evaluate one side, and this is
3247 # after evaluating the truth value, so we may
3248 # use an allocation strategy here which results in
3249 # this node and both its operands sharing the same
3250 # result variable. This allows us to avoid some
3251 # assignments and increfs/decrefs that would otherwise
3253 self.allocate_temp(env, result_code)
3254 self.test.allocate_temps(env, result_code)
3255 self.true_val.allocate_temps(env, self.result_code)
3256 self.false_val.allocate_temps(env, self.result_code)
3257 # We haven't called release_temp on either value,
3258 # because although they are temp nodes, they don't own
3259 # their result variable. And because they are temp
3260 # nodes, any temps in their subnodes will have been
3261 # released before their allocate_temps returned.
3262 # Therefore, they contain no temp vars that need to
3265 def compute_result_type(self, type1, type2):
3268 elif type1.is_numeric and type2.is_numeric:
3269 return PyrexTypes.widest_numeric_type(type1, type2)
3270 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
3272 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
3274 elif type1.is_pyobject or type2.is_pyobject:
3275 return py_object_type
3276 elif type1.assignable_from(type2):
3278 elif type2.assignable_from(type1):
3281 return PyrexTypes.error_type
3283 def type_error(self):
3284 if not (self.true_val.type.is_error or self.false_val.type.is_error):
3285 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
3286 (self.true_val.type, self.false_val.type))
3287 self.type = PyrexTypes.error_type
3289 def check_const(self):
3290 self.test.check_const()
3291 self.true_val.check_const()
3292 self.false_val.check_const()
3294 def generate_evaluation_code(self, code):
3295 self.test.generate_evaluation_code(code)
3296 code.putln("if (%s) {" % self.test.result_code )
3297 self.true_val.generate_evaluation_code(code)
3298 code.putln("} else {")
3299 self.false_val.generate_evaluation_code(code)
3301 self.test.generate_disposal_code(code)
3303 richcmp_constants = {
3314 # Mixin class containing code common to PrimaryCmpNodes
3315 # and CascadedCmpNodes.
3317 def cascaded_compile_time_value(self, operand1, denv):
3318 func = get_compile_time_binop(self)
3319 operand2 = self.operand2.compile_time_value(denv)
3321 result = func(operand1, operand2)
3322 except Exception, e:
3323 self.compile_time_value_error(e)
3326 cascade = self.cascade
3328 result = result and cascade.compile_time_value(operand2, denv)
3331 def is_python_comparison(self):
3332 return (self.has_python_operands()
3333 or (self.cascade and self.cascade.is_python_comparison())
3334 or self.operator in ('in', 'not_in'))
3336 def is_python_result(self):
3337 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
3338 or (self.cascade and self.cascade.is_python_result()))
3340 def check_types(self, env, operand1, op, operand2):
3341 if not self.types_okay(operand1, op, operand2):
3342 error(self.pos, "Invalid types for '%s' (%s, %s)" %
3343 (self.operator, operand1.type, operand2.type))
3345 def types_okay(self, operand1, op, operand2):
3346 type1 = operand1.type
3347 type2 = operand2.type
3348 if type1.is_error or type2.is_error:
3350 if type1.is_pyobject: # type2 will be, too
3352 elif type1.is_ptr or type1.is_array:
3353 return type1.is_null_ptr or type2.is_null_ptr \
3354 or ((type2.is_ptr or type2.is_array)
3355 and type1.base_type.same_as(type2.base_type))
3356 elif ((type1.is_numeric and type2.is_numeric
3357 or type1.is_enum and (type1 is type2 or type2.is_int)
3358 or type1.is_int and type2.is_enum)
3359 and op not in ('is', 'is_not')):
3362 return type1.is_cfunction and type1.is_cfunction and type1 == type2
3364 def generate_operation_code(self, code, result_code,
3365 operand1, op , operand2):
3366 if self.type is PyrexTypes.py_object_type:
3367 coerce_result = "__Pyx_PyBool_FromLong"
3370 if 'not' in op: negation = "!"
3372 if op == 'in' or op == 'not_in':
3374 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
3378 operand2.py_result(),
3379 operand1.py_result(),
3380 code.error_goto_if_neg(result_code, self.pos)))
3381 elif (operand1.type.is_pyobject
3382 and op not in ('is', 'is_not')):
3383 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
3385 operand1.py_result(),
3386 operand2.py_result(),
3387 richcmp_constants[op],
3388 code.error_goto_if_null(result_code, self.pos)))
3390 type1 = operand1.type
3391 type2 = operand2.type
3392 if (type1.is_extension_type or type2.is_extension_type) \
3393 and not type1.same_as(type2):
3394 common_type = py_object_type
3395 elif type1.is_numeric:
3396 common_type = PyrexTypes.widest_numeric_type(type1, type2)
3399 code1 = operand1.result_as(common_type)
3400 code2 = operand2.result_as(common_type)
3401 code.putln("%s = %s(%s %s %s);" % (
3405 self.c_operator(op),
3408 def c_operator(self, op):
3411 elif op == 'is_not':
3417 class PrimaryCmpNode(ExprNode, CmpNode):
3418 # Non-cascaded comparison or first comparison of
3419 # a cascaded sequence.
3424 # cascade CascadedCmpNode
3426 # We don't use the subexprs mechanism, because
3427 # things here are too complicated for it to handle.
3428 # Instead, we override all the framework methods
3431 child_attrs = ['operand1', 'operand2', 'cascade']
3435 def compile_time_value(self, denv):
3436 operand1 = self.operand1.compile_time_value(denv)
3437 return self.cascaded_compile_time_value(operand1, denv)
3439 def analyse_types(self, env):
3440 self.operand1.analyse_types(env)
3441 self.operand2.analyse_types(env)
3443 self.cascade.analyse_types(env, self.operand2)
3444 self.is_pycmp = self.is_python_comparison()
3446 self.coerce_operands_to_pyobjects(env)
3447 if self.has_int_operands():
3448 self.coerce_chars_to_ints(env)
3450 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
3451 self.operand2 = self.operand2.coerce_to_simple(env)
3452 self.cascade.coerce_cascaded_operands_to_temp(env)
3453 self.check_operand_types(env)
3454 if self.is_python_result():
3455 self.type = PyrexTypes.py_object_type
3457 self.type = PyrexTypes.c_bint_type
3460 cdr.type = self.type
3462 if self.is_pycmp or self.cascade:
3465 def check_operand_types(self, env):
3466 self.check_types(env,
3467 self.operand1, self.operator, self.operand2)
3469 self.cascade.check_operand_types(env, self.operand2)
3471 def has_python_operands(self):
3472 return (self.operand1.type.is_pyobject
3473 or self.operand2.type.is_pyobject)
3475 def coerce_operands_to_pyobjects(self, env):
3476 self.operand1 = self.operand1.coerce_to_pyobject(env)
3477 self.operand2 = self.operand2.coerce_to_pyobject(env)
3479 self.cascade.coerce_operands_to_pyobjects(env)
3481 def has_int_operands(self):
3482 return (self.operand1.type.is_int or self.operand2.type.is_int) \
3483 or (self.cascade and self.cascade.has_int_operands())
3485 def coerce_chars_to_ints(self, env):
3486 if self.operand1.type.is_string:
3487 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
3488 if self.operand2.type.is_string:
3489 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3491 self.cascade.coerce_chars_to_ints(env)
3493 def allocate_subexpr_temps(self, env):
3494 self.operand1.allocate_temps(env)
3495 self.operand2.allocate_temps(env)
3497 self.cascade.allocate_subexpr_temps(env)
3499 def release_subexpr_temps(self, env):
3500 self.operand1.release_temp(env)
3501 self.operand2.release_temp(env)
3503 self.cascade.release_subexpr_temps(env)
3505 def check_const(self):
3506 self.operand1.check_const()
3507 self.operand2.check_const()
3511 def calculate_result_code(self):
3512 return "(%s %s %s)" % (
3513 self.operand1.result_code,
3514 self.c_operator(self.operator),
3515 self.operand2.result_code)
3517 def generate_evaluation_code(self, code):
3518 self.operand1.generate_evaluation_code(code)
3519 self.operand2.generate_evaluation_code(code)
3521 self.generate_operation_code(code, self.result_code,
3522 self.operand1, self.operator, self.operand2)
3524 self.cascade.generate_evaluation_code(code,
3525 self.result_code, self.operand2)
3526 self.operand1.generate_disposal_code(code)
3527 self.operand2.generate_disposal_code(code)
3529 def generate_subexpr_disposal_code(self, code):
3530 # If this is called, it is a non-cascaded cmp,
3531 # so only need to dispose of the two main operands.
3532 self.operand1.generate_disposal_code(code)
3533 self.operand2.generate_disposal_code(code)
3535 def annotate(self, code):
3536 self.operand1.annotate(code)
3537 self.operand2.annotate(code)
3539 self.cascade.annotate(code)
3542 class CascadedCmpNode(Node, CmpNode):
3543 # A CascadedCmpNode is not a complete expression node. It
3544 # hangs off the side of another comparison node, shares
3545 # its left operand with that node, and shares its result
3546 # with the PrimaryCmpNode at the head of the chain.
3550 # cascade CascadedCmpNode
3552 child_attrs = ['operand2', 'cascade']
3556 def analyse_types(self, env, operand1):
3557 self.operand2.analyse_types(env)
3559 self.cascade.analyse_types(env, self.operand2)
3561 def check_operand_types(self, env, operand1):
3562 self.check_types(env,
3563 operand1, self.operator, self.operand2)
3565 self.cascade.check_operand_types(env, self.operand2)
3567 def has_python_operands(self):
3568 return self.operand2.type.is_pyobject
3570 def coerce_operands_to_pyobjects(self, env):
3571 self.operand2 = self.operand2.coerce_to_pyobject(env)
3573 self.cascade.coerce_operands_to_pyobjects(env)
3575 def has_int_operands(self):
3576 return self.operand2.type.is_int
3578 def coerce_chars_to_ints(self, env):
3579 if self.operand2.type.is_string:
3580 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3582 def coerce_cascaded_operands_to_temp(self, env):
3584 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
3585 self.operand2 = self.operand2.coerce_to_simple(env)
3586 self.cascade.coerce_cascaded_operands_to_temp(env)
3588 def allocate_subexpr_temps(self, env):
3589 self.operand2.allocate_temps(env)
3591 self.cascade.allocate_subexpr_temps(env)
3593 def release_subexpr_temps(self, env):
3594 self.operand2.release_temp(env)
3596 self.cascade.release_subexpr_temps(env)
3598 def generate_evaluation_code(self, code, result, operand1):
3599 if self.type.is_pyobject:
3600 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
3602 code.putln("if (%s) {" % result)
3603 self.operand2.generate_evaluation_code(code)
3604 self.generate_operation_code(code, result,
3605 operand1, self.operator, self.operand2)
3607 self.cascade.generate_evaluation_code(
3608 code, result, self.operand2)
3609 # Cascaded cmp result is always temp
3610 self.operand2.generate_disposal_code(code)
3613 def annotate(self, code):
3614 self.operand2.annotate(code)
3616 self.cascade.annotate(code)
3619 binop_node_classes = {
3620 "or": BoolBinopNode,
3621 "and": BoolBinopNode,
3636 def binop_node(pos, operator, operand1, operand2):
3637 # Construct binop node of appropriate class for
3639 return binop_node_classes[operator](pos,
3640 operator = operator,
3641 operand1 = operand1,
3642 operand2 = operand2)
3644 #-------------------------------------------------------------------
3648 # Coercion nodes are special in that they are created during
3649 # the analyse_types phase of parse tree processing.
3650 # Their __init__ methods consequently incorporate some aspects
3653 #-------------------------------------------------------------------
3655 class CoercionNode(ExprNode):
3656 # Abstract base class for coercion nodes.
3658 # arg ExprNode node being coerced
3662 def __init__(self, arg):
3666 print("%s Coercing %s" % (self, self.arg))
3668 def annotate(self, code):
3669 self.arg.annotate(code)
3670 if self.arg.type != self.type:
3671 file, line, col = self.pos
3672 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
3675 class CastNode(CoercionNode):
3676 # Wrap a node in a C type cast.
3678 def __init__(self, arg, new_type):
3679 CoercionNode.__init__(self, arg)
3680 self.type = new_type
3682 def calculate_result_code(self):
3683 return self.arg.result_as(self.type)
3685 def generate_result_code(self, code):
3686 self.arg.generate_result_code(code)
3689 class PyTypeTestNode(CoercionNode):
3690 # This node is used to check that a generic Python
3691 # object is an instance of a particular extension type.
3692 # This node borrows the result of its argument node.
3694 def __init__(self, arg, dst_type, env):
3695 # The arg is know to be a Python object, and
3696 # the dst_type is known to be an extension type.
3697 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
3698 CoercionNode.__init__(self, arg)
3699 self.type = dst_type
3700 self.result_ctype = arg.ctype()
3701 env.use_utility_code(type_test_utility_code)
3703 def analyse_types(self, env):
3706 def result_in_temp(self):
3707 return self.arg.result_in_temp()
3709 def is_ephemeral(self):
3710 return self.arg.is_ephemeral()
3712 def calculate_result_code(self):
3713 return self.arg.result_code
3715 def generate_result_code(self, code):
3716 if self.type.typeobj_is_available():
3719 self.type.type_test_code(self.arg.py_result()),
3720 code.error_goto(self.pos)))
3722 error(self.pos, "Cannot test type of extern C class "
3723 "without type object name specification")
3725 def generate_post_assignment_code(self, code):
3726 self.arg.generate_post_assignment_code(code)
3729 class CoerceToPyTypeNode(CoercionNode):
3730 # This node is used to convert a C data type
3731 # to a Python object.
3733 def __init__(self, arg, env):
3734 CoercionNode.__init__(self, arg)
3735 self.type = py_object_type
3737 if not arg.type.to_py_function:
3739 "Cannot convert '%s' to Python object" % arg.type)
3741 def generate_result_code(self, code):
3742 function = self.arg.type.to_py_function
3743 code.putln('%s = %s(%s); %s' % (
3746 self.arg.result_code,
3747 code.error_goto_if_null(self.result_code, self.pos)))
3750 class CoerceFromPyTypeNode(CoercionNode):
3751 # This node is used to convert a Python object
3754 def __init__(self, result_type, arg, env):
3755 CoercionNode.__init__(self, arg)
3756 self.type = result_type
3758 if not result_type.from_py_function:
3760 "Cannot convert Python object to '%s'" % result_type)
3761 if self.type.is_string and self.arg.is_ephemeral():
3763 "Obtaining char * from temporary Python value")
3765 def generate_result_code(self, code):
3766 function = self.type.from_py_function
3767 operand = self.arg.py_result()
3768 rhs = "%s(%s)" % (function, operand)
3769 if self.type.is_enum:
3770 rhs = typecast(self.type, c_long_type, rhs)
3771 code.putln('%s = %s; %s' % (
3774 code.error_goto_if(self.type.error_condition(self.result_code), self.pos)))
3777 class CoerceToBooleanNode(CoercionNode):
3778 # This node is used when a result needs to be used
3779 # in a boolean context.
3781 def __init__(self, arg, env):
3782 CoercionNode.__init__(self, arg)
3783 self.type = PyrexTypes.c_bint_type
3784 if arg.type.is_pyobject:
3787 def check_const(self):
3790 self.arg.check_const()
3792 def calculate_result_code(self):
3793 return "(%s != 0)" % self.arg.result_code
3795 def generate_result_code(self, code):
3796 if self.arg.type.is_pyobject:
3798 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3800 self.arg.py_result(),
3801 code.error_goto_if_neg(self.result_code, self.pos)))
3804 class CoerceToTempNode(CoercionNode):
3805 # This node is used to force the result of another node
3806 # to be stored in a temporary. It is only used if the
3807 # argument node's result is not already in a temporary.
3809 def __init__(self, arg, env):
3810 CoercionNode.__init__(self, arg)
3811 self.type = self.arg.type
3813 if self.type.is_pyobject:
3814 self.result_ctype = py_object_type
3816 def generate_result_code(self, code):
3817 #self.arg.generate_evaluation_code(code) # Already done
3818 # by generic generate_subexpr_evaluation_code!
3819 code.putln("%s = %s;" % (
3820 self.result_code, self.arg.result_as(self.ctype())))
3821 if self.type.is_pyobject:
3822 code.put_incref(self.result_code, self.ctype())
3825 class CloneNode(CoercionNode):
3826 # This node is employed when the result of another node needs
3827 # to be used multiple times. The argument node's result must
3828 # be in a temporary. This node "borrows" the result from the
3829 # argument node, and does not generate any evaluation or
3830 # disposal code for it. The original owner of the argument
3831 # node is responsible for doing those things.
3833 subexprs = [] # Arg is not considered a subexpr
3835 def __init__(self, arg):
3836 CoercionNode.__init__(self, arg)
3837 if hasattr(arg, 'type'):
3838 self.type = arg.type
3839 self.result_ctype = arg.result_ctype
3840 if hasattr(arg, 'entry'):
3841 self.entry = arg.entry
3843 def calculate_result_code(self):
3844 return self.arg.result_code
3846 def analyse_types(self, env):
3847 self.type = self.arg.type
3848 self.result_ctype = self.arg.result_ctype
3850 if hasattr(self.arg, 'entry'):
3851 self.entry = self.arg.entry
3853 #def result_as_extension_type(self):
3854 # return self.arg.result_as_extension_type()
3856 def generate_evaluation_code(self, code):
3859 def generate_result_code(self, code):
3862 def generate_disposal_code(self, code):
3865 def allocate_temps(self, env):
3866 self.result_code = self.calculate_result_code()
3868 def release_temp(self, env):
3871 #------------------------------------------------------------------------------------
3873 # Runtime support code
3875 #------------------------------------------------------------------------------------
3877 get_name_interned_utility_code = [
3879 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
3881 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
3883 result = PyObject_GetAttr(dict, name);
3885 PyErr_SetObject(PyExc_NameError, name);
3890 #------------------------------------------------------------------------------------
3892 import_utility_code = [
3894 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
3896 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
3897 PyObject *__import__ = 0;
3898 PyObject *empty_list = 0;
3899 PyObject *module = 0;
3900 PyObject *global_dict = 0;
3901 PyObject *empty_dict = 0;
3903 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
3909 empty_list = PyList_New(0);
3914 global_dict = PyModule_GetDict(%(GLOBALS)s);
3917 empty_dict = PyDict_New();
3920 module = PyObject_CallFunction(__import__, "OOOO",
3921 name, global_dict, empty_dict, list);
3923 Py_XDECREF(empty_list);
3924 Py_XDECREF(__import__);
3925 Py_XDECREF(empty_dict);
3929 "BUILTINS": Naming.builtins_cname,
3930 "GLOBALS": Naming.module_cname,
3933 #------------------------------------------------------------------------------------
3935 get_exception_utility_code = [
3937 static PyObject *__Pyx_GetExcValue(void); /*proto*/
3939 static PyObject *__Pyx_GetExcValue(void) {
3940 PyObject *type = 0, *value = 0, *tb = 0;
3941 PyObject *tmp_type, *tmp_value, *tmp_tb;
3942 PyObject *result = 0;
3943 PyThreadState *tstate = PyThreadState_Get();
3944 PyErr_Fetch(&type, &value, &tb);
3945 PyErr_NormalizeException(&type, &value, &tb);
3946 if (PyErr_Occurred())
3952 tmp_type = tstate->exc_type;
3953 tmp_value = tstate->exc_value;
3954 tmp_tb = tstate->exc_traceback;
3955 tstate->exc_type = type;
3956 tstate->exc_value = value;
3957 tstate->exc_traceback = tb;
3958 /* Make sure tstate is in a consistent state when we XDECREF
3959 these objects (XDECREF may run arbitrary code). */
3960 Py_XDECREF(tmp_type);
3961 Py_XDECREF(tmp_value);
3976 #------------------------------------------------------------------------------------
3978 unpacking_utility_code = [
3980 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
3981 static int __Pyx_EndUnpack(PyObject *); /*proto*/
3983 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
3985 if (!(item = PyIter_Next(iter))) {
3986 if (!PyErr_Occurred()) {
3987 PyErr_Format(PyExc_ValueError,
3988 #if PY_VERSION_HEX < 0x02050000
3989 "need more than %d values to unpack", (int)index);
3991 "need more than %zd values to unpack", index);
3998 static int __Pyx_EndUnpack(PyObject *iter) {
4000 if ((item = PyIter_Next(iter))) {
4002 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
4005 else if (!PyErr_Occurred())
4012 #------------------------------------------------------------------------------------
4014 type_test_utility_code = [
4016 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
4018 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
4020 PyErr_Format(PyExc_SystemError, "Missing type object");
4023 if (obj == Py_None || PyObject_TypeCheck(obj, type))
4025 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
4026 Py_TYPE(obj)->tp_name, type->tp_name);
4031 #------------------------------------------------------------------------------------
4033 create_class_utility_code = [
4035 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
4037 static PyObject *__Pyx_CreateClass(
4038 PyObject *bases, PyObject *dict, PyObject *name, char *modname)
4040 PyObject *py_modname;
4041 PyObject *result = 0;
4043 #if PY_MAJOR_VERSION < 3
4044 py_modname = PyString_FromString(modname);
4046 py_modname = PyUnicode_FromString(modname);
4050 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
4052 #if PY_MAJOR_VERSION < 3
4053 result = PyClass_New(bases, dict, name);
4055 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
4058 Py_XDECREF(py_modname);
4063 #------------------------------------------------------------------------------------
4065 cpp_exception_utility_code = [
4067 #ifndef __Pyx_CppExn2PyErr
4068 static void __Pyx_CppExn2PyErr() {
4070 if (PyErr_Occurred())
4071 ; // let the latest Python exn pass through and ignore the current one
4074 } catch (const std::out_of_range& exn) {
4075 // catch out_of_range explicitly so the proper Python exn may be raised
4076 PyErr_SetString(PyExc_IndexError, exn.what());
4077 } catch (const std::exception& exn) {
4078 PyErr_SetString(PyExc_RuntimeError, exn.what());
4082 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
4088 #------------------------------------------------------------------------------------
4090 append_utility_code = [
4092 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
4093 if (likely(PyList_CheckExact(L))) {
4094 if (PyList_Append(L, x) < 0) return NULL;
4096 return Py_None; // this is just to have an accurate signature
4099 return PyObject_CallMethod(L, "append", "(O)", x);
4105 #------------------------------------------------------------------------------------
4107 type_cache_invalidation_code = [
4109 #if PY_VERSION_HEX >= 0x02060000
4110 static void __Pyx_TypeModified(PyTypeObject* type); /*proto*/
4112 #define __Pyx_TypeModified(t)
4115 #if PY_VERSION_HEX >= 0x02060000
4116 /* copied from typeobject.c in Python 3.0a5 */
4117 static void __Pyx_TypeModified(PyTypeObject* type) {
4118 PyObject *raw, *ref;
4121 if (!PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))
4124 raw = type->tp_subclasses;
4126 n = PyList_GET_SIZE(raw);
4127 for (i = 0; i < n; i++) {
4128 ref = PyList_GET_ITEM(raw, i);
4129 ref = PyWeakref_GET_OBJECT(ref);
4130 if (ref != Py_None) {
4131 __Pyx_TypeModified((PyTypeObject *)ref);
4135 type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;