2 # Pyrex - Parse tree nodes for expressions
5 from string
import join
7 from Errors
import error
, InternalError
12 from Pyrex
.Debugging
import print_call_chain
13 from DebugFlags
import debug_disposal_code
, debug_temp_alloc
, \
17 # subexprs [string] Class var holding names of subexpr node attrs
18 # type PyrexType Type of the result
19 # result string C code fragment
20 # is_temp boolean Result is in a temporary variable
21 # is_sequence_constructor
22 # boolean Is a list or tuple constructor expression
24 # [ExprNode or [ExprNode or None] or None]
25 # Cached result of subexpr_nodes()
27 # The Analyse Expressions phase for expressions is split
28 # into two sub-phases:
31 # Determines the result type of the expression based
32 # on the types of its sub-expressions, and inserts
33 # coercion nodes into the expression tree where needed.
34 # Marks nodes which will need to have temporary variables
38 # Allocates temporary variables where needed, and fills
39 # in the result field of each node.
41 # ExprNode provides some convenience routines which
42 # perform both of the above phases. These should only
43 # be called from statement nodes, and only when no
44 # coercion nodes need to be added around the expression
45 # being analysed. In that case, the above two phases
46 # should be invoked separately.
48 # Framework code in ExprNode provides much of the common
49 # processing for the various phases. It makes use of the
50 # 'subexprs' class attribute of ExprNodes, which should
51 # contain a list of the names of attributes which can
52 # hold sub-nodes or sequences of sub-nodes.
54 # The framework makes use of a number of abstract methods.
55 # Their responsibilities are as follows.
57 # Declaration Analysis phase
59 # analyse_target_declaration
60 # Called during the Analyse Declarations phase to analyse
61 # the LHS of an assignment or argument of a del statement.
62 # Nodes which cannot be the LHS of an assignment need not
65 # Expression Analysis phase
68 # - Call analyse_types on all sub-expressions.
69 # - Check operand types, and wrap coercion nodes around
70 # sub-expressions where needed.
71 # - Set the type of this node.
72 # - If a temporary variable will be required for the
73 # result, set the is_temp flag of this node.
75 # analyse_target_types
76 # Called during the Analyse Types phase to analyse
77 # the LHS of an assignment or argument of a del
78 # statement. Similar responsibilities to analyse_types.
81 # - Call allocate_temps for all sub-nodes.
82 # - Call allocate_temp for this node.
83 # - If a temporary was allocated, call release_temp on
84 # all sub-expressions.
86 # A default implementation of allocate_temps is
87 # provided which uses the following abstract method:
90 # - Return a C code fragment evaluating to
91 # the result. This is only called when the
92 # result is not a temporary.
95 # - Check that this node and its subnodes form a
96 # legal constant expression. If so, do nothing,
97 # otherwise call not_const.
99 # The default implementation of check_const
100 # assumes that the expression is not constant.
103 # - Same as check_const, except check that the
104 # expression is a C lvalue whose address is
105 # constant. Otherwise, call addr_not_const.
107 # The default implementation of calc_const_addr
108 # assumes that the expression is not a constant
111 # Code Generation phase
113 # generate_evaluation_code
114 # - Call generate_evaluation_code for sub-expressions.
115 # - Perform the functions of generate_result_code
117 # - If result is temporary, call generate_disposal_code
118 # on all sub-expressions.
120 # A default implementation of generate_evaluation_code
121 # is provided which uses the following abstract method:
123 # generate_result_code
124 # - Generate any C statements necessary to calculate
125 # the result of this node from the results of its
128 # generate_assignment_code
129 # Called on the LHS of an assignment.
130 # - Call generate_evaluation_code for sub-expressions.
131 # - Generate code to perform the assignment.
132 # - If the assignment absorbed a reference, call
133 # generate_post_assignment_code on the RHS,
134 # otherwise call generate_disposal_code on it.
136 # generate_deletion_code
137 # Called on an argument of a del statement.
138 # - Call generate_evaluation_code for sub-expressions.
139 # - Generate code to perform the deletion.
140 # - Call generate_disposal_code on all sub-expressions.
142 # result_as_extension_type
143 # Normally, the results of all nodes whose type
144 # is a Python object, either generic or an extension
145 # type, are returned as a generic Python object, so
146 # that they can be passed directly to Python/C API
147 # routines. This method is called to obtain the
148 # result as the actual type of the node. It is only
149 # called when the type is known to actually be an
150 # extension type, and nodes whose result can never
151 # be an extension type need not implement it.
155 is_sequence_constructor
= 0
156 saved_subexpr_nodes
= None
158 def not_implemented(self
, method_name
):
159 print_call_chain(method_name
, "not implemented") ###
161 "%s.%s not implemented" %
162 (self
.__class
__.__name
__, method_name
))
167 def is_ephemeral(self
):
168 # An ephemeral node is one whose result is in
169 # a Python temporary and we suspect there are no
170 # other references to it. Certain operations are
171 # disallowed on such values, since they are
172 # likely to result in a dangling pointer.
173 return self
.type.is_pyobject
and self
.is_temp
175 def subexpr_nodes(self
):
176 # Extract a list of subexpression nodes based
177 # on the contents of the subexprs class attribute.
178 if self
.saved_subexpr_nodes
is None:
180 for name
in self
.subexprs
:
181 item
= getattr(self
, name
)
183 if isinstance(item
, ExprNode
):
187 self
.saved_subexpr_nodes
= nodes
188 return self
.saved_subexpr_nodes
190 # ------------- Declaration Analysis ----------------
192 def analyse_target_declaration(self
, env
):
193 error(self
.pos
, "Cannot assign to or delete this")
195 # ------------- Expression Analysis ----------------
197 def analyse_const_expression(self
, env
):
198 # Called during the analyse_declarations phase of a
199 # constant expression. Analyses the expression's type,
200 # checks whether it is a legal const expression,
201 # and determines its value.
202 self
.analyse_types(env
)
203 self
.allocate_temps(env
)
206 def analyse_expressions(self
, env
):
207 # Convenience routine performing both the Type
208 # Analysis and Temp Allocation phases for a whole
210 self
.analyse_types(env
)
211 self
.allocate_temps(env
)
213 def analyse_target_expression(self
, env
):
214 # Convenience routine performing both the Type
215 # Analysis and Temp Allocation phases for the LHS of
217 self
.analyse_target_types(env
)
218 self
.allocate_target_temps(env
)
220 def analyse_boolean_expression(self
, env
):
221 # Analyse expression and coerce to a boolean.
222 self
.analyse_types(env
)
223 bool = self
.coerce_to_boolean(env
)
224 bool.allocate_temps(env
)
227 def analyse_temp_boolean_expression(self
, env
):
228 # Analyse boolean expression and coerce result into
229 # a temporary. This is used when a branch is to be
230 # performed on the result and we won't have an
231 # opportunity to ensure disposal code is executed
232 # afterwards. By forcing the result into a temporary,
233 # we ensure that all disposal has been done by the
234 # time we get the result.
235 self
.analyse_types(env
)
236 bool = self
.coerce_to_boolean(env
)
237 temp_bool
= bool.coerce_to_temp(env
)
238 temp_bool
.allocate_temps(env
)
241 # --------------- Type Analysis ------------------
243 def analyse_as_module(self
, env
):
244 # If this node can be interpreted as a reference to a
245 # cimported module, return its scope, else None.
248 def analyse_types(self
, env
):
249 self
.not_implemented("analyse_types")
251 def analyse_target_types(self
, env
):
252 self
.analyse_types(env
)
254 def check_const(self
):
258 error(self
.pos
, "Not allowed in a constant expression")
260 def check_const_addr(self
):
261 self
.addr_not_const()
263 def addr_not_const(self
):
264 error(self
.pos
, "Address is not constant")
266 # ----------------- Result Allocation -----------------
268 def result_in_temp(self
):
269 # Return true if result is in a temporary owned by
270 # this node or one of its subexpressions. Overridden
271 # by certain nodes which can share the result of
275 def allocate_target_temps(self
, env
):
276 # Perform allocate_temps for the LHS of an assignment.
278 print self
, "Allocating target temps"
279 self
.allocate_subexpr_temps(env
)
280 self
.result
= self
.target_code()
282 def allocate_temps(self
, env
, result
= None):
283 # Allocate temporary variables for this node and
284 # all its sub-expressions. If a result is specified,
285 # this must be a temp node and the specified variable
286 # is used as the result instead of allocating a new
289 print self
, "Allocating temps"
290 self
.allocate_subexpr_temps(env
)
291 self
.allocate_temp(env
, result
)
293 self
.release_subexpr_temps(env
)
295 def allocate_subexpr_temps(self
, env
):
296 # Allocate temporary variables for all sub-expressions
299 print self
, "Allocating temps for:", self
.subexprs
300 for node
in self
.subexpr_nodes():
303 print self
, "Allocating temps for", node
304 node
.allocate_temps(env
)
306 def allocate_temp(self
, env
, result
= None):
307 # If this node requires a temporary variable for its
308 # result, allocate one, otherwise set the result to
309 # a C code fragment. If a result is specified,
310 # this must be a temp node and the specified variable
311 # is used as the result instead of allocating a new
314 print self
, "Allocating temp"
317 raise InternalError("Result forced on non-temp node")
323 type = PyrexTypes
.py_object_type
324 self
.result
= env
.allocate_temp(type)
328 print self
, "Allocated result", self
.result
329 #print_call_chain(self, "allocated temp", self.result)
331 self
.result
= self
.result_code()
333 def target_code(self
):
334 # Return code fragment for use as LHS of a C assignment.
335 return self
.result_code()
337 def result_code(self
):
338 #return "<Internal error: %s.result_code not implemented>" \
339 # % self.__class__.__name__
340 self
.not_implemented("result_code")
342 def release_target_temp(self
, env
):
343 # Release temporaries used by LHS of an assignment.
344 self
.release_subexpr_temps(env
)
346 def release_temp(self
, env
):
347 # If this node owns a temporary result, release it,
348 # otherwise release results of its sub-expressions.
351 print self
, "Releasing result", self
.result
352 #print_call_chain(self, "releasing temp", self.result)
353 env
.release_temp(self
.result
)
355 self
.release_subexpr_temps(env
)
357 def release_subexpr_temps(self
, env
):
358 # Release the results of all sub-expressions of
360 for node
in self
.subexpr_nodes():
362 node
.release_temp(env
)
364 # ---------------- Code Generation -----------------
366 def make_owned_reference(self
, code
):
367 # If result is a pyobject, make sure we own
369 #if self.type.is_pyobject and not self.is_temp:
370 if self
.type.is_pyobject
and not self
.result_in_temp():
371 code
.put_incref(self
.result
)
373 def generate_evaluation_code(self
, code
):
374 # Generate code to evaluate this node and
375 # its sub-expressions, and dispose of any
376 # temporary results of its sub-expressions.
377 self
.generate_subexpr_evaluation_code(code
)
378 self
.generate_result_code(code
)
380 self
.generate_subexpr_disposal_code(code
)
382 def generate_subexpr_evaluation_code(self
, code
):
383 for node
in self
.subexpr_nodes():
384 node
.generate_evaluation_code(code
)
386 def generate_result_code(self
, code
):
387 self
.not_implemented("generate_result_code")
389 def generate_disposal_code(self
, code
):
390 # If necessary, generate code to dispose of
391 # temporary Python reference.
393 if self
.type.is_pyobject
:
394 code
.put_decref_clear(self
.result
)
396 self
.generate_subexpr_disposal_code(code
)
398 def generate_subexpr_disposal_code(self
, code
):
399 # Generate code to dispose of temporary results
400 # of all sub-expressions.
401 for node
in self
.subexpr_nodes():
402 node
.generate_disposal_code(code
)
404 def generate_post_assignment_code(self
, code
):
405 # Same as generate_disposal_code except that
406 # assignment will have absorbed a reference to
407 # the result if it is a Python object.
409 if self
.type.is_pyobject
:
410 code
.putln("%s = 0;" % self
.result
)
412 self
.generate_subexpr_disposal_code(code
)
414 def generate_assignment_code(self
, rhs
, code
):
415 # Stub method for nodes which are not legal as
416 # the LHS of an assignment. An error will have
417 # been reported earlier.
420 def generate_deletion_code(self
, code
):
421 # Stub method for nodes that are not legal as
422 # the argument of a del statement. An error
423 # will have been reported earlier.
426 # ----------------- Coercion ----------------------
428 def coerce_to(self
, dst_type
, env
):
429 # Coerce the result so that it can be assigned to
430 # something of type dst_type. If processing is necessary,
431 # wraps this node in a coercion node and returns that.
432 # Otherwise, returns this node unchanged.
434 # This method is called during the analyse_expressions
435 # phase of the src_node's processing.
437 src_is_py_type
= src_type
.is_pyobject
438 dst_is_py_type
= dst_type
.is_pyobject
441 if not src_is_py_type
:
442 result
= CoerceToPyTypeNode(result
, env
)
443 # src and dst are now both py types
444 if not dst_type
.same_as(result
.type):
445 if dst_type
.is_extension_type
:
446 result
= PyTypeTestNode(result
, dst_type
, env
)
449 return CoerceFromPyTypeNode(dst_type
, self
, env
)
450 else: # neither src nor dst are py types
451 if not dst_type
.assignable_from(src_type
):
452 error(self
.pos
, "Cannot assign type '%s' to '%s'" %
453 (src_type
, dst_type
))
456 def coerce_to_pyobject(self
, env
):
457 return self
.coerce_to(PyrexTypes
.py_object_type
, env
)
459 def coerce_to_boolean(self
, env
):
460 # Coerce result to something acceptable as
463 if type.is_pyobject
or type.is_ptr
or type.is_float
:
464 return CoerceToBooleanNode(self
, env
)
468 "Type '%s' not acceptable as a boolean" % type)
471 def coerce_to_integer(self
, env
):
472 # If not already some C integer type, coerce to longint.
476 return self
.coerce_to(PyrexTypes
.c_long_type
, env
)
478 def coerce_to_temp(self
, env
):
479 # Ensure that the result is in a temporary.
480 if self
.result_in_temp():
483 return CoerceToTempNode(self
, env
)
485 def coerce_to_simple(self
, env
):
486 # Ensure that the result is simple.
487 # e.g. a local var, C global var, or struct member.
491 return self
.coerce_to_temp(env
)
494 # A node is simple if its result is something that can
495 # be referred to without performing any operations, e.g.
496 # a constant, local var, C global var, struct member
497 # reference, or temporary.
498 return self
.result_in_temp()
500 class AtomicExprNode(ExprNode
):
501 # Abstract base class for expression nodes which have
502 # no sub-expressions.
507 class PyConstNode(AtomicExprNode
):
508 # Abstract base class for constant Python values.
513 def analyse_types(self
, env
):
514 self
.type = PyrexTypes
.py_object_type
516 def result_code(self
):
519 def generate_result_code(self
, code
):
523 class NoneNode(PyConstNode
):
524 # The constant value None
529 class EllipsisNode(PyConstNode
):
530 # '...' in a subscript list.
532 value
= "Py_Ellipsis"
535 class ConstNode(AtomicExprNode
):
536 # Abstract base type for literal constant nodes.
538 # value string C code fragment
545 def analyse_types(self
, env
):
546 pass # Types are held in class variables
548 def check_const(self
):
551 def result_code(self
):
552 return str(self
.value
)
554 def generate_result_code(self
, code
):
558 class NullNode(ConstNode
):
559 type = PyrexTypes
.c_null_ptr_type
563 class CharNode(ConstNode
):
564 type = PyrexTypes
.c_char_type
566 def result_code(self
):
567 return "'%s'" % self
.value
570 class IntNode(ConstNode
):
571 type = PyrexTypes
.c_long_type
574 class FloatNode(ConstNode
):
575 type = PyrexTypes
.c_double_type
578 class StringNode(ConstNode
):
581 type = PyrexTypes
.c_char_ptr_type
583 def analyse_types(self
, env
):
584 self
.entry
= env
.add_string_const(self
.value
)
586 def result_code(self
):
587 return self
.entry
.cname
590 class ImagNode(AtomicExprNode
):
591 # Imaginary number literal
593 # value float imaginary part
595 def analyse_types(self
, env
):
596 self
.type = PyrexTypes
.py_object_type
599 def generate_evaluation_code(self
, code
):
601 "%s = PyComplex_FromDoubles(0.0, %s); if (!%s) %s" % (
605 code
.error_goto(self
.pos
)))
608 class NameNode(AtomicExprNode
):
609 # Reference to a local or global variable name.
611 # name string Python name of the variable
612 # entry Entry Symbol table entry
616 def analyse_as_module(self
, env
):
617 entry
= env
.lookup_here(self
.name
)
618 if entry
and entry
.as_module
:
619 return entry
.as_module
622 def analyse_target_declaration(self
, env
):
623 self
.entry
= env
.lookup_here(self
.name
)
625 self
.entry
= env
.declare_var(self
.name
,
626 PyrexTypes
.py_object_type
, self
.pos
)
628 def analyse_types(self
, env
):
629 self
.entry
= env
.lookup(self
.name
)
631 self
.entry
= env
.declare_builtin(self
.name
, self
.pos
)
632 self
.analyse_entry(env
)
634 def analyse_entry(self
, env
):
635 self
.check_identifier_kind()
636 self
.type = self
.entry
.type
637 # Reference to C array turns into pointer to first element.
638 if self
.type.is_array
:
639 self
.type = self
.type.element_ptr_type()
640 if self
.entry
.is_pyglobal
or self
.entry
.is_builtin
:
641 if not self
.type.is_pyobject
:
642 raise InternalError("Python global or builtin not a Python object")
644 env
.use_utility_code(get_name_utility_code
)
647 # If it's not a C variable, it'll be in a temp anyway.
650 def check_identifier_kind(self
):
652 if not (entry
.is_const
or entry
.is_variable
653 or entry
.is_builtin
or entry
.is_cfunction
):
654 if self
.entry
.as_variable
:
655 self
.entry
= self
.entry
.as_variable
658 "'%s' is not a constant, variable or function identifier" % self
.name
)
660 def analyse_target_types(self
, env
):
661 self
.check_identifier_kind()
663 self
.type = self
.entry
.type
665 error(self
.pos
, "Assignment to non-lvalue '%s'"
668 self
.type = PyrexTypes
.error_type
670 def calculate_target_results(self
, env
):
673 def check_const(self
):
675 if not (entry
.is_const
or entry
.is_cfunction
):
678 def check_const_addr(self
):
680 if not (entry
.is_cglobal
or entry
.is_cfunction
):
681 self
.addr_not_const()
684 return self
.entry
.is_variable
and \
685 not self
.entry
.type.is_array
and \
686 not self
.entry
.is_readonly
688 def is_ephemeral(self
):
689 # Name nodes are never ephemeral, even if the
690 # result is in a temporary.
693 def result_code(self
):
694 if self
.entry
is None:
695 return "<error>" # There was an error earlier
696 result
= self
.entry
.cname
697 if self
.type.is_extension_type
and \
698 not self
.entry
.is_declared_generic
:
699 result
= "((PyObject *)%s)" % result
702 def result_as_extension_type(self
):
703 if self
.entry
is None:
704 return "<error>" # There was an error earlier
705 #if not self.entry.is_self_arg:
706 if not self
.entry
.is_declared_generic
:
707 return self
.entry
.cname
709 return "((%s)%s)" % (
710 self
.type.declaration_code(""),
713 def generate_result_code(self
, code
):
714 if not hasattr(self
, 'entry'):
715 error(self
.pos
, "INTERNAL ERROR: NameNode has no entry attribute during code generation")
718 return # There was an error earlier
719 if entry
.is_pyglobal
or entry
.is_builtin
:
721 namespace
= Naming
.builtins_cname
722 else: # entry.is_pyglobal
723 namespace
= entry
.namespace_cname
725 '%s = __Pyx_GetName(%s, "%s"); if (!%s) %s' % (
730 code
.error_goto(self
.pos
)))
732 def generate_assignment_code(self
, rhs
, code
):
733 if self
.entry
is None:
734 return # There was an error earlier
735 if self
.entry
.is_pyglobal
:
736 namespace
= self
.entry
.namespace_cname
738 'if (PyObject_SetAttrString(%s, "%s", %s) < 0) %s' % (
742 code
.error_goto(self
.pos
)))
743 if debug_disposal_code
:
744 print "NameNode.generate_assignment_code:"
745 print "...generating disposal code for", rhs
746 rhs
.generate_disposal_code(code
)
748 if self
.type.is_pyobject
:
749 rhs
.make_owned_reference(code
)
750 code
.put_decref(self
.result
)
751 code
.putln('%s = %s;' % (self
.result
, rhs
.result
))
752 if debug_disposal_code
:
753 print "NameNode.generate_assignment_code:"
754 print "...generating post-assignment code for", rhs
755 rhs
.generate_post_assignment_code(code
)
757 def generate_deletion_code(self
, code
):
758 if self
.entry
is None:
759 return # There was an error earlier
760 if not self
.entry
.is_pyglobal
:
761 error(self
.pos
, "Deletion of local or C global name not supported")
764 'if (PyObject_DelAttrString(%s, "%s") < 0) %s' % (
767 code
.error_goto(self
.pos
)))
770 class BackquoteNode(ExprNode
):
777 def analyse_types(self
, env
):
778 self
.arg
.analyse_types(env
)
779 self
.arg
= self
.arg
.coerce_to_pyobject(env
)
780 self
.type = PyrexTypes
.py_object_type
783 def generate_result_code(self
, code
):
785 "%s = PyObject_Repr(%s); if (!%s) %s" % (
789 code
.error_goto(self
.pos
)))
792 class ImportNode(ExprNode
):
793 # Used as part of import statement implementation.
794 # Implements result =
795 # __import__(module_name, globals(), None, name_list)
797 # module_name StringNode dotted name of module
798 # name_list ListNode or None list of names to be imported
800 subexprs
= ['module_name', 'name_list']
802 def analyse_types(self
, env
):
803 self
.module_name
.analyse_types(env
)
804 self
.module_name
= self
.module_name
.coerce_to_pyobject(env
)
806 self
.name_list
.analyse_types(env
)
807 self
.type = PyrexTypes
.py_object_type
809 env
.use_utility_code(import_utility_code
)
811 def generate_result_code(self
, code
):
813 name_list_code
= self
.name_list
.result
817 "%s = __Pyx_Import(%s, %s); if (!%s) %s" % (
819 self
.module_name
.result
,
822 code
.error_goto(self
.pos
)))
825 class IteratorNode(ExprNode
):
826 # Used as part of for statement implementation.
827 # Implements result = iter(sequence)
831 subexprs
= ['sequence']
833 def analyse_types(self
, env
):
834 self
.sequence
.analyse_types(env
)
835 self
.sequence
= self
.sequence
.coerce_to_pyobject(env
)
836 self
.type = PyrexTypes
.py_object_type
839 def generate_result_code(self
, code
):
841 "%s = PyObject_GetIter(%s); if (!%s) %s" % (
843 self
.sequence
.result
,
845 code
.error_goto(self
.pos
)))
848 class NextNode(AtomicExprNode
):
849 # Used as part of for statement implementation.
850 # Implements result = iterator.next()
851 # Created during analyse_types phase.
852 # The iterator is not owned by this node.
856 def __init__(self
, iterator
, env
):
857 self
.pos
= iterator
.pos
858 self
.iterator
= iterator
859 self
.type = PyrexTypes
.py_object_type
862 def generate_result_code(self
, code
):
864 "%s = PyIter_Next(%s);" % (
866 self
.iterator
.result
))
871 "if (PyErr_Occurred()) %s" %
872 code
.error_goto(self
.pos
))
879 class ExcValueNode(AtomicExprNode
):
880 # Node created during analyse_types phase
881 # of an ExceptClauseNode to fetch the current
884 def __init__(self
, pos
, env
):
885 ExprNode
.__init
__(self
, pos
)
886 self
.type = PyrexTypes
.py_object_type
888 env
.use_utility_code(get_exception_utility_code
)
890 def generate_result_code(self
, code
):
892 "%s = __Pyx_GetExcValue(); if (!%s) %s" % (
895 code
.error_goto(self
.pos
)))
898 class TempNode(AtomicExprNode
):
899 # Node created during analyse_types phase
900 # of some nodes to hold a temporary value.
902 def __init__(self
, pos
, type, env
):
903 ExprNode
.__init
__(self
, pos
)
907 def generate_result_code(self
, code
):
911 class PyTempNode(TempNode
):
912 # TempNode holding a Python value.
914 def __init__(self
, pos
, env
):
915 TempNode
.__init
__(self
, pos
, PyrexTypes
.py_object_type
, env
)
918 #-------------------------------------------------------------------
922 #-------------------------------------------------------------------
924 class IndexNode(ExprNode
):
930 subexprs
= ['base', 'index']
932 def analyse_target_declaration(self
, env
):
935 def analyse_types(self
, env
):
936 self
.base
.analyse_types(env
)
937 self
.index
.analyse_types(env
)
938 if self
.base
.type.is_pyobject
:
939 self
.index
= self
.index
.coerce_to_pyobject(env
)
940 self
.type = PyrexTypes
.py_object_type
943 if self
.base
.type.is_ptr
or self
.base
.type.is_array
:
944 self
.type = self
.base
.type.base_type
947 "Attempting to index non-array type '%s'" %
949 self
.type = PyrexTypes
.error_type
950 if self
.index
.type.is_pyobject
:
951 self
.index
= self
.index
.coerce_to(
952 PyrexTypes
.c_int_type
, env
)
953 if not self
.index
.type.is_int
:
955 "Invalid index type '%s'" %
958 def check_const_addr(self
):
959 self
.base
.check_const_addr()
960 self
.index
.check_const()
965 def result_code(self
):
966 return "(%s[%s])" % (
967 self
.base
.result
, self
.index
.result
)
969 def generate_result_code(self
, code
):
970 if self
.type.is_pyobject
:
972 "%s = PyObject_GetItem(%s, %s); if (!%s) %s" % (
977 code
.error_goto(self
.pos
)))
979 def generate_assignment_code(self
, rhs
, code
):
980 self
.generate_subexpr_evaluation_code(code
)
981 if self
.type.is_pyobject
:
983 "if (PyObject_SetItem(%s, %s, %s) < 0) %s" % (
987 code
.error_goto(self
.pos
)))
988 self
.generate_subexpr_disposal_code(code
)
992 self
.result
, rhs
.result
))
993 rhs
.generate_disposal_code(code
)
995 def generate_deletion_code(self
, code
):
996 self
.generate_subexpr_evaluation_code(code
)
998 "if (PyObject_DelItem(%s, %s) < 0) %s" % (
1001 code
.error_goto(self
.pos
)))
1002 self
.generate_subexpr_disposal_code(code
)
1005 class SliceIndexNode(ExprNode
):
1006 # 2-element slice indexing
1009 # start ExprNode or None
1010 # stop ExprNode or None
1012 subexprs
= ['base', 'start', 'stop']
1014 def analyse_target_declaration(self
, env
):
1017 def analyse_types(self
, env
):
1018 self
.base
.analyse_types(env
)
1020 self
.start
.analyse_types(env
)
1022 self
.stop
.analyse_types(env
)
1023 self
.base
= self
.base
.coerce_to_pyobject(env
)
1024 c_int
= PyrexTypes
.c_int_type
1026 self
.start
= self
.start
.coerce_to(c_int
, env
)
1028 self
.stop
= self
.stop
.coerce_to(c_int
, env
)
1029 self
.type = PyrexTypes
.py_object_type
1032 def generate_result_code(self
, code
):
1034 "%s = PySequence_GetSlice(%s, %s, %s); if (!%s) %s" % (
1040 code
.error_goto(self
.pos
)))
1042 def generate_assignment_code(self
, rhs
, code
):
1043 self
.generate_subexpr_evaluation_code(code
)
1045 "if (PySequence_SetSlice(%s, %s, %s, %s) < 0) %s" % (
1050 code
.error_goto(self
.pos
)))
1051 self
.generate_subexpr_disposal_code(code
)
1052 rhs
.generate_disposal_code(code
)
1054 def generate_deletion_code(self
, code
):
1055 self
.generate_subexpr_evaluation_code(code
)
1057 "if (PySequence_DelSlice(%s, %s, %s) < 0) %s" % (
1061 code
.error_goto(self
.pos
)))
1062 self
.generate_subexpr_disposal_code(code
)
1064 def start_code(self
):
1066 return self
.start
.result
1070 def stop_code(self
):
1072 return self
.stop
.result
1076 def result_code(self
):
1077 # self.result is not used, but this method must exist
1081 class SliceNode(ExprNode
):
1082 # start:stop:step in subscript list
1088 subexprs
= ['start', 'stop', 'step']
1090 def analyse_types(self
, env
):
1091 self
.start
.analyse_types(env
)
1092 self
.stop
.analyse_types(env
)
1093 self
.step
.analyse_types(env
)
1094 self
.start
= self
.start
.coerce_to_pyobject(env
)
1095 self
.stop
= self
.stop
.coerce_to_pyobject(env
)
1096 self
.step
= self
.step
.coerce_to_pyobject(env
)
1097 self
.type = PyrexTypes
.py_object_type
1100 def generate_result_code(self
, code
):
1102 "%s = PySlice_New(%s, %s, %s); if (!%s) %s" % (
1108 code
.error_goto(self
.pos
)))
1111 class SimpleCallNode(ExprNode
):
1112 # Function call without keyword, * or ** args.
1116 # arg_tuple ExprNode used internally
1118 subexprs
= ['function', 'args', 'arg_tuple']
1122 def analyse_types(self
, env
):
1123 self
.function
.analyse_types(env
)
1124 if self
.function
.type.is_pyobject
:
1125 self
.arg_tuple
= TupleNode(self
.pos
, args
= self
.args
)
1127 self
.arg_tuple
.analyse_types(env
)
1128 self
.type = PyrexTypes
.py_object_type
1131 for arg
in self
.args
:
1132 arg
.analyse_types(env
)
1133 self
.analyse_c_function_call(env
)
1135 def analyse_c_function_call(self
, env
):
1136 func_type
= self
.function
.type
1137 # Coerce function pointer to function
1138 if func_type
.is_ptr
:
1139 func_type
= func_type
.base_type
1140 self
.function
.type = func_type
1141 # Check function type
1142 if not func_type
.is_cfunction
:
1143 if not func_type
.is_error
:
1144 error(self
.pos
, "Calling non-function type '%s'" %
1146 self
.type = PyrexTypes
.error_type
1147 self
.result
= "<error>"
1150 expected_nargs
= len(func_type
.args
)
1151 actual_nargs
= len(self
.args
)
1152 if actual_nargs
< expected_nargs \
1153 or (not func_type
.has_varargs
and actual_nargs
> expected_nargs
):
1154 expected_str
= str(expected_nargs
)
1155 if func_type
.has_varargs
:
1156 expected_str
= "at least " + expected_str
1158 "Call with wrong number of arguments (expected %s, got %s)"
1159 % (expected_str
, actual_nargs
))
1161 self
.type = PyrexTypes
.error_type
1162 self
.result
= "<error>"
1165 for i
in range(expected_nargs
):
1166 formal_type
= func_type
.args
[i
].type
1167 self
.args
[i
] = self
.args
[i
].coerce_to(formal_type
, env
)
1168 for i
in range(expected_nargs
, actual_nargs
):
1169 if self
.args
[i
].type.is_pyobject
:
1170 error(self
.args
[i
].pos
,
1171 "Python object cannot be passed as a varargs parameter")
1172 # Calc result type and code fragment
1173 self
.type = func_type
.return_type
1174 if self
.type.is_pyobject \
1175 or func_type
.exception_value
is not None \
1176 or func_type
.exception_check
:
1179 def result_code(self
):
1180 return self
.c_call_code(as_extension_type
= 0)
1182 def result_as_extension_type(self
):
1183 return self
.c_call_code(as_extension_type
= 1)
1185 def c_call_code(self
, as_extension_type
):
1186 if self
.args
is None or self
.function
.type.is_error
:
1188 formal_args
= self
.function
.type.args
1190 for (formal_arg
, actual_arg
) in \
1191 zip(formal_args
, self
.args
):
1192 if formal_arg
.type.is_extension_type
:
1193 arg_code
= actual_arg
.result_as_extension_type()
1195 arg_code
= actual_arg
.result
1196 arg_list_code
.append(arg_code
)
1197 for actual_arg
in self
.args
[len(formal_args
):]:
1198 arg_list_code
.append(actual_arg
.result
)
1199 result
= "%s(%s)" % (self
.function
.result
,
1200 join(arg_list_code
, ","))
1201 if self
.type.is_extension_type
and not as_extension_type
:
1202 result
= "((PyObject *)%s)" % result
1205 def generate_result_code(self
, code
):
1206 #print_call_chain("SimpleCallNode.generate_result_code") ###
1207 if self
.function
.type.is_pyobject
:
1209 "%s = PyObject_CallObject(%s, %s); if (!%s) %s" % (
1211 self
.function
.result
,
1212 self
.arg_tuple
.result
,
1214 code
.error_goto(self
.pos
)))
1217 if self
.type.is_pyobject
:
1218 exc_checks
.append("!%s" % self
.result
)
1220 exc_val
= self
.function
.type.exception_value
1221 exc_check
= self
.function
.type.exception_check
1222 if exc_val
is not None:
1223 exc_checks
.append("%s == %s" % (self
.result
, exc_val
))
1225 exc_checks
.append("PyErr_Occurred()")
1226 if self
.is_temp
or exc_checks
:
1228 lhs
= "%s = " % self
.result
1232 "%s%s; if (%s) %s" % (
1234 self
.c_call_code(as_extension_type
= 0),
1235 " && ".join(exc_checks
),
1236 code
.error_goto(self
.pos
)))
1239 class GeneralCallNode(ExprNode
):
1240 # General Python function call, including keyword,
1241 # * and ** arguments.
1244 # positional_args ExprNode Tuple of positional arguments
1245 # keyword_args ExprNode or None Dict of keyword arguments
1246 # starstar_arg ExprNode or None Dict of extra keyword args
1248 subexprs
= ['function', 'positional_args', 'keyword_args', 'starstar_arg']
1250 def analyse_types(self
, env
):
1251 self
.function
.analyse_types(env
)
1252 self
.positional_args
.analyse_types(env
)
1253 if self
.keyword_args
:
1254 self
.keyword_args
.analyse_types(env
)
1255 if self
.starstar_arg
:
1256 self
.starstar_arg
.analyse_types(env
)
1257 self
.function
= self
.function
.coerce_to_pyobject(env
)
1258 self
.positional_args
= \
1259 self
.positional_args
.coerce_to_pyobject(env
)
1260 if self
.starstar_arg
:
1261 self
.starstar_arg
= \
1262 self
.starstar_arg
.coerce_to_pyobject(env
)
1263 self
.type = PyrexTypes
.py_object_type
1266 def generate_result_code(self
, code
):
1267 if self
.keyword_args
and self
.starstar_arg
:
1269 "if (PyDict_Update(%s, %s) < 0) %s" % (
1270 self
.keyword_args
.result
,
1271 self
.starstar_arg
.result
,
1272 code
.error_goto(self
.pos
)))
1273 keyword_code
= self
.keyword_args
.result
1274 elif self
.keyword_args
:
1275 keyword_code
= self
.keyword_args
.result
1276 elif self
.starstar_arg
:
1277 keyword_code
= self
.starstar_arg
.result
1280 if not keyword_code
:
1281 call_code
= "PyObject_CallObject(%s, %s)" % (
1282 self
.function
.result
,
1283 self
.positional_args
.result
)
1285 call_code
= "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
1286 self
.function
.result
,
1287 self
.positional_args
.result
,
1290 "%s = %s; if (!%s) %s" % (
1294 code
.error_goto(self
.pos
)))
1297 class AsTupleNode(ExprNode
):
1298 # Convert argument to tuple. Used for normalising
1299 # the * argument of a function call.
1305 def analyse_types(self
, env
):
1306 self
.arg
.analyse_types(env
)
1307 self
.arg
= self
.arg
.coerce_to_pyobject(env
)
1308 self
.type = PyrexTypes
.py_object_type
1311 def generate_result_code(self
, code
):
1313 "%s = PySequence_Tuple(%s); if (!%s) %s" % (
1317 code
.error_goto(self
.pos
)))
1320 class AttributeNode(ExprNode
):
1328 # is_py_attr boolean Is a Python getattr operation
1329 # member string C name of struct member
1333 type = PyrexTypes
.error_type
1336 def analyse_target_declaration(self
, env
):
1339 def analyse_target_types(self
, env
):
1340 self
.analyse_types(env
, target
= 1)
1342 def analyse_types(self
, env
, target
= 0):
1343 if not self
.analyse_as_cimported_attribute(env
, target
):
1344 self
.analyse_as_ordinary_attribute(env
, target
)
1346 def analyse_as_cimported_attribute(self
, env
, target
):
1347 # Try to interpret this as a reference to an imported
1348 # C const, type, var or function. If successful, mutates
1349 # this node into a NameNode and returns 1, otherwise
1351 module_scope
= self
.obj
.analyse_as_module(env
)
1353 entry
= module_scope
.lookup_here(self
.attribute
)
1355 entry
.is_cglobal
or entry
.is_cfunction
1356 or entry
.is_type
or entry
.is_const
):
1357 self
.__class
__ = NameNode
1358 self
.name
= self
.attribute
1363 NameNode
.analyse_target_types(self
, env
)
1365 NameNode
.analyse_entry(self
, env
)
1369 def analyse_as_module(self
, env
):
1370 module_scope
= self
.obj
.analyse_as_module(env
)
1372 entry
= module_scope
.lookup_here(self
.attribute
)
1373 if entry
and entry
.as_module
:
1374 return entry
.as_module
1377 def analyse_as_ordinary_attribute(self
, env
, target
):
1378 self
.obj
.analyse_types(env
)
1379 self
.analyse_attribute(env
)
1380 # Reference to C array turns into pointer to first element.
1381 if self
.type.is_array
:
1382 self
.type = self
.type.element_ptr_type()
1387 def analyse_attribute(self
, env
):
1388 # Look up attribute and set self.type and self.member.
1390 self
.member
= self
.attribute
1391 if self
.obj
.type.is_string
:
1392 self
.obj
= self
.obj
.coerce_to_pyobject(env
)
1393 obj_type
= self
.obj
.type
1395 obj_type
= obj_type
.base_type
1397 elif obj_type
.is_extension_type
:
1401 if obj_type
.has_attributes
:
1403 if obj_type
.attributes_known():
1404 entry
= obj_type
.scope
.lookup_here(self
.attribute
)
1407 "Cannot select attribute of incomplete type '%s'"
1409 obj_type
= PyrexTypes
.error_type
1411 if entry
.is_variable
:
1412 self
.type = entry
.type
1413 self
.member
= entry
.cname
1416 # If it's not a variable, it must be a method of an
1417 # extension type, so we treat it like a Python attribute.
1419 # If we get here, the base object is not a struct/union/extension
1420 # type, or it is an extension type and the attribute is either not
1421 # declared or is declared as a method. Treat as a Python attribute
1423 if obj_type
.is_pyobject
:
1424 self
.type = PyrexTypes
.py_object_type
1427 if not obj_type
.is_error
:
1429 "Object of type '%s' has no attribute '%s'" %
1430 (obj_type
, self
.attribute
))
1432 def is_simple(self
):
1434 return self
.result_in_temp() or self
.obj
.is_simple()
1436 return NameNode
.is_simple(self
)
1438 def is_lvalue(self
):
1442 return NameNode
.is_lvalue(self
)
1444 def is_ephemeral(self
):
1446 return ExprNode
.is_ephemeral(self
)
1448 return NameNode
.is_ephemeral(self
)
1450 def result_code(self
):
1451 return self
.select_code()
1453 def result_as_extension_type(self
):
1454 return self
.uncast_select_code()
1456 def select_code(self
):
1457 code
= self
.uncast_select_code()
1458 if self
.type.is_extension_type
:
1459 code
= "((PyObject *)%s)" % code
1462 def uncast_select_code(self
):
1463 obj_type
= self
.obj
.type
1464 obj_code
= self
.obj
.result
1465 if obj_type
.is_extension_type
:
1466 #obj_code = "((%s)%s)" % (
1467 # obj_type.declaration_code(""),
1469 obj_code
= self
.obj
.result_as_extension_type()
1470 return "%s%s%s" % (obj_code
, self
.op
, self
.member
)
1472 def generate_result_code(self
, code
):
1475 '%s = PyObject_GetAttrString(%s, "%s"); if (!%s) %s' % (
1480 code
.error_goto(self
.pos
)))
1481 #elif self.type.is_pyobject:
1482 # code.put("%s = %s; " % (
1484 # self.select_code()))
1485 # code.put_incref(self.result)
1487 def generate_assignment_code(self
, rhs
, code
):
1488 self
.obj
.generate_evaluation_code(code
)
1491 'if (PyObject_SetAttrString(%s, "%s", %s) < 0) %s' % (
1495 code
.error_goto(self
.pos
)))
1496 rhs
.generate_disposal_code(code
)
1498 select_code
= self
.select_code()
1499 if self
.type.is_pyobject
:
1500 rhs
.make_owned_reference(code
)
1501 code
.put_decref(select_code
)
1506 rhs
.generate_post_assignment_code(code
)
1507 self
.obj
.generate_disposal_code(code
)
1509 def generate_deletion_code(self
, code
):
1510 self
.obj
.generate_evaluation_code(code
)
1513 'if (PyObject_DelAttrString(%s, "%s") < 0) %s' % (
1516 code
.error_goto(self
.pos
)))
1518 error(self
.pos
, "Cannot delete C attribute of extension type")
1519 self
.obj
.generate_disposal_code(code
)
1521 #-------------------------------------------------------------------
1525 #-------------------------------------------------------------------
1527 class SequenceNode(ExprNode
):
1528 # Base class for list and tuple constructor nodes.
1529 # Contains common code for performing sequence unpacking.
1532 # unpacked_items [ExprNode] or None
1533 # coerced_unpacked_items [ExprNode] or None
1537 is_sequence_constructor
= 1
1538 unpacked_items
= None
1540 def analyse_target_declaration(self
, env
):
1541 for arg
in self
.args
:
1542 arg
.analyse_target_declaration(env
)
1544 def analyse_types(self
, env
):
1545 for i
in range(len(self
.args
)):
1547 arg
.analyse_types(env
)
1548 self
.args
[i
] = arg
.coerce_to_pyobject(env
)
1549 self
.type = PyrexTypes
.py_object_type
1552 def analyse_target_types(self
, env
):
1553 self
.unpacked_items
= [] # PyTempNode(self.pos, env)
1554 self
.coerced_unpacked_items
= []
1555 for arg
in self
.args
:
1556 arg
.analyse_target_types(env
)
1557 #node = CloneNode(self.unpacked_item)
1558 unpacked_item
= PyTempNode(self
.pos
, env
)
1559 coerced_unpacked_item
= unpacked_item
.coerce_to(arg
.type, env
)
1560 self
.unpacked_items
.append(unpacked_item
)
1561 self
.coerced_unpacked_items
.append(coerced_unpacked_item
)
1562 self
.type = PyrexTypes
.py_object_type
1563 env
.use_utility_code(unpacking_utility_code
)
1565 def allocate_target_temps(self
, env
):
1566 for arg
in self
.args
:
1567 arg
.allocate_target_temps(env
)
1568 for node
in self
.coerced_unpacked_items
:
1569 node
.allocate_temps(env
)
1571 def release_target_temp(self
, env
):
1572 for arg
in self
.args
:
1573 arg
.release_target_temp(env
)
1574 for node
in self
.coerced_unpacked_items
:
1575 node
.release_temp(env
)
1577 def generate_result_code(self
, code
):
1578 self
.generate_operation_code(code
)
1580 def generate_assignment_code(self
, rhs
, code
):
1581 for i
in range(len(self
.args
)):
1582 unpack_result
= self
.unpacked_items
[i
].result
1584 "%s = __Pyx_UnpackItem(%s, %s); if (!%s) %s" % (
1589 code
.error_goto(self
.pos
)))
1590 value_node
= self
.coerced_unpacked_items
[i
]
1591 value_node
.generate_evaluation_code(code
)
1592 self
.args
[i
].generate_assignment_code(value_node
, code
)
1594 "if (__Pyx_EndUnpack(%s, %s) < 0) %s" % (
1597 code
.error_goto(self
.pos
)))
1598 if debug_disposal_code
:
1599 print "UnpackNode.generate_assignment_code:"
1600 print "...generating disposal code for", rhs
1601 rhs
.generate_disposal_code(code
)
1604 class TupleNode(SequenceNode
):
1605 # Tuple constructor.
1607 def generate_operation_code(self
, code
):
1609 "%s = PyTuple_New(%s); if (!%s) %s" % (
1613 code
.error_goto(self
.pos
)))
1614 for i
in range(len(self
.args
)):
1616 if not arg
.result_in_temp():
1617 code
.put_incref(arg
.result
)
1619 "PyTuple_SET_ITEM(%s, %s, %s);" % (
1624 def generate_subexpr_disposal_code(self
, code
):
1625 # We call generate_post_assignment_code here instead
1626 # of generate_disposal_code, because values were stored
1627 # in the tuple using a reference-stealing operation.
1628 for arg
in self
.args
:
1629 arg
.generate_post_assignment_code(code
)
1632 class ListNode(SequenceNode
):
1635 def generate_operation_code(self
, code
):
1636 code
.putln("%s = PyList_New(%s); if (!%s) %s" %
1640 code
.error_goto(self
.pos
)))
1641 for i
in range(len(self
.args
)):
1643 #if not arg.is_temp:
1644 if not arg
.result_in_temp():
1645 code
.put_incref(arg
.result
)
1646 code
.putln("PyList_SET_ITEM(%s, %s, %s);" %
1651 def generate_subexpr_disposal_code(self
, code
):
1652 # We call generate_post_assignment_code here instead
1653 # of generate_disposal_code, because values were stored
1654 # in the list using a reference-stealing operation.
1655 for arg
in self
.args
:
1656 arg
.generate_post_assignment_code(code
)
1659 class DictNode(ExprNode
):
1660 # Dictionary constructor.
1662 # key_value_pairs [(ExprNode, ExprNode)]
1664 def analyse_types(self
, env
):
1666 for key
, value
in self
.key_value_pairs
:
1667 key
.analyse_types(env
)
1668 value
.analyse_types(env
)
1669 key
= key
.coerce_to_pyobject(env
)
1670 value
= value
.coerce_to_pyobject(env
)
1671 new_pairs
.append((key
, value
))
1672 self
.key_value_pairs
= new_pairs
1673 self
.type = PyrexTypes
.py_object_type
1676 def allocate_temps(self
, env
):
1677 # Custom method used here because key-value
1678 # pairs are evaluated and used one at a time.
1679 self
.allocate_temp(env
)
1680 for key
, value
in self
.key_value_pairs
:
1681 key
.allocate_temps(env
)
1682 value
.allocate_temps(env
)
1683 key
.release_temp(env
)
1684 value
.release_temp(env
)
1686 def generate_evaluation_code(self
, code
):
1687 # Custom method used here because key-value
1688 # pairs are evaluated and used one at a time.
1690 "%s = PyDict_New(); if (!%s) %s" % (
1693 code
.error_goto(self
.pos
)))
1694 for key
, value
in self
.key_value_pairs
:
1695 key
.generate_evaluation_code(code
)
1696 value
.generate_evaluation_code(code
)
1698 "if (PyDict_SetItem(%s, %s, %s) < 0) %s" % (
1702 code
.error_goto(self
.pos
)))
1703 key
.generate_disposal_code(code
)
1704 value
.generate_disposal_code(code
)
1707 class ClassNode(ExprNode
):
1708 # Helper class used in the implementation of Python
1709 # class definitions. Constructs a class object given
1710 # a name, tuple of bases and class dictionary.
1712 # name ExprNode Name of the class
1713 # bases ExprNode Base class tuple
1714 # dict ExprNode Class dict (not owned by this node)
1715 # doc ExprNode or None Doc string
1717 subexprs
= ['name', 'bases', 'doc']
1719 def analyse_types(self
, env
):
1720 self
.name
.analyse_types(env
)
1721 self
.name
= self
.name
.coerce_to_pyobject(env
)
1722 self
.bases
.analyse_types(env
)
1724 self
.doc
.analyse_types(env
)
1725 self
.doc
= self
.doc
.coerce_to_pyobject(env
)
1726 self
.type = PyrexTypes
.py_object_type
1729 def generate_result_code(self
, code
):
1732 'if (PyDict_SetItemString(%s, "__doc__", %s) < 0) %s' % (
1735 code
.error_goto(self
.pos
)))
1737 '%s = PyClass_New(%s, %s, %s); if (!%s) %s' % (
1743 code
.error_goto(self
.pos
)))
1746 class UnboundMethodNode(ExprNode
):
1747 # Helper class used in the implementation of Python
1748 # class definitions. Constructs an unbound method
1749 # object from a class and a function.
1751 # class_cname string C var holding the class object
1752 # function ExprNode Function object
1754 subexprs
= ['function']
1756 def analyse_types(self
, env
):
1757 self
.function
.analyse_types(env
)
1758 self
.type = PyrexTypes
.py_object_type
1761 def generate_result_code(self
, code
):
1763 "%s = PyMethod_New(%s, 0, %s); if (!%s) %s" % (
1765 self
.function
.result
,
1768 code
.error_goto(self
.pos
)))
1771 class PyCFunctionNode(AtomicExprNode
):
1772 # Helper class used in the implementation of Python
1773 # class definitions. Constructs a PyCFunction object
1774 # from a PyMethodDef struct.
1776 # pymethdef_cname string PyMethodDef structure
1778 def analyse_types(self
, env
):
1779 self
.type = PyrexTypes
.py_object_type
1782 def generate_result_code(self
, code
):
1784 "%s = PyCFunction_New(&%s, 0); if (!%s) %s" % (
1786 self
.pymethdef_cname
,
1788 code
.error_goto(self
.pos
)))
1790 #-------------------------------------------------------------------
1792 # Unary operator nodes
1794 #-------------------------------------------------------------------
1796 class UnopNode(ExprNode
):
1800 # Processing during analyse_expressions phase:
1802 # analyse_c_operation
1803 # Called when the operand is not a pyobject.
1804 # - Check operand type and coerce if needed.
1805 # - Determine result type and result code fragment.
1806 # - Allocate temporary for result if needed.
1808 subexprs
= ['operand']
1810 def analyse_types(self
, env
):
1811 self
.operand
.analyse_types(env
)
1812 if self
.is_py_operation():
1813 self
.coerce_operand_to_pyobject(env
)
1814 self
.type = PyrexTypes
.py_object_type
1817 self
.analyse_c_operation(env
)
1819 def check_const(self
):
1820 self
.operand
.check_const()
1822 def is_py_operation(self
):
1823 return self
.operand
.type.is_pyobject
1825 def coerce_operand_to_pyobject(self
, env
):
1826 self
.operand
= self
.operand
.coerce_to_pyobject(env
)
1828 def generate_result_code(self
, code
):
1829 if self
.operand
.type.is_pyobject
:
1830 self
.generate_py_operation_code(code
)
1833 self
.generate_c_operation_code(code
)
1835 def generate_py_operation_code(self
, code
):
1836 function
= self
.py_operation_function()
1838 "%s = %s(%s); if (!%s) %s" % (
1841 self
.operand
.result
,
1843 code
.error_goto(self
.pos
)))
1845 def type_error(self
):
1846 if not self
.operand
.type.is_error
:
1847 error(self
.pos
, "Invalid operand type for '%s' (%s)" %
1848 (self
.operator
, self
.operand
.type))
1849 self
.type = PyrexTypes
.error_type
1852 class NotNode(ExprNode
):
1857 subexprs
= ['operand']
1859 def analyse_types(self
, env
):
1860 self
.operand
.analyse_types(env
)
1861 self
.operand
= self
.operand
.coerce_to_boolean(env
)
1862 self
.type = PyrexTypes
.c_int_type
1864 def result_code(self
):
1865 return "(!%s)" % self
.operand
.result
1867 def generate_result_code(self
, code
):
1871 class UnaryPlusNode(UnopNode
):
1872 # unary '+' operator
1876 def analyse_c_operation(self
, env
):
1877 self
.type = self
.operand
.type
1879 def py_operation_function(self
):
1880 return "PyNumber_Positive"
1882 def result_code(self
):
1883 return self
.operand
.result
1886 class UnaryMinusNode(UnopNode
):
1887 # unary '-' operator
1891 def analyse_c_operation(self
, env
):
1892 if self
.operand
.type.is_numeric
:
1893 self
.type = self
.operand
.type
1897 def py_operation_function(self
):
1898 return "PyNumber_Negative"
1900 def result_code(self
):
1901 return "(-%s)" % self
.operand
.result
1904 class TildeNode(UnopNode
):
1905 # unary '~' operator
1907 def analyse_c_operation(self
, env
):
1908 if self
.operand
.type.is_int
:
1909 self
.type = self
.operand
.type
1913 def py_operation_function(self
):
1914 return "PyNumber_Invert"
1916 def result_code(self
):
1917 return "(~%s)" % self
.operand
.result
1920 class AmpersandNode(ExprNode
):
1921 # The C address-of operator.
1925 subexprs
= ['operand']
1927 def analyse_types(self
, env
):
1928 self
.operand
.analyse_types(env
)
1929 argtype
= self
.operand
.type
1930 if not (argtype
.is_cfunction
or self
.operand
.is_lvalue()):
1931 self
.error("Taking address of non-lvalue")
1933 if argtype
.is_pyobject
:
1934 self
.error("Cannot take address of Python variable")
1936 self
.type = PyrexTypes
.c_ptr_type(argtype
)
1938 def check_const(self
):
1939 self
.operand
.check_const_addr()
1941 def error(self
, mess
):
1942 error(self
.pos
, mess
)
1943 self
.type = PyrexTypes
.error_type
1944 self
.result
= "<error>"
1946 def result_code(self
):
1947 return "(&%s)" % self
.operand
.result
1949 def generate_result_code(self
, code
):
1953 unop_node_classes
= {
1955 "-": UnaryMinusNode
,
1959 def unop_node(pos
, operator
, operand
):
1960 # Construct unnop node of appropriate class for
1962 return unop_node_classes
[operator
](pos
,
1963 operator
= operator
,
1967 class TypecastNode(ExprNode
):
1970 # base_type CBaseTypeNode
1971 # declarator CDeclaratorNode
1974 subexprs
= ['operand']
1976 def analyse_types(self
, env
):
1977 base_type
= self
.base_type
.analyse(env
)
1978 _
, self
.type = self
.declarator
.analyse(base_type
, env
)
1979 self
.operand
.analyse_types(env
)
1980 to_py
= self
.type.is_pyobject
1981 from_py
= self
.operand
.type.is_pyobject
1982 if from_py
and not to_py
and self
.operand
.is_ephemeral():
1983 error(self
.pos
, "Casting temporary Python object to non-Python type")
1985 if to_py
and not from_py
:
1988 def check_const(self
):
1989 self
.operand
.check_const()
1991 def result_code(self
):
1992 if self
.type.is_pyobject
:
1995 cast
= self
.type.declaration_code("")
1996 return "((%s)%s)" % (cast
, self
.operand
.result
)
1998 def result_as_extension_type(self
):
1999 return "((%s)%s)" % (
2000 self
.type.declaration_code(""),
2001 self
.operand
.result
)
2003 def generate_result_code(self
, code
):
2006 "%s = (PyObject *)%s;" % (
2008 #self.type.declaration_code(""),
2009 self
.operand
.result
))
2010 code
.put_incref(self
.result
)
2013 class SizeofNode(ExprNode
):
2014 # Abstract base class for sizeof(x) expression nodes.
2016 def check_const(self
):
2019 def generate_result_code(self
, code
):
2023 class SizeofTypeNode(SizeofNode
):
2024 # C sizeof function applied to a type
2026 # base_type CBaseTypeNode
2027 # declarator CDeclaratorNode
2031 def analyse_types(self
, env
):
2032 base_type
= self
.base_type
.analyse(env
)
2033 _
, arg_type
= self
.declarator
.analyse(base_type
, env
)
2034 self
.arg_type
= arg_type
2035 if arg_type
.is_pyobject
:
2036 error(self
.pos
, "Cannot take sizeof Python object")
2037 elif arg_type
.is_void
:
2038 error(self
.pos
, "Cannot take sizeof void")
2039 elif not arg_type
.is_complete():
2040 error(self
.pos
, "Cannot take sizeof incomplete type '%s'" % arg_code
)
2041 self
.type = PyrexTypes
.c_int_type
2043 def result_code(self
):
2044 arg_code
= self
.arg_type
.declaration_code("")
2045 return "(sizeof(%s))" % arg_code
2048 class SizeofVarNode(SizeofNode
):
2049 # C sizeof function applied to a variable
2053 subexprs
= ['operand']
2055 def analyse_types(self
, env
):
2056 self
.operand
.analyse_types(env
)
2057 self
.type = PyrexTypes
.c_int_type
2059 def result_code(self
):
2060 return "(sizeof(%s))" % self
.operand
.result
2062 def generate_result_code(self
, code
):
2066 #-------------------------------------------------------------------
2068 # Binary operator nodes
2070 #-------------------------------------------------------------------
2072 class BinopNode(ExprNode
):
2077 # Processing during analyse_expressions phase:
2079 # analyse_c_operation
2080 # Called when neither operand is a pyobject.
2081 # - Check operand types and coerce if needed.
2082 # - Determine result type and result code fragment.
2083 # - Allocate temporary for result if needed.
2085 subexprs
= ['operand1', 'operand2']
2087 def analyse_types(self
, env
):
2088 self
.operand1
.analyse_types(env
)
2089 self
.operand2
.analyse_types(env
)
2090 if self
.is_py_operation():
2091 self
.coerce_operands_to_pyobjects(env
)
2092 self
.type = PyrexTypes
.py_object_type
2095 self
.analyse_c_operation(env
)
2097 def is_py_operation(self
):
2098 return (self
.operand1
.type.is_pyobject
2099 or self
.operand2
.type.is_pyobject
)
2101 def coerce_operands_to_pyobjects(self
, env
):
2102 self
.operand1
= self
.operand1
.coerce_to_pyobject(env
)
2103 self
.operand2
= self
.operand2
.coerce_to_pyobject(env
)
2105 def check_const(self
):
2106 self
.operand1
.check_const()
2107 self
.operand2
.check_const()
2109 def generate_result_code(self
, code
):
2110 if self
.operand1
.type.is_pyobject
:
2111 function
= self
.py_operation_function()
2112 if function
== "PyNumber_Power":
2113 extra_args
= ", Py_None"
2117 "%s = %s(%s, %s%s); if (!%s) %s" % (
2120 self
.operand1
.result
,
2121 self
.operand2
.result
,
2124 code
.error_goto(self
.pos
)))
2127 self
.generate_c_operation_code(code
)
2129 def type_error(self
):
2130 if not (self
.operand1
.type.is_error
2131 or self
.operand2
.type.is_error
):
2132 error(self
.pos
, "Invalid operand types for '%s' (%s; %s)" %
2133 (self
.operator
, self
.operand1
.type,
2134 self
.operand2
.type))
2135 self
.type = PyrexTypes
.error_type
2138 class NumBinopNode(BinopNode
):
2139 # Binary operation taking numeric arguments.
2141 def analyse_c_operation(self
, env
):
2142 type1
= self
.operand1
.type
2143 type2
= self
.operand2
.type
2144 self
.type = self
.compute_c_result_type(type1
, type2
)
2148 def compute_c_result_type(self
, type1
, type2
):
2149 if self
.c_types_okay(type1
, type2
):
2150 return PyrexTypes
.widest_numeric_type(type1
, type2
)
2154 def c_types_okay(self
, type1
, type2
):
2155 return type1
.is_numeric
and type2
.is_numeric
2157 def result_code(self
):
2158 return "(%s %s %s)" % (
2159 self
.operand1
.result
,
2161 self
.operand2
.result
)
2163 def py_operation_function(self
):
2164 return self
.py_functions
[self
.operator
]
2168 "^": "PyNumber_Xor",
2169 "&": "PyNumber_And",
2170 "<<": "PyNumber_Lshift",
2171 ">>": "PyNumber_Rshift",
2172 "+": "PyNumber_Add",
2173 "-": "PyNumber_Subtract",
2174 "*": "PyNumber_Multiply",
2175 "/": "PyNumber_Divide",
2176 "%": "PyNumber_Remainder",
2177 "**": "PyNumber_Power"
2181 class IntBinopNode(NumBinopNode
):
2182 # Binary operation taking integer arguments.
2184 def c_types_okay(self
, type1
, type2
):
2185 return type1
.is_int
and type2
.is_int
2188 class AddNode(NumBinopNode
):
2191 def is_py_operation(self
):
2192 if self
.operand1
.type.is_string \
2193 and self
.operand2
.type.is_string
:
2196 return NumBinopNode
.is_py_operation(self
)
2198 def compute_c_result_type(self
, type1
, type2
):
2199 if type1
.is_ptr
and type2
.is_int
:
2201 elif type1
.is_int
and type2
.is_ptr
:
2204 return NumBinopNode
.compute_c_result_type(
2208 class SubNode(NumBinopNode
):
2211 def compute_c_result_type(self
, type1
, type2
):
2212 if type1
.is_ptr
and type2
.is_int
:
2214 elif type1
.is_ptr
and type2
.is_ptr
:
2215 return PyrexTypes
.c_int_type
2217 return NumBinopNode
.compute_c_result_type(
2221 class MulNode(NumBinopNode
):
2224 def is_py_operation(self
):
2225 type1
= self
.operand1
.type
2226 type2
= self
.operand2
.type
2227 if (type1
.is_string
and type2
.is_int
) \
2228 or (type2
.is_string
and type1
.is_int
):
2231 return NumBinopNode
.is_py_operation(self
)
2234 class ModNode(IntBinopNode
):
2237 def is_py_operation(self
):
2238 return (self
.operand1
.type.is_string
2239 or self
.operand2
.type.is_string
2240 or IntBinopNode
.is_py_operation(self
))
2243 class PowNode(NumBinopNode
):
2246 def analyse_types(self
, env
):
2247 env
.pow_function_used
= 1
2248 NumBinopNode
.analyse_types(self
, env
)
2250 def compute_c_result_type(self
, type1
, type2
):
2251 if self
.c_types_okay(type1
, type2
):
2252 return PyrexTypes
.c_double_type
2256 def result_code(self
):
2257 return "pow(%s, %s)" % (
2258 self
.operand1
.result
, self
.operand2
.result
)
2261 class BoolBinopNode(ExprNode
):
2262 # Short-circuiting boolean operation.
2267 # temp_bool ExprNode used internally
2271 subexprs
= ['operand1', 'operand2', 'temp_bool']
2273 def analyse_types(self
, env
):
2274 self
.operand1
.analyse_types(env
)
2275 self
.operand2
.analyse_types(env
)
2276 if self
.operand1
.type.is_pyobject
or \
2277 self
.operand2
.type.is_pyobject
:
2278 self
.operand1
= self
.operand1
.coerce_to_pyobject(env
)
2279 self
.operand2
= self
.operand2
.coerce_to_pyobject(env
)
2280 self
.temp_bool
= TempNode(self
.pos
,
2281 PyrexTypes
.c_int_type
, env
)
2282 self
.type = PyrexTypes
.py_object_type
2284 self
.operand1
= self
.operand1
.coerce_to_boolean(env
)
2285 self
.operand2
= self
.operand2
.coerce_to_boolean(env
)
2286 self
.type = PyrexTypes
.c_int_type
2287 # For what we're about to do, it's vital that
2288 # both operands be temp nodes.
2289 self
.operand1
= self
.operand1
.coerce_to_temp(env
) #CTT
2290 self
.operand2
= self
.operand2
.coerce_to_temp(env
)
2291 # coerce_to_simple does not seem to be sufficient
2292 #self.operand1 = self.operand1.coerce_to_simple(env)
2293 #self.operand2 = self.operand2.coerce_to_simple(env)
2296 def allocate_temps(self
, env
, result
= None):
2297 # We don't need both operands at the same time, and
2298 # one of the operands will also be our result. So we
2299 # use an allocation strategy here which results in
2300 # this node and both its operands sharing the same
2301 # result variable. This allows us to avoid some
2302 # assignments and increfs/decrefs that would otherwise
2304 self
.allocate_temp(env
, result
)
2305 self
.operand1
.allocate_temps(env
, self
.result
)
2307 self
.temp_bool
.allocate_temp(env
)
2308 self
.temp_bool
.release_temp(env
)
2309 self
.operand2
.allocate_temps(env
, self
.result
)
2310 # We haven't called release_temp on either operand,
2311 # because although they are temp nodes, they don't own
2312 # their result variable. And because they are temp
2313 # nodes, any temps in their subnodes will have been
2314 # released before their allocate_temps returned.
2315 # Therefore, they contain no temp vars that need to
2318 def check_const(self
):
2319 self
.operand1
.check_const()
2320 self
.operand2
.check_const()
2322 def result_code(self
):
2323 return "(%s %s %s)" % (
2324 self
.operand1
.result
,
2325 self
.py_to_c_op
[self
.operator
],
2326 self
.operand2
.result
)
2328 py_to_c_op
= {'and': "&&", 'or': "||"}
2330 def generate_evaluation_code(self
, code
):
2331 self
.operand1
.generate_evaluation_code(code
)
2332 test_result
= self
.generate_operand1_test(code
)
2333 if self
.operator
== 'and':
2341 self
.operand1
.generate_disposal_code(code
)
2342 self
.operand2
.generate_evaluation_code(code
)
2346 def generate_operand1_test(self
, code
):
2347 # Generate code to test the truth of the first operand.
2348 if self
.type.is_pyobject
:
2349 test_result
= self
.temp_bool
.result
2351 "%s = PyObject_IsTrue(%s); if (%s < 0) %s" % (
2353 self
.operand1
.result
,
2355 code
.error_goto(self
.pos
)))
2357 test_result
= self
.operand1
.result
2362 # Mixin class containing code common to PrimaryCmpNodes
2363 # and CascadedCmpNodes.
2365 def is_python_comparison(self
):
2366 return (self
.has_python_operands()
2367 or (self
.cascade
and self
.cascade
.is_python_comparison())
2368 or self
.operator
in ('in', 'not_in'))
2370 def check_types(self
, env
, operand1
, op
, operand2
):
2371 if not self
.types_okay(operand1
, op
, operand2
):
2372 error(self
.pos
, "Invalid types for '%s' (%s, %s)" %
2373 (self
.operator
, operand1
.type, operand2
.type))
2375 def types_okay(self
, operand1
, op
, operand2
):
2376 type1
= operand1
.type
2377 type2
= operand2
.type
2378 if type1
.is_error
or type2
.is_error
:
2380 if type1
.is_pyobject
: # type2 will be, too
2383 return type1
.is_null_ptr
or type2
.is_null_ptr \
2384 or type1
.same_as(type2
)
2385 elif (type1
.is_numeric
and type2
.is_numeric
2386 and op
not in ('is', 'is_not')):
2391 def generate_operation_code(self
, code
, result
,
2392 operand1
, op
, operand2
):
2393 if op
== 'in' or op
== 'not_in':
2395 "%s = PySequence_Contains(%s, %s); if (%s < 0) %s" % (
2400 code
.error_goto(self
.pos
)))
2405 elif (operand1
.type.is_pyobject
2406 and op
not in ('is', 'is_not')):
2408 "if (PyObject_Cmp(%s, %s, &%s) < 0) %s" % (
2412 code
.error_goto(self
.pos
)))
2415 result
, result
, op
))
2417 code
.putln("%s = %s %s %s;" % (
2420 self
.c_operator(op
),
2423 def c_operator(self
, op
):
2426 elif op
== 'is_not':
2432 class PrimaryCmpNode(ExprNode
, CmpNode
):
2433 # Non-cascaded comparison or first comparison of
2434 # a cascaded sequence.
2439 # cascade CascadedCmpNode
2441 # We don't use the subexprs mechanism, because
2442 # things here are too complicated for it to handle.
2443 # Instead, we override all the framework methods
2448 def analyse_types(self
, env
):
2449 self
.operand1
.analyse_types(env
)
2450 self
.operand2
.analyse_types(env
)
2452 self
.cascade
.analyse_types(env
, self
.operand2
)
2453 self
.is_pycmp
= self
.is_python_comparison()
2455 self
.coerce_operands_to_pyobjects(env
)
2457 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
2458 self
.operand2
= self
.operand2
.coerce_to_simple(env
)
2459 self
.cascade
.coerce_cascaded_operands_to_temp(env
)
2460 self
.check_operand_types(env
)
2461 self
.type = PyrexTypes
.c_int_type
2462 if self
.is_pycmp
or self
.cascade
:
2465 def check_operand_types(self
, env
):
2466 self
.check_types(env
,
2467 self
.operand1
, self
.operator
, self
.operand2
)
2469 self
.cascade
.check_operand_types(env
, self
.operand2
)
2471 def has_python_operands(self
):
2472 return (self
.operand1
.type.is_pyobject
2473 or self
.operand2
.type.is_pyobject
)
2475 def coerce_operands_to_pyobjects(self
, env
):
2476 self
.operand1
= self
.operand1
.coerce_to_pyobject(env
)
2477 self
.operand2
= self
.operand2
.coerce_to_pyobject(env
)
2479 self
.cascade
.coerce_operands_to_pyobjects(env
)
2481 def allocate_subexpr_temps(self
, env
):
2482 self
.operand1
.allocate_temps(env
)
2483 self
.operand2
.allocate_temps(env
)
2485 self
.cascade
.allocate_subexpr_temps(env
)
2487 def release_subexpr_temps(self
, env
):
2488 self
.operand1
.release_temp(env
)
2489 self
.operand2
.release_temp(env
)
2491 self
.cascade
.release_subexpr_temps(env
)
2493 def check_const(self
):
2494 self
.operand1
.check_const()
2495 self
.operand2
.check_const()
2499 def result_code(self
):
2500 return "(%s %s %s)" % (
2501 self
.operand1
.result
,
2502 self
.c_operator(self
.operator
),
2503 self
.operand2
.result
)
2505 def generate_evaluation_code(self
, code
):
2506 self
.operand1
.generate_evaluation_code(code
)
2507 self
.operand2
.generate_evaluation_code(code
)
2509 self
.generate_operation_code(code
, self
.result
,
2510 self
.operand1
, self
.operator
, self
.operand2
)
2512 self
.cascade
.generate_evaluation_code(code
,
2513 self
.result
, self
.operand2
)
2514 self
.operand1
.generate_disposal_code(code
)
2515 self
.operand2
.generate_disposal_code(code
)
2517 def generate_subexpr_disposal_code(self
, code
):
2518 # If this is called, it is a non-cascaded cmp,
2519 # so only need to dispose of the two main operands.
2520 self
.operand1
.generate_disposal_code(code
)
2521 self
.operand2
.generate_disposal_code(code
)
2524 class CascadedCmpNode(Node
, CmpNode
):
2525 # A CascadedCmpNode is not a complete expression node. It
2526 # hangs off the side of another comparison node, shares
2527 # its left operand with that node, and shares its result
2528 # with the PrimaryCmpNode at the head of the chain.
2532 # cascade CascadedCmpNode
2536 def analyse_types(self
, env
, operand1
):
2537 self
.operand2
.analyse_types(env
)
2539 self
.cascade
.analyse_types(env
, self
.operand2
)
2541 def check_operand_types(self
, env
, operand1
):
2542 self
.check_types(env
,
2543 operand1
, self
.operator
, self
.operand2
)
2545 self
.cascade
.check_operand_types(env
, self
.operand2
)
2547 def has_python_operands(self
):
2548 return self
.operand2
.type.is_pyobject
2550 def coerce_operands_to_pyobjects(self
, env
):
2551 self
.operand2
= self
.operand2
.coerce_to_pyobject(env
)
2553 self
.cascade
.coerce_operands_to_pyobjects(env
)
2555 def coerce_cascaded_operands_to_temp(self
, env
):
2557 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
2558 self
.operand2
= self
.operand2
.coerce_to_simple(env
)
2559 self
.cascade
.coerce_cascaded_operands_to_temp(env
)
2561 def allocate_subexpr_temps(self
, env
):
2562 self
.operand2
.allocate_temps(env
)
2564 self
.cascade
.allocate_subexpr_temps(env
)
2566 def release_subexpr_temps(self
, env
):
2567 self
.operand2
.release_temp(env
)
2569 self
.cascade
.release_subexpr_temps(env
)
2571 def generate_evaluation_code(self
, code
, result
, operand1
):
2572 code
.putln("if (%s) {" % result
)
2573 self
.operand2
.generate_evaluation_code(code
)
2574 self
.generate_operation_code(code
, result
,
2575 operand1
, self
.operator
, self
.operand2
)
2577 self
.cascade
.generate_evaluation_code(
2578 code
, result
, self
.operand2
)
2579 # Cascaded cmp result is always temp
2580 self
.operand2
.generate_disposal_code(code
)
2584 binop_node_classes
= {
2585 "or": BoolBinopNode
,
2586 "and": BoolBinopNode
,
2600 def binop_node(pos
, operator
, operand1
, operand2
):
2601 # Construct binop node of appropriate class for
2603 return binop_node_classes
[operator
](pos
,
2604 operator
= operator
,
2605 operand1
= operand1
,
2606 operand2
= operand2
)
2608 #-------------------------------------------------------------------
2612 # Coercion nodes are special in that they are created during
2613 # the analyse_types phase of parse tree processing.
2614 # Their __init__ methods consequently incorporate some aspects
2617 #-------------------------------------------------------------------
2619 class CoercionNode(ExprNode
):
2620 # Abstract base class for coercion nodes.
2622 # arg ExprNode node being coerced
2626 def __init__(self
, arg
):
2630 print self
, "Coercing", self
.arg
2633 class PyTypeTestNode(CoercionNode
):
2634 # This node is used to check that a generic Python
2635 # object is an instance of a particular extension type.
2636 # This node borrows the result of its argument node.
2638 def __init__(self
, arg
, dst_type
, env
):
2639 # The arg is know to be a Python object, and
2640 # the dst_type is known to be an extension type.
2641 CoercionNode
.__init
__(self
, arg
)
2642 self
.type = dst_type
2643 env
.use_utility_code(type_test_utility_code
)
2645 def result_in_temp(self
):
2646 return self
.arg
.result_in_temp()
2648 def is_ephemeral(self
):
2649 return self
.arg
.is_ephemeral()
2651 def result_code(self
):
2652 return self
.arg
.result
2654 def result_as_extension_type(self
):
2655 return "((%s)%s)" % (
2656 self
.type.declaration_code(""),
2659 def generate_result_code(self
, code
):
2660 if self
.type.typeobj_is_available():
2662 "if (!__Pyx_TypeTest(%s, %s)) %s" % (
2664 self
.type.typeptr_cname
,
2665 code
.error_goto(self
.pos
)))
2667 error(self
.pos
, "Cannot test type of extern C class "
2668 "without type object name specification")
2670 def generate_post_assignment_code(self
, code
):
2671 self
.arg
.generate_post_assignment_code(code
)
2674 class CoerceToPyTypeNode(CoercionNode
):
2675 # This node is used to convert a C data type
2676 # to a Python object.
2678 def __init__(self
, arg
, env
):
2679 CoercionNode
.__init
__(self
, arg
)
2680 self
.type = PyrexTypes
.py_object_type
2681 if not arg
.type.to_py_function
:
2683 "Cannot convert '%s' to Python object" % arg
.type)
2686 def generate_result_code(self
, code
):
2687 function
= self
.arg
.type.to_py_function
2688 code
.putln('%s = %s(%s); if (!%s) %s' % (
2693 code
.error_goto(self
.pos
)))
2696 class CoerceFromPyTypeNode(CoercionNode
):
2697 # This node is used to convert a Python object
2700 def __init__(self
, result_type
, arg
, env
):
2701 CoercionNode
.__init
__(self
, arg
)
2702 self
.type = result_type
2703 if not result_type
.from_py_function
:
2705 "Cannot convert Python object to '%s'" % result_type
)
2706 if self
.type.is_string
and self
.arg
.is_ephemeral():
2708 "Obtaining char * from temporary Python value")
2711 def generate_result_code(self
, code
):
2712 opnd
= self
.arg
.result
2713 function
= self
.type.from_py_function
2714 code
.putln('%s = %s(%s); if (PyErr_Occurred()) %s' % (
2718 code
.error_goto(self
.pos
)))
2721 class CoerceToBooleanNode(CoercionNode
):
2722 # This node is used when a result needs to be used
2723 # in a boolean context.
2725 def __init__(self
, arg
, env
):
2726 CoercionNode
.__init
__(self
, arg
)
2727 self
.type = PyrexTypes
.c_int_type
2728 if arg
.type.is_pyobject
:
2731 def check_const(self
):
2734 self
.arg
.check_const()
2736 def result_code(self
):
2737 return "(%s != 0)" % self
.arg
.result
2739 def generate_result_code(self
, code
):
2740 if self
.arg
.type.is_pyobject
:
2742 "%s = PyObject_IsTrue(%s); if (%s < 0) %s" % (
2746 code
.error_goto(self
.pos
)))
2749 #class CoerceToCharNode(CoercionNode):
2750 # # Convert char array or pointer to character.
2752 # def __init__(self, arg):
2753 # CoercionNode.__init__(self, arg)
2754 # self.type = PyrexTypes.c_char_type
2756 # def result_code(self):
2757 # return "(%s[0])" % self.arg.result
2759 # def generate_result_code(self, code):
2763 class CoerceToTempNode(CoercionNode
):
2764 # This node is used to force the result of another node
2765 # to be stored in a temporary. It is only used if the
2766 # argument node's result is not already in a temporary.
2768 def __init__(self
, arg
, env
):
2769 CoercionNode
.__init
__(self
, arg
)
2770 self
.type = self
.arg
.type
2773 def generate_result_code(self
, code
):
2774 #self.arg.generate_evaluation_code(code) # Already done
2775 # by generic generate_subexpr_evaluation_code!
2776 code
.putln("%s = %s;" % (
2777 self
.result
, self
.arg
.result
))
2778 if self
.type.is_pyobject
:
2779 code
.put_incref(self
.result
)
2782 class CloneNode(CoercionNode
):
2783 # This node is employed when the result of another node needs
2784 # to be used multiple times. The argument node's result must
2785 # be in a temporary. This node "borrows" the result from the
2786 # argument node, and does not generate any evaluation or
2787 # disposal code for it. The original owner of the argument
2788 # node is responsible for doing those things.
2790 subexprs
= [] # Arg is not considered a subexpr
2792 def __init__(self
, arg
):
2793 CoercionNode
.__init
__(self
, arg
)
2794 self
.type = arg
.type
2796 def result_code(self
):
2797 return self
.arg
.result
2799 def generate_evaluation_code(self
, code
):
2803 #------------------------------------------------------------------------------------
2805 # Runtime support code
2807 #------------------------------------------------------------------------------------
2809 get_name_utility_code
= \
2811 static PyObject *__Pyx_GetName(PyObject *dict, char *name) {
2813 result = PyObject_GetAttrString(dict, name);
2815 PyErr_SetString(PyExc_NameError, name);
2820 #------------------------------------------------------------------------------------
2822 import_utility_code
= \
2824 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
2825 PyObject *__import__ = 0;
2826 PyObject *empty_list = 0;
2827 PyObject *module = 0;
2828 PyObject *global_dict = 0;
2829 PyObject *empty_dict = 0;
2831 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
2837 empty_list = PyList_New(0);
2842 global_dict = PyModule_GetDict(%(GLOBALS)s);
2845 empty_dict = PyDict_New();
2848 module = PyObject_CallFunction(__import__, "OOOO",
2849 name, global_dict, empty_dict, list);
2851 Py_XDECREF(empty_list);
2852 Py_XDECREF(__import__);
2853 Py_XDECREF(empty_dict);
2857 "BUILTINS": Naming
.builtins_cname
,
2858 "GLOBALS": Naming
.module_cname
,
2861 #------------------------------------------------------------------------------------
2863 get_exception_utility_code
= \
2865 static PyObject *__Pyx_GetExcValue(void) {
2866 PyObject *type = 0, *value = 0, *tb = 0;
2867 PyObject *result = 0;
2868 PyThreadState *tstate = PyThreadState_Get();
2869 PyErr_Fetch(&type, &value, &tb);
2870 PyErr_NormalizeException(&type, &value, &tb);
2871 if (PyErr_Occurred())
2877 Py_XDECREF(tstate->exc_type);
2878 Py_XDECREF(tstate->exc_value);
2879 Py_XDECREF(tstate->exc_traceback);
2880 tstate->exc_type = type;
2881 tstate->exc_value = value;
2882 tstate->exc_traceback = tb;
2896 #------------------------------------------------------------------------------------
2898 unpacking_utility_code
= \
2900 static void __Pyx_UnpackError(void) {
2901 PyErr_SetString(PyExc_ValueError, "unpack sequence of wrong size");
2904 static PyObject *__Pyx_UnpackItem(PyObject *seq, int i) {
2906 if (!(item = PySequence_GetItem(seq, i))) {
2907 if (PyErr_ExceptionMatches(PyExc_IndexError))
2908 __Pyx_UnpackError();
2913 static int __Pyx_EndUnpack(PyObject *seq, int i) {
2915 if (item = PySequence_GetItem(seq, i)) {
2917 __Pyx_UnpackError();
2925 #------------------------------------------------------------------------------------
2927 type_test_utility_code
= \
2929 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
2931 PyErr_Format(PyExc_SystemError, "Missing type object");
2934 if (obj == Py_None || PyObject_TypeCheck(obj, type))
2936 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
2937 obj->ob_type->tp_name, type->tp_name);
2942 #------------------------------------------------------------------------------------