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
851 def analyse_types(self, env):
852 self.entry = env.lookup(self.name)
854 self.entry = env.declare_builtin(self.name, self.pos)
856 self.type = PyrexTypes.error_type
858 self.analyse_rvalue_entry(env)
860 def analyse_target_types(self, env):
861 self.analyse_entry(env)
862 if not self.is_lvalue():
863 error(self.pos, "Assignment to non-lvalue '%s'"
865 self.type = PyrexTypes.error_type
868 def analyse_rvalue_entry(self, env):
869 #print "NameNode.analyse_rvalue_entry:", self.name ###
870 #print "Entry:", self.entry.__dict__ ###
871 self.analyse_entry(env)
873 if entry.is_declared_generic:
874 self.result_ctype = py_object_type
875 if entry.is_pyglobal or entry.is_builtin:
876 if Options.cache_builtins and entry.is_builtin:
880 env.use_utility_code(get_name_interned_utility_code)
882 def analyse_entry(self, env):
883 #print "NameNode.analyse_entry:", self.name ###
884 self.check_identifier_kind()
888 if entry.is_pyglobal or entry.is_builtin:
889 assert type.is_pyobject, "Python global or builtin not a Python object"
890 self.interned_cname = self.entry.interned_cname = \
891 env.intern_identifier(self.entry.name)
893 def check_identifier_kind(self):
894 #print "NameNode.check_identifier_kind:", self.entry.name ###
895 #print self.entry.__dict__ ###
898 if not (entry.is_const or entry.is_variable
899 or entry.is_builtin or entry.is_cfunction):
900 if self.entry.as_variable:
901 self.entry = self.entry.as_variable
904 "'%s' is not a constant, variable or function identifier" % self.name)
907 # If it's not a C variable, it'll be in a temp.
910 def calculate_target_results(self, env):
913 def check_const(self):
915 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
918 def check_const_addr(self):
920 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
921 self.addr_not_const()
924 return self.entry.is_variable and \
925 not self.entry.type.is_array and \
926 not self.entry.is_readonly
928 def is_ephemeral(self):
929 # Name nodes are never ephemeral, even if the
930 # result is in a temporary.
933 def allocate_temp(self, env, result = None):
934 AtomicExprNode.allocate_temp(self, env, result)
938 if entry.utility_code:
939 env.use_utility_code(entry.utility_code)
941 def calculate_result_code(self):
944 return "<error>" # There was an error earlier
947 def generate_result_code(self, code):
948 assert hasattr(self, 'entry')
951 return # There was an error earlier
952 if entry.is_builtin and Options.cache_builtins:
953 return # Lookup already cached
954 elif entry.is_pyglobal or entry.is_builtin:
956 namespace = Naming.builtins_cname
957 else: # entry.is_pyglobal
958 namespace = entry.namespace_cname
960 '%s = __Pyx_GetName(%s, %s); %s' % (
964 code.error_goto_if_null(self.result_code, self.pos)))
965 elif entry.is_local and False:
966 # control flow not good enough yet
967 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
968 if assigned is False:
969 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
970 elif not Options.init_local_none and assigned is None:
971 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
972 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
974 def generate_assignment_code(self, rhs, code):
975 #print "NameNode.generate_assignment_code:", self.name ###
978 return # There was an error earlier
980 # is_pyglobal seems to be True for module level-globals only.
981 # We use this to access class->tp_dict if necessary.
982 if entry.is_pyglobal:
983 namespace = self.entry.namespace_cname
985 # if the entry is a member we have to cheat: SetAttr does not work
986 # on types, so we create a descriptor which is then added to tp_dict
987 code.put_error_if_neg(self.pos,
988 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
992 # in Py2.6+, we need to invalidate the method cache
993 typeptr_cname = entry.scope.parent_type.typeptr_cname
994 code.putln("#if PY_VERSION_HEX >= 0x02060000")
995 code.putln("(%s)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;" %
999 code.put_error_if_neg(self.pos,
1000 'PyObject_SetAttr(%s, %s, %s)' % (
1002 self.interned_cname,
1004 if debug_disposal_code:
1005 print("NameNode.generate_assignment_code:")
1006 print("...generating disposal code for %s" % rhs)
1007 rhs.generate_disposal_code(code)
1010 if self.type.is_pyobject:
1011 #print "NameNode.generate_assignment_code: to", self.name ###
1012 #print "...from", rhs ###
1013 #print "...LHS type", self.type, "ctype", self.ctype() ###
1014 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1015 rhs.make_owned_reference(code)
1016 if entry.is_local and not Options.init_local_none:
1017 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1018 if initalized is True:
1019 code.put_decref(self.result_code, self.ctype())
1020 elif initalized is None:
1021 code.put_xdecref(self.result_code, self.ctype())
1023 code.put_decref(self.result_code, self.ctype())
1024 code.putln('%s = %s;' % (self.result_code, rhs.result_as(self.ctype())))
1025 if debug_disposal_code:
1026 print("NameNode.generate_assignment_code:")
1027 print("...generating post-assignment code for %s" % rhs)
1028 rhs.generate_post_assignment_code(code)
1030 def generate_deletion_code(self, code):
1031 if self.entry is None:
1032 return # There was an error earlier
1033 if not self.entry.is_pyglobal:
1034 error(self.pos, "Deletion of local or C global name not supported")
1036 code.put_error_if_neg(self.pos,
1037 'PyObject_DelAttrString(%s, "%s")' % (
1038 Naming.module_cname,
1041 def annotate(self, code):
1042 if hasattr(self, 'is_called') and self.is_called:
1043 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1044 if self.type.is_pyobject:
1045 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1047 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1050 class BackquoteNode(ExprNode):
1057 def analyse_types(self, env):
1058 self.arg.analyse_types(env)
1059 self.arg = self.arg.coerce_to_pyobject(env)
1060 self.type = py_object_type
1063 def generate_result_code(self, code):
1065 "%s = PyObject_Repr(%s); %s" % (
1067 self.arg.py_result(),
1068 code.error_goto_if_null(self.result_code, self.pos)))
1071 class ImportNode(ExprNode):
1072 # Used as part of import statement implementation.
1073 # Implements result =
1074 # __import__(module_name, globals(), None, name_list)
1076 # module_name IdentifierStringNode dotted name of module
1077 # name_list ListNode or None list of names to be imported
1079 subexprs = ['module_name', 'name_list']
1081 def analyse_types(self, env):
1082 self.module_name.analyse_types(env)
1083 self.module_name = self.module_name.coerce_to_pyobject(env)
1085 self.name_list.analyse_types(env)
1086 self.type = py_object_type
1088 env.use_utility_code(import_utility_code)
1090 def generate_result_code(self, code):
1092 name_list_code = self.name_list.py_result()
1094 name_list_code = "0"
1096 "%s = __Pyx_Import(%s, %s); %s" % (
1098 self.module_name.py_result(),
1100 code.error_goto_if_null(self.result_code, self.pos)))
1103 class IteratorNode(ExprNode):
1104 # Used as part of for statement implementation.
1105 # Implements result = iter(sequence)
1109 subexprs = ['sequence']
1111 def analyse_types(self, env):
1112 self.sequence.analyse_types(env)
1113 self.sequence = self.sequence.coerce_to_pyobject(env)
1114 self.type = py_object_type
1117 self.counter = TempNode(self.pos, PyrexTypes.c_py_ssize_t_type, env)
1118 self.counter.allocate_temp(env)
1120 def release_temp(self, env):
1121 env.release_temp(self.result_code)
1122 self.counter.release_temp(env)
1124 def generate_result_code(self, code):
1126 "if (PyList_CheckExact(%s)) { %s = 0; %s = %s; Py_INCREF(%s); }" % (
1127 self.sequence.py_result(),
1128 self.counter.result_code,
1130 self.sequence.py_result(),
1132 code.putln("else { %s = PyObject_GetIter(%s); %s }" % (
1134 self.sequence.py_result(),
1135 code.error_goto_if_null(self.result_code, self.pos)))
1138 class NextNode(AtomicExprNode):
1139 # Used as part of for statement implementation.
1140 # Implements result = iterator.next()
1141 # Created during analyse_types phase.
1142 # The iterator is not owned by this node.
1146 def __init__(self, iterator, env):
1147 self.pos = iterator.pos
1148 self.iterator = iterator
1149 self.type = py_object_type
1152 def generate_result_code(self, code):
1154 "if (PyList_CheckExact(%s)) { if (%s >= PyList_GET_SIZE(%s)) break; %s = PyList_GET_ITEM(%s, %s++); Py_INCREF(%s); }" % (
1155 self.iterator.py_result(),
1156 self.iterator.counter.result_code,
1157 self.iterator.py_result(),
1159 self.iterator.py_result(),
1160 self.iterator.counter.result_code,
1162 code.putln("else {")
1164 "%s = PyIter_Next(%s);" % (
1166 self.iterator.py_result()))
1170 code.error_goto_if_PyErr(self.pos)
1171 code.putln("break;")
1176 class ExcValueNode(AtomicExprNode):
1177 # Node created during analyse_types phase
1178 # of an ExceptClauseNode to fetch the current
1181 def __init__(self, pos, env, var):
1182 ExprNode.__init__(self, pos)
1183 self.type = py_object_type
1186 def calculate_result_code(self):
1189 def generate_result_code(self, code):
1193 class TempNode(AtomicExprNode):
1194 # Node created during analyse_types phase
1195 # of some nodes to hold a temporary value.
1197 def __init__(self, pos, type, env):
1198 ExprNode.__init__(self, pos)
1200 if type.is_pyobject:
1201 self.result_ctype = py_object_type
1204 def analyse_types(self, env):
1207 def generate_result_code(self, code):
1211 class PyTempNode(TempNode):
1212 # TempNode holding a Python value.
1214 def __init__(self, pos, env):
1215 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1218 #-------------------------------------------------------------------
1222 #-------------------------------------------------------------------
1224 class IndexNode(ExprNode):
1225 # Sequence indexing.
1230 subexprs = ['base', 'index', 'py_index']
1232 def compile_time_value(self, denv):
1233 base = self.base.compile_time_value(denv)
1234 index = self.index.compile_time_value(denv)
1237 except Exception, e:
1238 self.compile_time_value_error(e)
1240 def is_ephemeral(self):
1241 return self.base.is_ephemeral()
1243 def analyse_target_declaration(self, env):
1246 def analyse_types(self, env):
1247 self.base.analyse_types(env)
1248 self.index.analyse_types(env)
1249 if self.base.type.is_pyobject:
1250 if self.index.type.is_int:
1251 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1252 self.py_index = CloneNode(self.index).coerce_to_pyobject(env)
1254 self.index = self.index.coerce_to_pyobject(env)
1255 self.py_index = CloneNode(self.index)
1256 self.type = py_object_type
1259 self.py_index = CloneNode(self.index) # so that it exists for subexpr processing
1260 if self.base.type.is_ptr or self.base.type.is_array:
1261 self.type = self.base.type.base_type
1264 "Attempting to index non-array type '%s'" %
1266 self.type = PyrexTypes.error_type
1267 if self.index.type.is_pyobject:
1268 self.index = self.index.coerce_to(
1269 PyrexTypes.c_py_ssize_t_type, env)
1270 if not self.index.type.is_int:
1272 "Invalid index type '%s'" %
1275 def check_const_addr(self):
1276 self.base.check_const_addr()
1277 self.index.check_const()
1279 def is_lvalue(self):
1282 def calculate_result_code(self):
1283 return "(%s[%s])" % (
1284 self.base.result_code, self.index.result_code)
1286 def generate_subexpr_evaluation_code(self, code):
1287 # do not evaluate self.py_index in case we don't need it
1288 self.base.generate_evaluation_code(code)
1289 self.index.generate_evaluation_code(code)
1291 def generate_subexpr_disposal_code(self, code):
1292 # if we used self.py_index, it will be disposed of manually
1293 self.base.generate_disposal_code(code)
1294 self.index.generate_disposal_code(code)
1296 def generate_result_code(self, code):
1297 if self.type.is_pyobject:
1298 if self.index.type.is_int:
1299 code.putln("if (PyList_CheckExact(%s) && 0 <= %s && %s < PyList_GET_SIZE(%s)) {" % (
1300 self.base.py_result(),
1301 self.index.result_code,
1302 self.index.result_code,
1303 self.base.py_result()))
1304 code.putln("%s = PyList_GET_ITEM(%s, %s); Py_INCREF(%s);" % (
1306 self.base.py_result(),
1307 self.index.result_code,
1309 code.putln("} else if (PyTuple_CheckExact(%s) && 0 <= %s && %s < PyTuple_GET_SIZE(%s)) {" % (
1310 self.base.py_result(),
1311 self.index.result_code,
1312 self.index.result_code,
1313 self.base.py_result()))
1314 code.putln("%s = PyTuple_GET_ITEM(%s, %s); Py_INCREF(%s);" % (
1316 self.base.py_result(),
1317 self.index.result_code,
1319 code.putln("} else {")
1320 self.generate_generic_code_result(code)
1323 self.generate_generic_code_result(code)
1325 def generate_generic_code_result(self, code):
1326 self.py_index.generate_result_code(code)
1328 "%s = PyObject_GetItem(%s, %s); %s" % (
1330 self.base.py_result(),
1331 self.py_index.py_result(),
1332 code.error_goto_if_null(self.result_code, self.pos)))
1334 self.py_index.generate_disposal_code(code)
1336 def generate_assignment_code(self, rhs, code):
1337 self.generate_subexpr_evaluation_code(code)
1338 if self.type.is_pyobject:
1339 if self.index.type.is_int:
1340 code.putln("if (PyList_CheckExact(%s) && 0 <= %s && %s < PyList_GET_SIZE(%s)) {" % (
1341 self.base.py_result(),
1342 self.index.result_code,
1343 self.index.result_code,
1344 self.base.py_result()))
1345 code.putln("Py_DECREF(PyList_GET_ITEM(%s, %s)); Py_INCREF(%s);" % (
1346 self.base.py_result(),
1347 self.index.result_code,
1349 code.putln("PyList_SET_ITEM(%s, %s, %s);" % (
1350 self.base.py_result(),
1351 self.index.result_code,
1353 code.putln("} else {")
1354 self.generate_generic_assignment_code(rhs, code)
1357 self.generate_generic_assignment_code(rhs, code)
1361 self.result_code, rhs.result_code))
1362 self.generate_subexpr_disposal_code(code)
1363 rhs.generate_disposal_code(code)
1365 def generate_generic_assignment_code(self, rhs, code):
1366 self.py_index.generate_result_code(code)
1367 code.put_error_if_neg(self.pos,
1368 "PyObject_SetItem(%s, %s, %s)" % (
1369 self.base.py_result(),
1370 self.py_index.py_result(),
1373 self.py_index.generate_disposal_code(code)
1375 def generate_deletion_code(self, code):
1376 self.generate_subexpr_evaluation_code(code)
1377 self.py_index.generate_evaluation_code(code)
1378 code.put_error_if_neg(self.pos,
1379 "PyObject_DelItem(%s, %s)" % (
1380 self.base.py_result(),
1381 self.py_index.py_result()))
1382 self.generate_subexpr_disposal_code(code)
1383 self.py_index.generate_disposal_code(code)
1386 class SliceIndexNode(ExprNode):
1387 # 2-element slice indexing
1390 # start ExprNode or None
1391 # stop ExprNode or None
1393 subexprs = ['base', 'start', 'stop']
1395 def compile_time_value(self, denv):
1396 base = self.base.compile_time_value(denv)
1397 start = self.start.compile_time_value(denv)
1398 stop = self.stop.compile_time_value(denv)
1400 return base[start:stop]
1401 except Exception, e:
1402 self.compile_time_value_error(e)
1404 def analyse_target_declaration(self, env):
1407 def analyse_types(self, env):
1408 self.base.analyse_types(env)
1410 self.start.analyse_types(env)
1412 self.stop.analyse_types(env)
1413 self.base = self.base.coerce_to_pyobject(env)
1414 c_int = PyrexTypes.c_py_ssize_t_type
1416 self.start = self.start.coerce_to(c_int, env)
1418 self.stop = self.stop.coerce_to(c_int, env)
1419 self.type = py_object_type
1422 def generate_result_code(self, code):
1424 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1426 self.base.py_result(),
1429 code.error_goto_if_null(self.result_code, self.pos)))
1431 def generate_assignment_code(self, rhs, code):
1432 self.generate_subexpr_evaluation_code(code)
1433 code.put_error_if_neg(self.pos,
1434 "PySequence_SetSlice(%s, %s, %s, %s)" % (
1435 self.base.py_result(),
1439 self.generate_subexpr_disposal_code(code)
1440 rhs.generate_disposal_code(code)
1442 def generate_deletion_code(self, code):
1443 self.generate_subexpr_evaluation_code(code)
1444 code.put_error_if_neg(self.pos,
1445 "PySequence_DelSlice(%s, %s, %s)" % (
1446 self.base.py_result(),
1449 self.generate_subexpr_disposal_code(code)
1451 def start_code(self):
1453 return self.start.result_code
1457 def stop_code(self):
1459 return self.stop.result_code
1461 return "PY_SSIZE_T_MAX"
1463 def calculate_result_code(self):
1464 # self.result_code is not used, but this method must exist
1468 class SliceNode(ExprNode):
1469 # start:stop:step in subscript list
1475 def compile_time_value(self, denv):
1476 start = self.start.compile_time_value(denv)
1477 stop = self.stop.compile_time_value(denv)
1478 step = step.step.compile_time_value(denv)
1480 return slice(start, stop, step)
1481 except Exception, e:
1482 self.compile_time_value_error(e)
1484 subexprs = ['start', 'stop', 'step']
1486 def analyse_types(self, env):
1487 self.start.analyse_types(env)
1488 self.stop.analyse_types(env)
1489 self.step.analyse_types(env)
1490 self.start = self.start.coerce_to_pyobject(env)
1491 self.stop = self.stop.coerce_to_pyobject(env)
1492 self.step = self.step.coerce_to_pyobject(env)
1493 self.type = py_object_type
1496 def generate_result_code(self, code):
1498 "%s = PySlice_New(%s, %s, %s); %s" % (
1500 self.start.py_result(),
1501 self.stop.py_result(),
1502 self.step.py_result(),
1503 code.error_goto_if_null(self.result_code, self.pos)))
1505 class SimpleCallNode(ExprNode):
1506 # Function call without keyword, * or ** args.
1510 # arg_tuple ExprNode or None used internally
1511 # self ExprNode or None used internally
1512 # coerced_self ExprNode or None used internally
1513 # wrapper_call bool used internally
1515 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
1520 wrapper_call = False
1522 def compile_time_value(self, denv):
1523 function = self.function.compile_time_value(denv)
1524 args = [arg.compile_time_value(denv) for arg in self.args]
1526 return function(*args)
1527 except Exception, e:
1528 self.compile_time_value_error(e)
1530 def analyse_types(self, env):
1531 function = self.function
1532 function.is_called = 1
1533 self.function.analyse_types(env)
1534 if function.is_attribute and function.is_py_attr and \
1535 function.attribute == "append" and len(self.args) == 1:
1536 # L.append(x) is almost always applied to a list
1537 self.py_func = self.function
1538 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
1539 self.function.analyse_types(env)
1540 self.self = self.py_func.obj
1541 function.obj = CloneNode(self.self)
1542 env.use_utility_code(append_utility_code)
1543 if function.is_attribute and function.entry and function.entry.is_cmethod:
1544 # Take ownership of the object from which the attribute
1545 # was obtained, because we need to pass it as 'self'.
1546 self.self = function.obj
1547 function.obj = CloneNode(self.self)
1548 func_type = self.function_type()
1549 if func_type.is_pyobject:
1550 self.arg_tuple = TupleNode(self.pos, args = self.args)
1551 self.arg_tuple.analyse_types(env)
1553 self.type = py_object_type
1556 for arg in self.args:
1557 arg.analyse_types(env)
1558 if self.self and func_type.args:
1559 # Coerce 'self' to the type expected by the method.
1560 expected_type = func_type.args[0].type
1561 self.coerced_self = CloneNode(self.self).coerce_to(
1563 # Insert coerced 'self' argument into argument list.
1564 self.args.insert(0, self.coerced_self)
1565 self.analyse_c_function_call(env)
1567 def function_type(self):
1568 # Return the type of the function being called, coercing a function
1569 # pointer to a function if necessary.
1570 func_type = self.function.type
1571 if func_type.is_ptr:
1572 func_type = func_type.base_type
1575 def analyse_c_function_call(self, env):
1576 func_type = self.function_type()
1577 # Check function type
1578 if not func_type.is_cfunction:
1579 if not func_type.is_error:
1580 error(self.pos, "Calling non-function type '%s'" %
1582 self.type = PyrexTypes.error_type
1583 self.result_code = "<error>"
1586 max_nargs = len(func_type.args)
1587 expected_nargs = max_nargs - func_type.optional_arg_count
1588 actual_nargs = len(self.args)
1589 if actual_nargs < expected_nargs \
1590 or (not func_type.has_varargs and actual_nargs > max_nargs):
1591 expected_str = str(expected_nargs)
1592 if func_type.has_varargs:
1593 expected_str = "at least " + expected_str
1594 elif func_type.optional_arg_count:
1595 if actual_nargs < max_nargs:
1596 expected_str = "at least " + expected_str
1598 expected_str = "at most " + str(max_nargs)
1600 "Call with wrong number of arguments (expected %s, got %s)"
1601 % (expected_str, actual_nargs))
1603 self.type = PyrexTypes.error_type
1604 self.result_code = "<error>"
1607 for i in range(min(max_nargs, actual_nargs)):
1608 formal_type = func_type.args[i].type
1609 self.args[i] = self.args[i].coerce_to(formal_type, env)
1610 for i in range(max_nargs, actual_nargs):
1611 if self.args[i].type.is_pyobject:
1612 error(self.args[i].pos,
1613 "Python object cannot be passed as a varargs parameter")
1614 # Calc result type and code fragment
1615 self.type = func_type.return_type
1616 if self.type.is_pyobject \
1617 or func_type.exception_value is not None \
1618 or func_type.exception_check:
1620 if self.type.is_pyobject:
1621 self.result_ctype = py_object_type
1622 # C++ exception handler
1623 if func_type.exception_check == '+':
1624 if func_type.exception_value is None:
1625 env.use_utility_code(cpp_exception_utility_code)
1627 def calculate_result_code(self):
1628 return self.c_call_code()
1630 def c_call_code(self):
1631 func_type = self.function_type()
1632 if self.args is None or not func_type.is_cfunction:
1634 formal_args = func_type.args
1636 args = zip(formal_args, self.args)
1637 max_nargs = len(func_type.args)
1638 expected_nargs = max_nargs - func_type.optional_arg_count
1639 actual_nargs = len(self.args)
1640 for formal_arg, actual_arg in args[:expected_nargs]:
1641 arg_code = actual_arg.result_as(formal_arg.type)
1642 arg_list_code.append(arg_code)
1644 if func_type.optional_arg_count:
1645 if expected_nargs == actual_nargs:
1646 optional_args = 'NULL'
1648 optional_arg_code = [str(actual_nargs - expected_nargs)]
1649 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
1650 arg_code = actual_arg.result_as(formal_arg.type)
1651 optional_arg_code.append(arg_code)
1652 # for formal_arg in formal_args[actual_nargs:max_nargs]:
1653 # optional_arg_code.append(formal_arg.type.cast_code('0'))
1654 optional_arg_struct = '{%s}' % ','.join(optional_arg_code)
1655 optional_args = PyrexTypes.c_void_ptr_type.cast_code(
1656 '&' + func_type.op_arg_struct.base_type.cast_code(optional_arg_struct))
1657 arg_list_code.append(optional_args)
1659 for actual_arg in self.args[len(formal_args):]:
1660 arg_list_code.append(actual_arg.result_code)
1661 result = "%s(%s)" % (self.function.result_code,
1662 join(arg_list_code, ", "))
1663 if self.wrapper_call or \
1664 self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
1665 result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
1668 def generate_result_code(self, code):
1669 func_type = self.function_type()
1670 if func_type.is_pyobject:
1671 arg_code = self.arg_tuple.py_result()
1673 "%s = PyObject_Call(%s, %s, NULL); %s" % (
1675 self.function.py_result(),
1677 code.error_goto_if_null(self.result_code, self.pos)))
1678 elif func_type.is_cfunction:
1680 if self.type.is_pyobject:
1681 exc_checks.append("!%s" % self.result_code)
1683 exc_val = func_type.exception_value
1684 exc_check = func_type.exception_check
1685 if exc_val is not None:
1686 exc_checks.append("%s == %s" % (self.result_code, exc_val))
1688 exc_checks.append("PyErr_Occurred()")
1689 if self.is_temp or exc_checks:
1690 rhs = self.c_call_code()
1691 if self.result_code:
1692 lhs = "%s = " % self.result_code
1693 if self.is_temp and self.type.is_pyobject:
1694 #return_type = self.type # func_type.return_type
1695 #print "SimpleCallNode.generate_result_code: casting", rhs, \
1696 # "from", return_type, "to pyobject" ###
1697 rhs = typecast(py_object_type, self.type, rhs)
1700 if func_type.exception_check == '+':
1701 if func_type.exception_value is None:
1702 raise_py_exception = "__Pyx_CppExn2PyErr()"
1703 elif func_type.exception_value.type.is_pyobject:
1704 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
1706 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
1708 "try {%s%s;} catch(...) {%s; %s}" % (
1712 code.error_goto(self.pos)))
1718 code.error_goto_if(" && ".join(exc_checks), self.pos)))
1720 class GeneralCallNode(ExprNode):
1721 # General Python function call, including keyword,
1722 # * and ** arguments.
1725 # positional_args ExprNode Tuple of positional arguments
1726 # keyword_args ExprNode or None Dict of keyword arguments
1727 # starstar_arg ExprNode or None Dict of extra keyword args
1729 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
1731 def compile_time_value(self, denv):
1732 function = self.function.compile_time_value(denv)
1733 positional_args = self.positional_args.compile_time_value(denv)
1734 keyword_args = self.keyword_args.compile_time_value(denv)
1735 starstar_arg = self.starstar_arg.compile_time_value(denv)
1737 keyword_args.update(starstar_arg)
1738 return function(*positional_args, **keyword_args)
1739 except Exception, e:
1740 self.compile_time_value_error(e)
1742 def analyse_types(self, env):
1743 self.function.analyse_types(env)
1744 self.positional_args.analyse_types(env)
1745 if self.keyword_args:
1746 self.keyword_args.analyse_types(env)
1747 if self.starstar_arg:
1748 self.starstar_arg.analyse_types(env)
1749 self.function = self.function.coerce_to_pyobject(env)
1750 self.positional_args = \
1751 self.positional_args.coerce_to_pyobject(env)
1752 if self.starstar_arg:
1753 self.starstar_arg = \
1754 self.starstar_arg.coerce_to_pyobject(env)
1755 self.type = py_object_type
1758 def generate_result_code(self, code):
1759 if self.keyword_args and self.starstar_arg:
1760 code.put_error_if_neg(self.pos,
1761 "PyDict_Update(%s, %s)" % (
1762 self.keyword_args.py_result(),
1763 self.starstar_arg.py_result()))
1764 keyword_code = self.keyword_args.py_result()
1765 elif self.keyword_args:
1766 keyword_code = self.keyword_args.py_result()
1767 elif self.starstar_arg:
1768 keyword_code = self.starstar_arg.py_result()
1771 if not keyword_code:
1772 call_code = "PyObject_Call(%s, %s, NULL)" % (
1773 self.function.py_result(),
1774 self.positional_args.py_result())
1776 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
1777 self.function.py_result(),
1778 self.positional_args.py_result(),
1784 code.error_goto_if_null(self.result_code, self.pos)))
1787 class AsTupleNode(ExprNode):
1788 # Convert argument to tuple. Used for normalising
1789 # the * argument of a function call.
1795 def compile_time_value(self, denv):
1796 arg = self.arg.compile_time_value(denv)
1799 except Exception, e:
1800 self.compile_time_value_error(e)
1802 def analyse_types(self, env):
1803 self.arg.analyse_types(env)
1804 self.arg = self.arg.coerce_to_pyobject(env)
1805 self.type = py_object_type
1808 def generate_result_code(self, code):
1810 "%s = PySequence_Tuple(%s); %s" % (
1812 self.arg.py_result(),
1813 code.error_goto_if_null(self.result_code, self.pos)))
1816 class AttributeNode(ExprNode):
1824 # is_py_attr boolean Is a Python getattr operation
1825 # member string C name of struct member
1826 # is_called boolean Function call is being done on result
1827 # entry Entry Symbol table entry of attribute
1828 # interned_attr_cname string C name of interned attribute name
1833 type = PyrexTypes.error_type
1838 def coerce_to(self, dst_type, env):
1839 # If coercing to a generic pyobject and this is a cpdef function
1840 # we can create the corresponding attribute
1841 if dst_type is py_object_type:
1843 if entry and entry.is_cfunction and entry.as_variable:
1844 # must be a cpdef function
1846 self.entry = entry.as_variable
1847 self.analyse_as_python_attribute(env)
1849 return ExprNode.coerce_to(self, dst_type, env)
1851 def compile_time_value(self, denv):
1852 attr = self.attribute
1853 if attr.beginswith("__") and attr.endswith("__"):
1854 self.error("Invalid attribute name '%s' in compile-time expression"
1857 obj = self.arg.compile_time_value(denv)
1859 return getattr(obj, attr)
1860 except Exception, e:
1861 self.compile_time_value_error(e)
1863 def analyse_target_declaration(self, env):
1866 def analyse_target_types(self, env):
1867 self.analyse_types(env, target = 1)
1869 def analyse_types(self, env, target = 0):
1870 if self.analyse_as_cimported_attribute(env, target):
1872 if not target and self.analyse_as_unbound_cmethod(env):
1874 self.analyse_as_ordinary_attribute(env, target)
1876 def analyse_as_cimported_attribute(self, env, target):
1877 # Try to interpret this as a reference to an imported
1878 # C const, type, var or function. If successful, mutates
1879 # this node into a NameNode and returns 1, otherwise
1881 module_scope = self.obj.analyse_as_module(env)
1883 entry = module_scope.lookup_here(self.attribute)
1885 entry.is_cglobal or entry.is_cfunction
1886 or entry.is_type or entry.is_const):
1887 self.mutate_into_name_node(env, entry, target)
1891 def analyse_as_unbound_cmethod(self, env):
1892 # Try to interpret this as a reference to an unbound
1893 # C method of an extension type. If successful, mutates
1894 # this node into a NameNode and returns 1, otherwise
1896 type = self.obj.analyse_as_extension_type(env)
1898 entry = type.scope.lookup_here(self.attribute)
1899 if entry and entry.is_cmethod:
1900 # Create a temporary entry describing the C method
1901 # as an ordinary function.
1902 ubcm_entry = Symtab.Entry(entry.name,
1903 "%s->%s" % (type.vtabptr_cname, entry.cname),
1905 ubcm_entry.is_cfunction = 1
1906 ubcm_entry.func_cname = entry.func_cname
1907 ubcm_entry.is_unbound_cmethod = 1
1908 self.mutate_into_name_node(env, ubcm_entry, None)
1912 def analyse_as_extension_type(self, env):
1913 # Try to interpret this as a reference to an extension type
1914 # in a cimported module. Returns the extension type, or None.
1915 module_scope = self.obj.analyse_as_module(env)
1917 entry = module_scope.lookup_here(self.attribute)
1918 if entry and entry.is_type and entry.type.is_extension_type:
1922 def analyse_as_module(self, env):
1923 # Try to interpret this as a reference to a cimported module
1924 # in another cimported module. Returns the module scope, or None.
1925 module_scope = self.obj.analyse_as_module(env)
1927 entry = module_scope.lookup_here(self.attribute)
1928 if entry and entry.as_module:
1929 return entry.as_module
1932 def mutate_into_name_node(self, env, entry, target):
1933 # Mutate this node into a NameNode and complete the
1934 # analyse_types phase.
1935 self.__class__ = NameNode
1936 self.name = self.attribute
1941 NameNode.analyse_target_types(self, env)
1943 NameNode.analyse_rvalue_entry(self, env)
1945 def analyse_as_ordinary_attribute(self, env, target):
1946 self.obj.analyse_types(env)
1947 self.analyse_attribute(env)
1948 if self.entry and self.entry.is_cmethod and not self.is_called:
1949 # error(self.pos, "C method can only be called")
1951 ## Reference to C array turns into pointer to first element.
1952 #while self.type.is_array:
1953 # self.type = self.type.element_ptr_type()
1957 self.result_ctype = py_object_type
1959 def analyse_attribute(self, env):
1960 # Look up attribute and set self.type and self.member.
1962 self.member = self.attribute
1963 if self.obj.type.is_string:
1964 self.obj = self.obj.coerce_to_pyobject(env)
1965 obj_type = self.obj.type
1966 if obj_type.is_ptr or obj_type.is_array:
1967 obj_type = obj_type.base_type
1969 elif obj_type.is_extension_type:
1973 if obj_type.has_attributes:
1975 if obj_type.attributes_known():
1976 entry = obj_type.scope.lookup_here(self.attribute)
1977 if entry and entry.is_member:
1981 "Cannot select attribute of incomplete type '%s'"
1983 obj_type = PyrexTypes.error_type
1986 if obj_type.is_extension_type and entry.name == "__weakref__":
1987 error(self.pos, "Illegal use of special attribute __weakref__")
1988 # methods need the normal attribute lookup
1989 # because they do not have struct entries
1990 if entry.is_variable or entry.is_cmethod:
1991 self.type = entry.type
1992 self.member = entry.cname
1995 # If it's not a variable or C method, it must be a Python
1996 # method of an extension type, so we treat it like a Python
1999 # If we get here, the base object is not a struct/union/extension
2000 # type, or it is an extension type and the attribute is either not
2001 # declared or is declared as a Python method. Treat it as a Python
2002 # attribute reference.
2003 self.analyse_as_python_attribute(env)
2005 def analyse_as_python_attribute(self, env):
2006 obj_type = self.obj.type
2007 self.member = self.attribute
2008 if obj_type.is_pyobject:
2009 self.type = py_object_type
2011 self.interned_attr_cname = env.intern_identifier(self.attribute)
2013 if not obj_type.is_error:
2015 "Object of type '%s' has no attribute '%s'" %
2016 (obj_type, self.attribute))
2018 def is_simple(self):
2020 return self.result_in_temp() or self.obj.is_simple()
2022 return NameNode.is_simple(self)
2024 def is_lvalue(self):
2028 return NameNode.is_lvalue(self)
2030 def is_ephemeral(self):
2032 return self.obj.is_ephemeral()
2034 return NameNode.is_ephemeral(self)
2036 def calculate_result_code(self):
2037 #print "AttributeNode.calculate_result_code:", self.member ###
2038 #print "...obj node =", self.obj, "code", self.obj.result_code ###
2039 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2041 obj_code = obj.result_as(obj.type)
2042 #print "...obj_code =", obj_code ###
2043 if self.entry and self.entry.is_cmethod:
2044 if obj.type.is_extension_type:
2045 return "((struct %s *)%s%s%s)->%s" % (
2046 obj.type.vtabstruct_cname, obj_code, self.op,
2047 obj.type.vtabslot_cname, self.member)
2051 return "%s%s%s" % (obj_code, self.op, self.member)
2053 def generate_result_code(self, code):
2056 '%s = PyObject_GetAttr(%s, %s); %s' % (
2058 self.obj.py_result(),
2059 self.interned_attr_cname,
2060 code.error_goto_if_null(self.result_code, self.pos)))
2062 def generate_assignment_code(self, rhs, code):
2063 self.obj.generate_evaluation_code(code)
2065 code.put_error_if_neg(self.pos,
2066 'PyObject_SetAttr(%s, %s, %s)' % (
2067 self.obj.py_result(),
2068 self.interned_attr_cname,
2070 rhs.generate_disposal_code(code)
2072 select_code = self.result_code
2073 if self.type.is_pyobject:
2074 rhs.make_owned_reference(code)
2075 code.put_decref(select_code, self.ctype())
2079 rhs.result_as(self.ctype())))
2081 rhs.generate_post_assignment_code(code)
2082 self.obj.generate_disposal_code(code)
2084 def generate_deletion_code(self, code):
2085 self.obj.generate_evaluation_code(code)
2087 code.put_error_if_neg(self.pos,
2088 'PyObject_DelAttr(%s, %s)' % (
2089 self.obj.py_result(),
2090 self.interned_attr_cname))
2092 error(self.pos, "Cannot delete C attribute of extension type")
2093 self.obj.generate_disposal_code(code)
2095 def annotate(self, code):
2097 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2099 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2101 #-------------------------------------------------------------------
2105 #-------------------------------------------------------------------
2107 class SequenceNode(ExprNode):
2108 # Base class for list and tuple constructor nodes.
2109 # Contains common code for performing sequence unpacking.
2113 # unpacked_items [ExprNode] or None
2114 # coerced_unpacked_items [ExprNode] or None
2118 is_sequence_constructor = 1
2119 unpacked_items = None
2121 def compile_time_value_list(self, denv):
2122 return [arg.compile_time_value(denv) for arg in self.args]
2124 def analyse_target_declaration(self, env):
2125 for arg in self.args:
2126 arg.analyse_target_declaration(env)
2128 def analyse_types(self, env):
2129 for i in range(len(self.args)):
2131 arg.analyse_types(env)
2132 self.args[i] = arg.coerce_to_pyobject(env)
2133 self.type = py_object_type
2136 def analyse_target_types(self, env):
2137 self.iterator = PyTempNode(self.pos, env)
2138 self.unpacked_items = []
2139 self.coerced_unpacked_items = []
2140 for arg in self.args:
2141 arg.analyse_target_types(env)
2142 unpacked_item = PyTempNode(self.pos, env)
2143 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2144 self.unpacked_items.append(unpacked_item)
2145 self.coerced_unpacked_items.append(coerced_unpacked_item)
2146 self.type = py_object_type
2147 env.use_utility_code(unpacking_utility_code)
2149 def allocate_target_temps(self, env, rhs):
2150 self.iterator.allocate_temps(env)
2151 for arg, node in zip(self.args, self.coerced_unpacked_items):
2152 node.allocate_temps(env)
2153 arg.allocate_target_temps(env, node)
2154 #arg.release_target_temp(env)
2155 #node.release_temp(env)
2157 rhs.release_temp(env)
2158 self.iterator.release_temp(env)
2160 # def release_target_temp(self, env):
2161 # #for arg in self.args:
2162 # # arg.release_target_temp(env)
2163 # #for node in self.coerced_unpacked_items:
2164 # # node.release_temp(env)
2165 # self.iterator.release_temp(env)
2167 def generate_result_code(self, code):
2168 self.generate_operation_code(code)
2170 def generate_assignment_code(self, rhs, code):
2172 "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
2176 code.putln("PyObject* tuple = %s;" % rhs.py_result())
2177 for i in range(len(self.args)):
2178 item = self.unpacked_items[i]
2180 "%s = PyTuple_GET_ITEM(tuple, %s);" % (
2183 code.put_incref(item.result_code, item.ctype())
2184 value_node = self.coerced_unpacked_items[i]
2185 value_node.generate_evaluation_code(code)
2186 self.args[i].generate_assignment_code(value_node, code)
2188 rhs.generate_disposal_code(code)
2190 code.putln("else {")
2193 "%s = PyObject_GetIter(%s); %s" % (
2194 self.iterator.result_code,
2196 code.error_goto_if_null(self.iterator.result_code, self.pos)))
2197 rhs.generate_disposal_code(code)
2198 for i in range(len(self.args)):
2199 item = self.unpacked_items[i]
2200 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
2201 self.iterator.py_result(), i)
2205 typecast(item.ctype(), py_object_type, unpack_code),
2206 code.error_goto_if_null(item.result_code, self.pos)))
2207 value_node = self.coerced_unpacked_items[i]
2208 value_node.generate_evaluation_code(code)
2209 self.args[i].generate_assignment_code(value_node, code)
2210 code.put_error_if_neg(self.pos,
2211 "__Pyx_EndUnpack(%s)" % (
2212 self.iterator.py_result()))
2213 if debug_disposal_code:
2214 print("UnpackNode.generate_assignment_code:")
2215 print("...generating disposal code for %s" % self.iterator)
2216 self.iterator.generate_disposal_code(code)
2220 def annotate(self, code):
2221 for arg in self.args:
2223 if self.unpacked_items:
2224 for arg in self.unpacked_items:
2226 for arg in self.coerced_unpacked_items:
2230 class TupleNode(SequenceNode):
2231 # Tuple constructor.
2233 def analyse_types(self, env):
2234 if len(self.args) == 0:
2238 SequenceNode.analyse_types(self, env)
2239 self.type = tuple_type
2241 def calculate_result_code(self):
2242 if len(self.args) > 0:
2243 error(self.pos, "Positive length tuples must be constructed.")
2245 return Naming.empty_tuple
2247 def compile_time_value(self, denv):
2248 values = self.compile_time_value_list(denv)
2250 return tuple(values)
2251 except Exception, e:
2252 self.compile_time_value_error(e)
2254 def generate_operation_code(self, code):
2255 if len(self.args) == 0:
2256 # result_code is Naming.empty_tuple
2259 "%s = PyTuple_New(%s); %s" % (
2262 code.error_goto_if_null(self.result_code, self.pos)))
2263 for i in range(len(self.args)):
2265 if not arg.result_in_temp():
2266 code.put_incref(arg.result_code, arg.ctype())
2268 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2273 def generate_subexpr_disposal_code(self, code):
2274 # We call generate_post_assignment_code here instead
2275 # of generate_disposal_code, because values were stored
2276 # in the tuple using a reference-stealing operation.
2277 for arg in self.args:
2278 arg.generate_post_assignment_code(code)
2281 class ListNode(SequenceNode):
2284 def analyse_types(self, env):
2285 SequenceNode.analyse_types(self, env)
2286 self.type = list_type
2288 def compile_time_value(self, denv):
2289 return self.compile_time_value_list(denv)
2291 def generate_operation_code(self, code):
2292 code.putln("%s = PyList_New(%s); %s" %
2295 code.error_goto_if_null(self.result_code, self.pos)))
2296 for i in range(len(self.args)):
2298 #if not arg.is_temp:
2299 if not arg.result_in_temp():
2300 code.put_incref(arg.result_code, arg.ctype())
2301 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
2306 def generate_subexpr_disposal_code(self, code):
2307 # We call generate_post_assignment_code here instead
2308 # of generate_disposal_code, because values were stored
2309 # in the list using a reference-stealing operation.
2310 for arg in self.args:
2311 arg.generate_post_assignment_code(code)
2314 class ListComprehensionNode(SequenceNode):
2317 is_sequence_constructor = 0 # not unpackable
2319 def analyse_types(self, env):
2320 self.type = list_type
2322 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
2324 def allocate_temps(self, env, result = None):
2325 if debug_temp_alloc:
2326 print("%s Allocating temps" % self)
2327 self.allocate_temp(env, result)
2328 self.loop.analyse_declarations(env)
2329 self.loop.analyse_expressions(env)
2331 def generate_operation_code(self, code):
2332 code.putln("%s = PyList_New(%s); %s" %
2335 code.error_goto_if_null(self.result_code, self.pos)))
2336 self.loop.generate_execution_code(code)
2338 def annotate(self, code):
2339 self.loop.annotate(code)
2342 class ListComprehensionAppendNode(ExprNode):
2346 def analyse_types(self, env):
2347 self.expr.analyse_types(env)
2348 if self.expr.type != py_object_type:
2349 self.expr = self.expr.coerce_to_pyobject(env)
2350 self.type = PyrexTypes.c_int_type
2353 def generate_result_code(self, code):
2354 code.putln("%s = PyList_Append(%s, %s); %s" %
2356 self.target.result_code,
2357 self.expr.result_code,
2358 code.error_goto_if(self.result_code, self.pos)))
2361 class DictNode(ExprNode):
2362 # Dictionary constructor.
2364 # key_value_pairs [DictItemNode]
2366 subexprs = ['key_value_pairs']
2368 def compile_time_value(self, denv):
2369 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
2370 for item in self.key_value_pairs]
2373 except Exception, e:
2374 self.compile_time_value_error(e)
2376 def analyse_types(self, env):
2377 for item in self.key_value_pairs:
2378 item.analyse_types(env)
2379 self.type = dict_type
2382 def allocate_temps(self, env, result = None):
2383 # Custom method used here because key-value
2384 # pairs are evaluated and used one at a time.
2385 self.allocate_temp(env, result)
2386 for item in self.key_value_pairs:
2387 item.key.allocate_temps(env)
2388 item.value.allocate_temps(env)
2389 item.key.release_temp(env)
2390 item.value.release_temp(env)
2392 def generate_evaluation_code(self, code):
2393 # Custom method used here because key-value
2394 # pairs are evaluated and used one at a time.
2396 "%s = PyDict_New(); %s" % (
2398 code.error_goto_if_null(self.result_code, self.pos)))
2399 for item in self.key_value_pairs:
2400 item.generate_evaluation_code(code)
2401 code.put_error_if_neg(self.pos,
2402 "PyDict_SetItem(%s, %s, %s)" % (
2404 item.key.py_result(),
2405 item.value.py_result()))
2406 item.generate_disposal_code(code)
2408 def annotate(self, code):
2409 for item in self.key_value_pairs:
2412 class DictItemNode(ExprNode):
2413 # Represents a single item in a DictNode
2417 subexprs = ['key', 'value']
2419 def analyse_types(self, env):
2420 self.key.analyse_types(env)
2421 self.value.analyse_types(env)
2422 self.key = self.key.coerce_to_pyobject(env)
2423 self.value = self.value.coerce_to_pyobject(env)
2425 def generate_evaluation_code(self, code):
2426 self.key.generate_evaluation_code(code)
2427 self.value.generate_evaluation_code(code)
2429 def generate_disposal_code(self, code):
2430 self.key.generate_disposal_code(code)
2431 self.value.generate_disposal_code(code)
2434 class ClassNode(ExprNode):
2435 # Helper class used in the implementation of Python
2436 # class definitions. Constructs a class object given
2437 # a name, tuple of bases and class dictionary.
2439 # name EncodedString Name of the class
2440 # cname string Class name as a Python string
2441 # bases ExprNode Base class tuple
2442 # dict ExprNode Class dict (not owned by this node)
2443 # doc ExprNode or None Doc string
2444 # module_name string Name of defining module
2446 subexprs = ['bases', 'doc']
2448 def analyse_types(self, env):
2449 self.cname = env.intern_identifier(self.name)
2450 self.bases.analyse_types(env)
2452 self.doc.analyse_types(env)
2453 self.doc = self.doc.coerce_to_pyobject(env)
2454 self.module_name = env.global_scope().qualified_name
2455 self.type = py_object_type
2457 env.use_utility_code(create_class_utility_code);
2459 def generate_result_code(self, code):
2461 code.put_error_if_neg(self.pos,
2462 'PyDict_SetItemString(%s, "__doc__", %s)' % (
2463 self.dict.py_result(),
2464 self.doc.py_result()))
2466 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
2468 self.bases.py_result(),
2469 self.dict.py_result(),
2472 code.error_goto_if_null(self.result_code, self.pos)))
2475 class UnboundMethodNode(ExprNode):
2476 # Helper class used in the implementation of Python
2477 # class definitions. Constructs an unbound method
2478 # object from a class and a function.
2480 # class_cname string C var holding the class object
2481 # function ExprNode Function object
2483 subexprs = ['function']
2485 def analyse_types(self, env):
2486 self.function.analyse_types(env)
2487 self.type = py_object_type
2490 def generate_result_code(self, code):
2492 "%s = PyMethod_New(%s, 0, %s); %s" % (
2494 self.function.py_result(),
2496 code.error_goto_if_null(self.result_code, self.pos)))
2499 class PyCFunctionNode(AtomicExprNode):
2500 # Helper class used in the implementation of Python
2501 # class definitions. Constructs a PyCFunction object
2502 # from a PyMethodDef struct.
2504 # pymethdef_cname string PyMethodDef structure
2506 def analyse_types(self, env):
2507 self.type = py_object_type
2510 def generate_result_code(self, code):
2512 "%s = PyCFunction_New(&%s, 0); %s" % (
2514 self.pymethdef_cname,
2515 code.error_goto_if_null(self.result_code, self.pos)))
2517 #-------------------------------------------------------------------
2519 # Unary operator nodes
2521 #-------------------------------------------------------------------
2523 compile_time_unary_operators = {
2524 'not': operator.not_,
2530 class UnopNode(ExprNode):
2534 # Processing during analyse_expressions phase:
2536 # analyse_c_operation
2537 # Called when the operand is not a pyobject.
2538 # - Check operand type and coerce if needed.
2539 # - Determine result type and result code fragment.
2540 # - Allocate temporary for result if needed.
2542 subexprs = ['operand']
2544 def compile_time_value(self, denv):
2545 func = compile_time_unary_operators.get(self.operator)
2548 "Unary '%s' not supported in compile-time expression"
2550 operand = self.operand.compile_time_value(denv)
2552 return func(operand)
2553 except Exception, e:
2554 self.compile_time_value_error(e)
2556 def analyse_types(self, env):
2557 self.operand.analyse_types(env)
2558 if self.is_py_operation():
2559 self.coerce_operand_to_pyobject(env)
2560 self.type = py_object_type
2563 self.analyse_c_operation(env)
2565 def check_const(self):
2566 self.operand.check_const()
2568 def is_py_operation(self):
2569 return self.operand.type.is_pyobject
2571 def coerce_operand_to_pyobject(self, env):
2572 self.operand = self.operand.coerce_to_pyobject(env)
2574 def generate_result_code(self, code):
2575 if self.operand.type.is_pyobject:
2576 self.generate_py_operation_code(code)
2579 self.generate_c_operation_code(code)
2581 def generate_py_operation_code(self, code):
2582 function = self.py_operation_function()
2584 "%s = %s(%s); %s" % (
2587 self.operand.py_result(),
2588 code.error_goto_if_null(self.result_code, self.pos)))
2590 def type_error(self):
2591 if not self.operand.type.is_error:
2592 error(self.pos, "Invalid operand type for '%s' (%s)" %
2593 (self.operator, self.operand.type))
2594 self.type = PyrexTypes.error_type
2597 class NotNode(ExprNode):
2602 def compile_time_value(self, denv):
2603 operand = self.operand.compile_time_value(denv)
2606 except Exception, e:
2607 self.compile_time_value_error(e)
2609 subexprs = ['operand']
2611 def analyse_types(self, env):
2612 self.operand.analyse_types(env)
2613 self.operand = self.operand.coerce_to_boolean(env)
2614 self.type = PyrexTypes.c_bint_type
2616 def calculate_result_code(self):
2617 return "(!%s)" % self.operand.result_code
2619 def generate_result_code(self, code):
2623 class UnaryPlusNode(UnopNode):
2624 # unary '+' operator
2628 def analyse_c_operation(self, env):
2629 self.type = self.operand.type
2631 def py_operation_function(self):
2632 return "PyNumber_Positive"
2634 def calculate_result_code(self):
2635 return self.operand.result_code
2638 class UnaryMinusNode(UnopNode):
2639 # unary '-' operator
2643 def analyse_c_operation(self, env):
2644 if self.operand.type.is_numeric:
2645 self.type = self.operand.type
2649 def py_operation_function(self):
2650 return "PyNumber_Negative"
2652 def calculate_result_code(self):
2653 return "(-%s)" % self.operand.result_code
2656 class TildeNode(UnopNode):
2657 # unary '~' operator
2659 def analyse_c_operation(self, env):
2660 if self.operand.type.is_int:
2661 self.type = self.operand.type
2665 def py_operation_function(self):
2666 return "PyNumber_Invert"
2668 def calculate_result_code(self):
2669 return "(~%s)" % self.operand.result_code
2672 class AmpersandNode(ExprNode):
2673 # The C address-of operator.
2677 subexprs = ['operand']
2679 def analyse_types(self, env):
2680 self.operand.analyse_types(env)
2681 argtype = self.operand.type
2682 if not (argtype.is_cfunction or self.operand.is_lvalue()):
2683 self.error("Taking address of non-lvalue")
2685 if argtype.is_pyobject:
2686 self.error("Cannot take address of Python variable")
2688 self.type = PyrexTypes.c_ptr_type(argtype)
2690 def check_const(self):
2691 self.operand.check_const_addr()
2693 def error(self, mess):
2694 error(self.pos, mess)
2695 self.type = PyrexTypes.error_type
2696 self.result_code = "<error>"
2698 def calculate_result_code(self):
2699 return "(&%s)" % self.operand.result_code
2701 def generate_result_code(self, code):
2705 unop_node_classes = {
2707 "-": UnaryMinusNode,
2711 def unop_node(pos, operator, operand):
2712 # Construct unnop node of appropriate class for
2714 if isinstance(operand, IntNode) and operator == '-':
2715 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
2716 elif isinstance(operand, UnopNode) and operand.operator == operator:
2717 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
2718 return unop_node_classes[operator](pos,
2719 operator = operator,
2723 class TypecastNode(ExprNode):
2726 # base_type CBaseTypeNode
2727 # declarator CDeclaratorNode
2730 subexprs = ['operand']
2732 def analyse_types(self, env):
2733 base_type = self.base_type.analyse(env)
2734 _, self.type = self.declarator.analyse(base_type, env)
2735 self.operand.analyse_types(env)
2736 to_py = self.type.is_pyobject
2737 from_py = self.operand.type.is_pyobject
2738 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
2739 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
2740 if to_py and not from_py:
2741 self.result_ctype = py_object_type
2743 if self.operand.type.to_py_function:
2744 self.operand = self.operand.coerce_to_pyobject(env)
2746 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
2747 elif from_py and not to_py:
2748 if self.type.from_py_function:
2749 self.operand = self.operand.coerce_to(self.type, env)
2751 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
2752 elif from_py and to_py:
2753 if self.typecheck and self.type.is_extension_type:
2754 self.operand = PyTypeTestNode(self.operand, self.type, env)
2756 def check_const(self):
2757 self.operand.check_const()
2759 def calculate_result_code(self):
2761 result_code = self.type.cast_code(opnd.result_code)
2764 def result_as(self, type):
2765 if self.type.is_pyobject and not self.is_temp:
2766 # Optimise away some unnecessary casting
2767 return self.operand.result_as(type)
2769 return ExprNode.result_as(self, type)
2771 def generate_result_code(self, code):
2774 "%s = (PyObject *)%s;" % (
2776 self.operand.result_code))
2777 code.put_incref(self.result_code, self.ctype())
2780 class SizeofNode(ExprNode):
2781 # Abstract base class for sizeof(x) expression nodes.
2783 def check_const(self):
2786 def generate_result_code(self, code):
2790 class SizeofTypeNode(SizeofNode):
2791 # C sizeof function applied to a type
2793 # base_type CBaseTypeNode
2794 # declarator CDeclaratorNode
2798 def analyse_types(self, env):
2799 base_type = self.base_type.analyse(env)
2800 _, arg_type = self.declarator.analyse(base_type, env)
2801 self.arg_type = arg_type
2802 if arg_type.is_pyobject and not arg_type.is_extension_type:
2803 error(self.pos, "Cannot take sizeof Python object")
2804 elif arg_type.is_void:
2805 error(self.pos, "Cannot take sizeof void")
2806 elif not arg_type.is_complete():
2807 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
2808 self.type = PyrexTypes.c_int_type
2810 def calculate_result_code(self):
2811 if self.arg_type.is_extension_type:
2812 # the size of the pointer is boring
2813 # we want the size of the actual struct
2814 arg_code = self.arg_type.declaration_code("", deref=1)
2816 arg_code = self.arg_type.declaration_code("")
2817 return "(sizeof(%s))" % arg_code
2820 class SizeofVarNode(SizeofNode):
2821 # C sizeof function applied to a variable
2825 subexprs = ['operand']
2827 def analyse_types(self, env):
2828 self.operand.analyse_types(env)
2829 self.type = PyrexTypes.c_int_type
2831 def calculate_result_code(self):
2832 return "(sizeof(%s))" % self.operand.result_code
2834 def generate_result_code(self, code):
2838 #-------------------------------------------------------------------
2840 # Binary operator nodes
2842 #-------------------------------------------------------------------
2844 def _not_in(x, seq):
2847 compile_time_binary_operators = {
2855 'is_not': operator.is_not,
2859 '//': operator.floordiv,
2860 '<<': operator.lshift,
2865 '>>': operator.rshift,
2867 #'/': operator.truediv,
2869 'in': operator.contains,
2873 def get_compile_time_binop(node):
2874 func = compile_time_binary_operators.get(node.operator)
2877 "Binary '%s' not supported in compile-time expression"
2881 class BinopNode(ExprNode):
2886 # Processing during analyse_expressions phase:
2888 # analyse_c_operation
2889 # Called when neither operand is a pyobject.
2890 # - Check operand types and coerce if needed.
2891 # - Determine result type and result code fragment.
2892 # - Allocate temporary for result if needed.
2894 subexprs = ['operand1', 'operand2']
2896 def compile_time_value(self, denv):
2897 func = get_compile_time_binop(self)
2898 operand1 = self.operand1.compile_time_value(denv)
2899 operand2 = self.operand2.compile_time_value(denv)
2901 return func(operand1, operand2)
2902 except Exception, e:
2903 self.compile_time_value_error(e)
2905 def analyse_types(self, env):
2906 self.operand1.analyse_types(env)
2907 self.operand2.analyse_types(env)
2908 if self.is_py_operation():
2909 self.coerce_operands_to_pyobjects(env)
2910 self.type = py_object_type
2912 if Options.incref_local_binop and self.operand1.type.is_pyobject:
2913 self.operand1 = self.operand1.coerce_to_temp(env)
2915 self.analyse_c_operation(env)
2917 def is_py_operation(self):
2918 return (self.operand1.type.is_pyobject
2919 or self.operand2.type.is_pyobject)
2921 def coerce_operands_to_pyobjects(self, env):
2922 self.operand1 = self.operand1.coerce_to_pyobject(env)
2923 self.operand2 = self.operand2.coerce_to_pyobject(env)
2925 def check_const(self):
2926 self.operand1.check_const()
2927 self.operand2.check_const()
2929 def generate_result_code(self, code):
2930 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
2931 if self.operand1.type.is_pyobject:
2932 function = self.py_operation_function()
2933 if function == "PyNumber_Power":
2934 extra_args = ", Py_None"
2938 "%s = %s(%s, %s%s); %s" % (
2941 self.operand1.py_result(),
2942 self.operand2.py_result(),
2944 code.error_goto_if_null(self.result_code, self.pos)))
2947 self.generate_c_operation_code(code)
2949 def type_error(self):
2950 if not (self.operand1.type.is_error
2951 or self.operand2.type.is_error):
2952 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
2953 (self.operator, self.operand1.type,
2954 self.operand2.type))
2955 self.type = PyrexTypes.error_type
2958 class NumBinopNode(BinopNode):
2959 # Binary operation taking numeric arguments.
2961 def analyse_c_operation(self, env):
2962 type1 = self.operand1.type
2963 type2 = self.operand2.type
2964 if self.operator == "**" and type1.is_int and type2.is_int:
2965 error(self.pos, "** with two C int types is ambiguous")
2966 self.type = error_type
2968 self.type = self.compute_c_result_type(type1, type2)
2972 def compute_c_result_type(self, type1, type2):
2973 if self.c_types_okay(type1, type2):
2974 return PyrexTypes.widest_numeric_type(type1, type2)
2978 def c_types_okay(self, type1, type2):
2979 #print "NumBinopNode.c_types_okay:", type1, type2 ###
2980 return (type1.is_numeric or type1.is_enum) \
2981 and (type2.is_numeric or type2.is_enum)
2983 def calculate_result_code(self):
2984 return "(%s %s %s)" % (
2985 self.operand1.result_code,
2987 self.operand2.result_code)
2989 def py_operation_function(self):
2990 return self.py_functions[self.operator]
2994 "^": "PyNumber_Xor",
2995 "&": "PyNumber_And",
2996 "<<": "PyNumber_Lshift",
2997 ">>": "PyNumber_Rshift",
2998 "+": "PyNumber_Add",
2999 "-": "PyNumber_Subtract",
3000 "*": "PyNumber_Multiply",
3001 "/": "PyNumber_Divide",
3002 "//": "PyNumber_FloorDivide",
3003 "%": "PyNumber_Remainder",
3004 "**": "PyNumber_Power"
3008 class IntBinopNode(NumBinopNode):
3009 # Binary operation taking integer arguments.
3011 def c_types_okay(self, type1, type2):
3012 #print "IntBinopNode.c_types_okay:", type1, type2 ###
3013 return (type1.is_int or type1.is_enum) \
3014 and (type2.is_int or type2.is_enum)
3017 class AddNode(NumBinopNode):
3020 def is_py_operation(self):
3021 if self.operand1.type.is_string \
3022 and self.operand2.type.is_string:
3025 return NumBinopNode.is_py_operation(self)
3027 def compute_c_result_type(self, type1, type2):
3028 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
3029 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3031 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
3034 return NumBinopNode.compute_c_result_type(
3038 class SubNode(NumBinopNode):
3041 def compute_c_result_type(self, type1, type2):
3042 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3044 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
3045 return PyrexTypes.c_int_type
3047 return NumBinopNode.compute_c_result_type(
3051 class MulNode(NumBinopNode):
3054 def is_py_operation(self):
3055 type1 = self.operand1.type
3056 type2 = self.operand2.type
3057 if (type1.is_string and type2.is_int) \
3058 or (type2.is_string and type1.is_int):
3061 return NumBinopNode.is_py_operation(self)
3064 class FloorDivNode(NumBinopNode):
3067 def calculate_result_code(self):
3068 return "(%s %s %s)" % (
3069 self.operand1.result_code,
3070 "/", # c division is by default floor-div
3071 self.operand2.result_code)
3074 class ModNode(IntBinopNode):
3077 def is_py_operation(self):
3078 return (self.operand1.type.is_string
3079 or self.operand2.type.is_string
3080 or IntBinopNode.is_py_operation(self))
3083 class PowNode(NumBinopNode):
3086 def analyse_types(self, env):
3087 env.pow_function_used = 1
3088 NumBinopNode.analyse_types(self, env)
3090 def compute_c_result_type(self, type1, type2):
3091 if self.c_types_okay(type1, type2):
3092 return PyrexTypes.c_double_type
3096 def c_types_okay(self, type1, type2):
3097 return type1.is_float or type2.is_float
3099 def type_error(self):
3100 if not (self.operand1.type.is_error or self.operand2.type.is_error):
3101 if self.operand1.type.is_int and self.operand2.type.is_int:
3102 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
3103 (self.operator, self.operand1.type, self.operand2.type))
3105 NumBinopNode.type_error(self)
3106 self.type = PyrexTypes.error_type
3108 def calculate_result_code(self):
3109 return "pow(%s, %s)" % (
3110 self.operand1.result_code, self.operand2.result_code)
3113 class BoolBinopNode(ExprNode):
3114 # Short-circuiting boolean operation.
3119 # temp_bool ExprNode used internally
3123 subexprs = ['operand1', 'operand2', 'temp_bool']
3125 def compile_time_value(self, denv):
3126 if self.operator == 'and':
3127 return self.operand1.compile_time_value(denv) \
3128 and self.operand2.compile_time_value(denv)
3130 return self.operand1.compile_time_value(denv) \
3131 or self.operand2.compile_time_value(denv)
3133 def analyse_types(self, env):
3134 self.operand1.analyse_types(env)
3135 self.operand2.analyse_types(env)
3136 if self.operand1.type.is_pyobject or \
3137 self.operand2.type.is_pyobject:
3138 self.operand1 = self.operand1.coerce_to_pyobject(env)
3139 self.operand2 = self.operand2.coerce_to_pyobject(env)
3140 self.temp_bool = TempNode(self.pos, PyrexTypes.c_bint_type, env)
3141 self.type = py_object_type
3143 self.operand1 = self.operand1.coerce_to_boolean(env)
3144 self.operand2 = self.operand2.coerce_to_boolean(env)
3145 self.type = PyrexTypes.c_bint_type
3146 # For what we're about to do, it's vital that
3147 # both operands be temp nodes.
3148 self.operand1 = self.operand1.coerce_to_temp(env) #CTT
3149 self.operand2 = self.operand2.coerce_to_temp(env)
3150 # coerce_to_simple does not seem to be sufficient
3151 #self.operand1 = self.operand1.coerce_to_simple(env)
3152 #self.operand2 = self.operand2.coerce_to_simple(env)
3155 def allocate_temps(self, env, result_code = None):
3156 # We don't need both operands at the same time, and
3157 # one of the operands will also be our result. So we
3158 # use an allocation strategy here which results in
3159 # this node and both its operands sharing the same
3160 # result variable. This allows us to avoid some
3161 # assignments and increfs/decrefs that would otherwise
3163 self.allocate_temp(env, result_code)
3164 self.operand1.allocate_temps(env, self.result_code)
3166 self.temp_bool.allocate_temp(env)
3167 self.temp_bool.release_temp(env)
3168 self.operand2.allocate_temps(env, self.result_code)
3169 # We haven't called release_temp on either operand,
3170 # because although they are temp nodes, they don't own
3171 # their result variable. And because they are temp
3172 # nodes, any temps in their subnodes will have been
3173 # released before their allocate_temps returned.
3174 # Therefore, they contain no temp vars that need to
3177 def check_const(self):
3178 self.operand1.check_const()
3179 self.operand2.check_const()
3181 def calculate_result_code(self):
3182 return "(%s %s %s)" % (
3183 self.operand1.result_code,
3184 self.py_to_c_op[self.operator],
3185 self.operand2.result_code)
3187 py_to_c_op = {'and': "&&", 'or': "||"}
3189 def generate_evaluation_code(self, code):
3190 self.operand1.generate_evaluation_code(code)
3191 test_result = self.generate_operand1_test(code)
3192 if self.operator == 'and':
3200 self.operand1.generate_disposal_code(code)
3201 self.operand2.generate_evaluation_code(code)
3205 def generate_operand1_test(self, code):
3206 # Generate code to test the truth of the first operand.
3207 if self.type.is_pyobject:
3208 test_result = self.temp_bool.result_code
3210 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3212 self.operand1.py_result(),
3213 code.error_goto_if_neg(test_result, self.pos)))
3215 test_result = self.operand1.result_code
3219 class CondExprNode(ExprNode):
3220 # Short-circuiting conditional expression.
3224 # false_val ExprNode
3228 subexprs = ['test', 'true_val', 'false_val']
3230 def analyse_types(self, env):
3231 self.test.analyse_types(env)
3232 self.test = self.test.coerce_to_boolean(env)
3233 self.true_val.analyse_types(env)
3234 self.false_val.analyse_types(env)
3235 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
3236 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
3237 self.true_val = self.true_val.coerce_to(self.type, env)
3238 self.false_val = self.false_val.coerce_to(self.type, env)
3239 # must be tmp variables so they can share a result
3240 self.true_val = self.true_val.coerce_to_temp(env)
3241 self.false_val = self.false_val.coerce_to_temp(env)
3243 if self.type == PyrexTypes.error_type:
3246 def allocate_temps(self, env, result_code = None):
3247 # We only ever evaluate one side, and this is
3248 # after evaluating the truth value, so we may
3249 # use an allocation strategy here which results in
3250 # this node and both its operands sharing the same
3251 # result variable. This allows us to avoid some
3252 # assignments and increfs/decrefs that would otherwise
3254 self.allocate_temp(env, result_code)
3255 self.test.allocate_temps(env, result_code)
3256 self.true_val.allocate_temps(env, self.result_code)
3257 self.false_val.allocate_temps(env, self.result_code)
3258 # We haven't called release_temp on either value,
3259 # because although they are temp nodes, they don't own
3260 # their result variable. And because they are temp
3261 # nodes, any temps in their subnodes will have been
3262 # released before their allocate_temps returned.
3263 # Therefore, they contain no temp vars that need to
3266 def compute_result_type(self, type1, type2):
3269 elif type1.is_numeric and type2.is_numeric:
3270 return PyrexTypes.widest_numeric_type(type1, type2)
3271 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
3273 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
3275 elif type1.is_pyobject or type2.is_pyobject:
3276 return py_object_type
3277 elif type1.assignable_from(type2):
3279 elif type2.assignable_from(type1):
3282 return PyrexTypes.error_type
3284 def type_error(self):
3285 if not (self.true_val.type.is_error or self.false_val.type.is_error):
3286 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
3287 (self.true_val.type, self.false_val.type))
3288 self.type = PyrexTypes.error_type
3290 def check_const(self):
3291 self.test.check_const()
3292 self.true_val.check_const()
3293 self.false_val.check_const()
3295 def generate_evaluation_code(self, code):
3296 self.test.generate_evaluation_code(code)
3297 code.putln("if (%s) {" % self.test.result_code )
3298 self.true_val.generate_evaluation_code(code)
3299 code.putln("} else {")
3300 self.false_val.generate_evaluation_code(code)
3302 self.test.generate_disposal_code(code)
3304 richcmp_constants = {
3315 # Mixin class containing code common to PrimaryCmpNodes
3316 # and CascadedCmpNodes.
3318 def cascaded_compile_time_value(self, operand1, denv):
3319 func = get_compile_time_binop(self)
3320 operand2 = self.operand2.compile_time_value(denv)
3322 result = func(operand1, operand2)
3323 except Exception, e:
3324 self.compile_time_value_error(e)
3327 cascade = self.cascade
3329 result = result and cascade.compile_time_value(operand2, denv)
3332 def is_python_comparison(self):
3333 return (self.has_python_operands()
3334 or (self.cascade and self.cascade.is_python_comparison())
3335 or self.operator in ('in', 'not_in'))
3337 def is_python_result(self):
3338 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
3339 or (self.cascade and self.cascade.is_python_result()))
3341 def check_types(self, env, operand1, op, operand2):
3342 if not self.types_okay(operand1, op, operand2):
3343 error(self.pos, "Invalid types for '%s' (%s, %s)" %
3344 (self.operator, operand1.type, operand2.type))
3346 def types_okay(self, operand1, op, operand2):
3347 type1 = operand1.type
3348 type2 = operand2.type
3349 if type1.is_error or type2.is_error:
3351 if type1.is_pyobject: # type2 will be, too
3353 elif type1.is_ptr or type1.is_array:
3354 return type1.is_null_ptr or type2.is_null_ptr \
3355 or ((type2.is_ptr or type2.is_array)
3356 and type1.base_type.same_as(type2.base_type))
3357 elif ((type1.is_numeric and type2.is_numeric
3358 or type1.is_enum and (type1 is type2 or type2.is_int)
3359 or type1.is_int and type2.is_enum)
3360 and op not in ('is', 'is_not')):
3363 return type1.is_cfunction and type1.is_cfunction and type1 == type2
3365 def generate_operation_code(self, code, result_code,
3366 operand1, op , operand2):
3367 if self.type is PyrexTypes.py_object_type:
3368 coerce_result = "__Pyx_PyBool_FromLong"
3371 if 'not' in op: negation = "!"
3373 if op == 'in' or op == 'not_in':
3375 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
3379 operand2.py_result(),
3380 operand1.py_result(),
3381 code.error_goto_if_neg(result_code, self.pos)))
3382 elif (operand1.type.is_pyobject
3383 and op not in ('is', 'is_not')):
3384 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
3386 operand1.py_result(),
3387 operand2.py_result(),
3388 richcmp_constants[op],
3389 code.error_goto_if_null(result_code, self.pos)))
3391 type1 = operand1.type
3392 type2 = operand2.type
3393 if (type1.is_extension_type or type2.is_extension_type) \
3394 and not type1.same_as(type2):
3395 common_type = py_object_type
3396 elif type1.is_numeric:
3397 common_type = PyrexTypes.widest_numeric_type(type1, type2)
3400 code1 = operand1.result_as(common_type)
3401 code2 = operand2.result_as(common_type)
3402 code.putln("%s = %s(%s %s %s);" % (
3406 self.c_operator(op),
3409 def c_operator(self, op):
3412 elif op == 'is_not':
3418 class PrimaryCmpNode(ExprNode, CmpNode):
3419 # Non-cascaded comparison or first comparison of
3420 # a cascaded sequence.
3425 # cascade CascadedCmpNode
3427 # We don't use the subexprs mechanism, because
3428 # things here are too complicated for it to handle.
3429 # Instead, we override all the framework methods
3432 child_attrs = ['operand1', 'operand2', 'cascade']
3436 def compile_time_value(self, denv):
3437 operand1 = self.operand1.compile_time_value(denv)
3438 return self.cascaded_compile_time_value(operand1, denv)
3440 def analyse_types(self, env):
3441 self.operand1.analyse_types(env)
3442 self.operand2.analyse_types(env)
3444 self.cascade.analyse_types(env, self.operand2)
3445 self.is_pycmp = self.is_python_comparison()
3447 self.coerce_operands_to_pyobjects(env)
3448 if self.has_int_operands():
3449 self.coerce_chars_to_ints(env)
3451 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
3452 self.operand2 = self.operand2.coerce_to_simple(env)
3453 self.cascade.coerce_cascaded_operands_to_temp(env)
3454 self.check_operand_types(env)
3455 if self.is_python_result():
3456 self.type = PyrexTypes.py_object_type
3458 self.type = PyrexTypes.c_bint_type
3461 cdr.type = self.type
3463 if self.is_pycmp or self.cascade:
3466 def check_operand_types(self, env):
3467 self.check_types(env,
3468 self.operand1, self.operator, self.operand2)
3470 self.cascade.check_operand_types(env, self.operand2)
3472 def has_python_operands(self):
3473 return (self.operand1.type.is_pyobject
3474 or self.operand2.type.is_pyobject)
3476 def coerce_operands_to_pyobjects(self, env):
3477 self.operand1 = self.operand1.coerce_to_pyobject(env)
3478 self.operand2 = self.operand2.coerce_to_pyobject(env)
3480 self.cascade.coerce_operands_to_pyobjects(env)
3482 def has_int_operands(self):
3483 return (self.operand1.type.is_int or self.operand2.type.is_int) \
3484 or (self.cascade and self.cascade.has_int_operands())
3486 def coerce_chars_to_ints(self, env):
3487 if self.operand1.type.is_string:
3488 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
3489 if self.operand2.type.is_string:
3490 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3492 self.cascade.coerce_chars_to_ints(env)
3494 def allocate_subexpr_temps(self, env):
3495 self.operand1.allocate_temps(env)
3496 self.operand2.allocate_temps(env)
3498 self.cascade.allocate_subexpr_temps(env)
3500 def release_subexpr_temps(self, env):
3501 self.operand1.release_temp(env)
3502 self.operand2.release_temp(env)
3504 self.cascade.release_subexpr_temps(env)
3506 def check_const(self):
3507 self.operand1.check_const()
3508 self.operand2.check_const()
3512 def calculate_result_code(self):
3513 return "(%s %s %s)" % (
3514 self.operand1.result_code,
3515 self.c_operator(self.operator),
3516 self.operand2.result_code)
3518 def generate_evaluation_code(self, code):
3519 self.operand1.generate_evaluation_code(code)
3520 self.operand2.generate_evaluation_code(code)
3522 self.generate_operation_code(code, self.result_code,
3523 self.operand1, self.operator, self.operand2)
3525 self.cascade.generate_evaluation_code(code,
3526 self.result_code, self.operand2)
3527 self.operand1.generate_disposal_code(code)
3528 self.operand2.generate_disposal_code(code)
3530 def generate_subexpr_disposal_code(self, code):
3531 # If this is called, it is a non-cascaded cmp,
3532 # so only need to dispose of the two main operands.
3533 self.operand1.generate_disposal_code(code)
3534 self.operand2.generate_disposal_code(code)
3536 def annotate(self, code):
3537 self.operand1.annotate(code)
3538 self.operand2.annotate(code)
3540 self.cascade.annotate(code)
3543 class CascadedCmpNode(Node, CmpNode):
3544 # A CascadedCmpNode is not a complete expression node. It
3545 # hangs off the side of another comparison node, shares
3546 # its left operand with that node, and shares its result
3547 # with the PrimaryCmpNode at the head of the chain.
3551 # cascade CascadedCmpNode
3553 child_attrs = ['operand2', 'cascade']
3557 def analyse_types(self, env, operand1):
3558 self.operand2.analyse_types(env)
3560 self.cascade.analyse_types(env, self.operand2)
3562 def check_operand_types(self, env, operand1):
3563 self.check_types(env,
3564 operand1, self.operator, self.operand2)
3566 self.cascade.check_operand_types(env, self.operand2)
3568 def has_python_operands(self):
3569 return self.operand2.type.is_pyobject
3571 def coerce_operands_to_pyobjects(self, env):
3572 self.operand2 = self.operand2.coerce_to_pyobject(env)
3574 self.cascade.coerce_operands_to_pyobjects(env)
3576 def has_int_operands(self):
3577 return self.operand2.type.is_int
3579 def coerce_chars_to_ints(self, env):
3580 if self.operand2.type.is_string:
3581 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3583 def coerce_cascaded_operands_to_temp(self, env):
3585 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
3586 self.operand2 = self.operand2.coerce_to_simple(env)
3587 self.cascade.coerce_cascaded_operands_to_temp(env)
3589 def allocate_subexpr_temps(self, env):
3590 self.operand2.allocate_temps(env)
3592 self.cascade.allocate_subexpr_temps(env)
3594 def release_subexpr_temps(self, env):
3595 self.operand2.release_temp(env)
3597 self.cascade.release_subexpr_temps(env)
3599 def generate_evaluation_code(self, code, result, operand1):
3600 if self.type.is_pyobject:
3601 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
3603 code.putln("if (%s) {" % result)
3604 self.operand2.generate_evaluation_code(code)
3605 self.generate_operation_code(code, result,
3606 operand1, self.operator, self.operand2)
3608 self.cascade.generate_evaluation_code(
3609 code, result, self.operand2)
3610 # Cascaded cmp result is always temp
3611 self.operand2.generate_disposal_code(code)
3614 def annotate(self, code):
3615 self.operand2.annotate(code)
3617 self.cascade.annotate(code)
3620 binop_node_classes = {
3621 "or": BoolBinopNode,
3622 "and": BoolBinopNode,
3637 def binop_node(pos, operator, operand1, operand2):
3638 # Construct binop node of appropriate class for
3640 return binop_node_classes[operator](pos,
3641 operator = operator,
3642 operand1 = operand1,
3643 operand2 = operand2)
3645 #-------------------------------------------------------------------
3649 # Coercion nodes are special in that they are created during
3650 # the analyse_types phase of parse tree processing.
3651 # Their __init__ methods consequently incorporate some aspects
3654 #-------------------------------------------------------------------
3656 class CoercionNode(ExprNode):
3657 # Abstract base class for coercion nodes.
3659 # arg ExprNode node being coerced
3663 def __init__(self, arg):
3667 print("%s Coercing %s" % (self, self.arg))
3669 def annotate(self, code):
3670 self.arg.annotate(code)
3671 if self.arg.type != self.type:
3672 file, line, col = self.pos
3673 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
3676 class CastNode(CoercionNode):
3677 # Wrap a node in a C type cast.
3679 def __init__(self, arg, new_type):
3680 CoercionNode.__init__(self, arg)
3681 self.type = new_type
3683 def calculate_result_code(self):
3684 return self.arg.result_as(self.type)
3686 def generate_result_code(self, code):
3687 self.arg.generate_result_code(code)
3690 class PyTypeTestNode(CoercionNode):
3691 # This node is used to check that a generic Python
3692 # object is an instance of a particular extension type.
3693 # This node borrows the result of its argument node.
3695 def __init__(self, arg, dst_type, env):
3696 # The arg is know to be a Python object, and
3697 # the dst_type is known to be an extension type.
3698 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
3699 CoercionNode.__init__(self, arg)
3700 self.type = dst_type
3701 self.result_ctype = arg.ctype()
3702 env.use_utility_code(type_test_utility_code)
3704 def analyse_types(self, env):
3707 def result_in_temp(self):
3708 return self.arg.result_in_temp()
3710 def is_ephemeral(self):
3711 return self.arg.is_ephemeral()
3713 def calculate_result_code(self):
3714 return self.arg.result_code
3716 def generate_result_code(self, code):
3717 if self.type.typeobj_is_available():
3720 self.type.type_test_code(self.arg.py_result()),
3721 code.error_goto(self.pos)))
3723 error(self.pos, "Cannot test type of extern C class "
3724 "without type object name specification")
3726 def generate_post_assignment_code(self, code):
3727 self.arg.generate_post_assignment_code(code)
3730 class CoerceToPyTypeNode(CoercionNode):
3731 # This node is used to convert a C data type
3732 # to a Python object.
3734 def __init__(self, arg, env):
3735 CoercionNode.__init__(self, arg)
3736 self.type = py_object_type
3738 if not arg.type.to_py_function:
3740 "Cannot convert '%s' to Python object" % arg.type)
3742 def generate_result_code(self, code):
3743 function = self.arg.type.to_py_function
3744 code.putln('%s = %s(%s); %s' % (
3747 self.arg.result_code,
3748 code.error_goto_if_null(self.result_code, self.pos)))
3751 class CoerceFromPyTypeNode(CoercionNode):
3752 # This node is used to convert a Python object
3755 def __init__(self, result_type, arg, env):
3756 CoercionNode.__init__(self, arg)
3757 self.type = result_type
3759 if not result_type.from_py_function:
3761 "Cannot convert Python object to '%s'" % result_type)
3762 if self.type.is_string and self.arg.is_ephemeral():
3764 "Obtaining char * from temporary Python value")
3766 def generate_result_code(self, code):
3767 function = self.type.from_py_function
3768 operand = self.arg.py_result()
3769 rhs = "%s(%s)" % (function, operand)
3770 if self.type.is_enum:
3771 rhs = typecast(self.type, c_long_type, rhs)
3772 code.putln('%s = %s; %s' % (
3775 code.error_goto_if(self.type.error_condition(self.result_code), self.pos)))
3778 class CoerceToBooleanNode(CoercionNode):
3779 # This node is used when a result needs to be used
3780 # in a boolean context.
3782 def __init__(self, arg, env):
3783 CoercionNode.__init__(self, arg)
3784 self.type = PyrexTypes.c_bint_type
3785 if arg.type.is_pyobject:
3788 def check_const(self):
3791 self.arg.check_const()
3793 def calculate_result_code(self):
3794 return "(%s != 0)" % self.arg.result_code
3796 def generate_result_code(self, code):
3797 if self.arg.type.is_pyobject:
3799 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3801 self.arg.py_result(),
3802 code.error_goto_if_neg(self.result_code, self.pos)))
3805 class CoerceToTempNode(CoercionNode):
3806 # This node is used to force the result of another node
3807 # to be stored in a temporary. It is only used if the
3808 # argument node's result is not already in a temporary.
3810 def __init__(self, arg, env):
3811 CoercionNode.__init__(self, arg)
3812 self.type = self.arg.type
3814 if self.type.is_pyobject:
3815 self.result_ctype = py_object_type
3817 def generate_result_code(self, code):
3818 #self.arg.generate_evaluation_code(code) # Already done
3819 # by generic generate_subexpr_evaluation_code!
3820 code.putln("%s = %s;" % (
3821 self.result_code, self.arg.result_as(self.ctype())))
3822 if self.type.is_pyobject:
3823 code.put_incref(self.result_code, self.ctype())
3826 class CloneNode(CoercionNode):
3827 # This node is employed when the result of another node needs
3828 # to be used multiple times. The argument node's result must
3829 # be in a temporary. This node "borrows" the result from the
3830 # argument node, and does not generate any evaluation or
3831 # disposal code for it. The original owner of the argument
3832 # node is responsible for doing those things.
3834 subexprs = [] # Arg is not considered a subexpr
3836 def __init__(self, arg):
3837 CoercionNode.__init__(self, arg)
3838 if hasattr(arg, 'type'):
3839 self.type = arg.type
3840 self.result_ctype = arg.result_ctype
3841 if hasattr(arg, 'entry'):
3842 self.entry = arg.entry
3844 def calculate_result_code(self):
3845 return self.arg.result_code
3847 def analyse_types(self, env):
3848 self.type = self.arg.type
3849 self.result_ctype = self.arg.result_ctype
3851 if hasattr(self.arg, 'entry'):
3852 self.entry = self.arg.entry
3854 #def result_as_extension_type(self):
3855 # return self.arg.result_as_extension_type()
3857 def generate_evaluation_code(self, code):
3860 def generate_result_code(self, code):
3863 def generate_disposal_code(self, code):
3866 def allocate_temps(self, env):
3867 self.result_code = self.calculate_result_code()
3869 def release_temp(self, env):
3872 #------------------------------------------------------------------------------------
3874 # Runtime support code
3876 #------------------------------------------------------------------------------------
3878 get_name_interned_utility_code = [
3880 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
3882 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
3884 result = PyObject_GetAttr(dict, name);
3886 PyErr_SetObject(PyExc_NameError, name);
3891 #------------------------------------------------------------------------------------
3893 import_utility_code = [
3895 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
3897 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
3898 PyObject *__import__ = 0;
3899 PyObject *empty_list = 0;
3900 PyObject *module = 0;
3901 PyObject *global_dict = 0;
3902 PyObject *empty_dict = 0;
3904 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
3910 empty_list = PyList_New(0);
3915 global_dict = PyModule_GetDict(%(GLOBALS)s);
3918 empty_dict = PyDict_New();
3921 module = PyObject_CallFunction(__import__, "OOOO",
3922 name, global_dict, empty_dict, list);
3924 Py_XDECREF(empty_list);
3925 Py_XDECREF(__import__);
3926 Py_XDECREF(empty_dict);
3930 "BUILTINS": Naming.builtins_cname,
3931 "GLOBALS": Naming.module_cname,
3934 #------------------------------------------------------------------------------------
3936 get_exception_utility_code = [
3938 static PyObject *__Pyx_GetExcValue(void); /*proto*/
3940 static PyObject *__Pyx_GetExcValue(void) {
3941 PyObject *type = 0, *value = 0, *tb = 0;
3942 PyObject *tmp_type, *tmp_value, *tmp_tb;
3943 PyObject *result = 0;
3944 PyThreadState *tstate = PyThreadState_Get();
3945 PyErr_Fetch(&type, &value, &tb);
3946 PyErr_NormalizeException(&type, &value, &tb);
3947 if (PyErr_Occurred())
3953 tmp_type = tstate->exc_type;
3954 tmp_value = tstate->exc_value;
3955 tmp_tb = tstate->exc_traceback;
3956 tstate->exc_type = type;
3957 tstate->exc_value = value;
3958 tstate->exc_traceback = tb;
3959 /* Make sure tstate is in a consistent state when we XDECREF
3960 these objects (XDECREF may run arbitrary code). */
3961 Py_XDECREF(tmp_type);
3962 Py_XDECREF(tmp_value);
3977 #------------------------------------------------------------------------------------
3979 unpacking_utility_code = [
3981 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
3982 static int __Pyx_EndUnpack(PyObject *); /*proto*/
3984 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
3986 if (!(item = PyIter_Next(iter))) {
3987 if (!PyErr_Occurred()) {
3988 PyErr_Format(PyExc_ValueError,
3989 #if PY_VERSION_HEX < 0x02050000
3990 "need more than %d values to unpack", (int)index);
3992 "need more than %zd values to unpack", index);
3999 static int __Pyx_EndUnpack(PyObject *iter) {
4001 if ((item = PyIter_Next(iter))) {
4003 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
4006 else if (!PyErr_Occurred())
4013 #------------------------------------------------------------------------------------
4015 type_test_utility_code = [
4017 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
4019 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
4021 PyErr_Format(PyExc_SystemError, "Missing type object");
4024 if (obj == Py_None || PyObject_TypeCheck(obj, type))
4026 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
4027 Py_TYPE(obj)->tp_name, type->tp_name);
4032 #------------------------------------------------------------------------------------
4034 create_class_utility_code = [
4036 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
4038 static PyObject *__Pyx_CreateClass(
4039 PyObject *bases, PyObject *dict, PyObject *name, char *modname)
4041 PyObject *py_modname;
4042 PyObject *result = 0;
4044 #if PY_MAJOR_VERSION < 3
4045 py_modname = PyString_FromString(modname);
4047 py_modname = PyUnicode_FromString(modname);
4051 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
4053 #if PY_MAJOR_VERSION < 3
4054 result = PyClass_New(bases, dict, name);
4056 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
4059 Py_XDECREF(py_modname);
4064 #------------------------------------------------------------------------------------
4066 cpp_exception_utility_code = [
4068 #ifndef __Pyx_CppExn2PyErr
4069 static void __Pyx_CppExn2PyErr() {
4071 if (PyErr_Occurred())
4072 ; // let the latest Python exn pass through and ignore the current one
4075 } catch (const std::out_of_range& exn) {
4076 // catch out_of_range explicitly so the proper Python exn may be raised
4077 PyErr_SetString(PyExc_IndexError, exn.what());
4078 } catch (const std::exception& exn) {
4079 PyErr_SetString(PyExc_RuntimeError, exn.what());
4083 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
4089 #------------------------------------------------------------------------------------
4091 append_utility_code = [
4093 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
4094 if (likely(PyList_CheckExact(L))) {
4095 if (PyList_Append(L, x) < 0) return NULL;
4097 return Py_None; // this is just to have an accurate signature
4100 return PyObject_CallMethod(L, "append", "(O)", x);