Better example and comments.
[rox-lib.git] / python / rox / Pyrex / Compiler / ExprNodes.py
blob5043ea595f78e1d5ccc2b3238d5d5b83a3212cf1
2 # Pyrex - Parse tree nodes for expressions
5 from string import join
7 from Errors import error, InternalError
8 import Naming
9 from Nodes import Node
10 import PyrexTypes
12 from Pyrex.Debugging import print_call_chain
13 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
14 debug_coercion
16 class ExprNode(Node):
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
23 # saved_subexpr_nodes
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:
30 # Analyse Types
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
35 # allocated.
37 # Allocate Temps
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
63 # implement it.
65 # Expression Analysis phase
67 # analyse_types
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.
80 # allocate_temps
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:
89 # result_code
90 # - Return a C code fragment evaluating to
91 # the result. This is only called when the
92 # result is not a temporary.
94 # check_const
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.
102 # check_const_addr
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
109 # lvalue.
111 # Code Generation phase
113 # generate_evaluation_code
114 # - Call generate_evaluation_code for sub-expressions.
115 # - Perform the functions of generate_result_code
116 # (see below).
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
126 # sub-expressions.
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.
154 is_temp = 0
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") ###
160 raise InternalError(
161 "%s.%s not implemented" %
162 (self.__class__.__name__, method_name))
164 def is_lvalue(self):
165 return 0
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:
179 nodes = []
180 for name in self.subexprs:
181 item = getattr(self, name)
182 if item:
183 if isinstance(item, ExprNode):
184 nodes.append(item)
185 else:
186 nodes.extend(item)
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)
204 self.check_const()
206 def analyse_expressions(self, env):
207 # Convenience routine performing both the Type
208 # Analysis and Temp Allocation phases for a whole
209 # expression.
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
216 # an assignment.
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)
225 return bool
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)
239 return temp_bool
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.
246 return 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):
255 self.not_const()
257 def not_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
272 # a subnode.
273 return self.is_temp
275 def allocate_target_temps(self, env):
276 # Perform allocate_temps for the LHS of an assignment.
277 if debug_temp_alloc:
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
287 # one.
288 if debug_temp_alloc:
289 print self, "Allocating temps"
290 self.allocate_subexpr_temps(env)
291 self.allocate_temp(env, result)
292 if self.is_temp:
293 self.release_subexpr_temps(env)
295 def allocate_subexpr_temps(self, env):
296 # Allocate temporary variables for all sub-expressions
297 # of this node.
298 if debug_temp_alloc:
299 print self, "Allocating temps for:", self.subexprs
300 for node in self.subexpr_nodes():
301 if node:
302 if debug_temp_alloc:
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
312 # one.
313 if debug_temp_alloc:
314 print self, "Allocating temp"
315 if result:
316 if not self.is_temp:
317 raise InternalError("Result forced on non-temp node")
318 self.result = result
319 elif self.is_temp:
320 type = self.type
321 if not type.is_void:
322 if type.is_pyobject:
323 type = PyrexTypes.py_object_type
324 self.result = env.allocate_temp(type)
325 else:
326 self.result = None
327 if debug_temp_alloc:
328 print self, "Allocated result", self.result
329 #print_call_chain(self, "allocated temp", self.result)
330 else:
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.
349 if self.is_temp:
350 if debug_temp_alloc:
351 print self, "Releasing result", self.result
352 #print_call_chain(self, "releasing temp", self.result)
353 env.release_temp(self.result)
354 else:
355 self.release_subexpr_temps(env)
357 def release_subexpr_temps(self, env):
358 # Release the results of all sub-expressions of
359 # this node.
360 for node in self.subexpr_nodes():
361 if node:
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
368 # a reference to it.
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)
379 if self.is_temp:
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.
392 if self.is_temp:
393 if self.type.is_pyobject:
394 code.put_decref_clear(self.result)
395 else:
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.
408 if self.is_temp:
409 if self.type.is_pyobject:
410 code.putln("%s = 0;" % self.result)
411 else:
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.
418 pass
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.
424 pass
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.
436 src_type = self.type
437 src_is_py_type = src_type.is_pyobject
438 dst_is_py_type = dst_type.is_pyobject
439 if dst_is_py_type:
440 result = self
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)
447 return result
448 elif src_is_py_type:
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))
454 return self
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
461 # a boolean value.
462 type = self.type
463 if type.is_pyobject or type.is_ptr or type.is_float:
464 return CoerceToBooleanNode(self, env)
465 else:
466 if not type.is_int:
467 error(self.pos,
468 "Type '%s' not acceptable as a boolean" % type)
469 return self
471 def coerce_to_integer(self, env):
472 # If not already some C integer type, coerce to longint.
473 if self.type.is_int:
474 return self
475 else:
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():
481 return self
482 else:
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.
488 if self.is_simple():
489 return self
490 else:
491 return self.coerce_to_temp(env)
493 def is_simple(self):
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.
504 subexprs = []
507 class PyConstNode(AtomicExprNode):
508 # Abstract base class for constant Python values.
510 def is_simple(self):
511 return 1
513 def analyse_types(self, env):
514 self.type = PyrexTypes.py_object_type
516 def result_code(self):
517 return self.value
519 def generate_result_code(self, code):
520 pass
523 class NoneNode(PyConstNode):
524 # The constant value None
526 value = "Py_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
540 is_literal = 1
542 def is_simple(self):
543 return 1
545 def analyse_types(self, env):
546 pass # Types are held in class variables
548 def check_const(self):
549 pass
551 def result_code(self):
552 return str(self.value)
554 def generate_result_code(self, code):
555 pass
558 class NullNode(ConstNode):
559 type = PyrexTypes.c_null_ptr_type
560 value = "0"
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):
579 # entry Symtab.Entry
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
597 self.is_temp = 1
599 def generate_evaluation_code(self, code):
600 code.putln(
601 "%s = PyComplex_FromDoubles(0.0, %s); if (!%s) %s" % (
602 self.result,
603 self.value,
604 self.result,
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
614 is_name = 1
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
620 return None
622 def analyse_target_declaration(self, env):
623 self.entry = env.lookup_here(self.name)
624 if not self.entry:
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)
630 if not self.entry:
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")
643 self.is_temp = 1
644 env.use_utility_code(get_name_utility_code)
646 def is_simple(self):
647 # If it's not a C variable, it'll be in a temp anyway.
648 return 1
650 def check_identifier_kind(self):
651 entry = self.entry
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
656 else:
657 error(self.pos,
658 "'%s' is not a constant, variable or function identifier" % self.name)
660 def analyse_target_types(self, env):
661 self.check_identifier_kind()
662 if self.is_lvalue():
663 self.type = self.entry.type
664 else:
665 error(self.pos, "Assignment to non-lvalue '%s'"
666 % self.name)
667 #self.entry = None
668 self.type = PyrexTypes.error_type
670 def calculate_target_results(self, env):
671 pass
673 def check_const(self):
674 entry = self.entry
675 if not (entry.is_const or entry.is_cfunction):
676 self.not_const()
678 def check_const_addr(self):
679 entry = self.entry
680 if not (entry.is_cglobal or entry.is_cfunction):
681 self.addr_not_const()
683 def is_lvalue(self):
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.
691 return 0
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
700 return 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
708 else:
709 return "((%s)%s)" % (
710 self.type.declaration_code(""),
711 self.entry.cname)
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")
716 entry = self.entry
717 if entry is None:
718 return # There was an error earlier
719 if entry.is_pyglobal or entry.is_builtin:
720 if entry.is_builtin:
721 namespace = Naming.builtins_cname
722 else: # entry.is_pyglobal
723 namespace = entry.namespace_cname
724 code.putln(
725 '%s = __Pyx_GetName(%s, "%s"); if (!%s) %s' % (
726 self.result,
727 namespace,
728 self.entry.name,
729 self.result,
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
737 code.putln(
738 'if (PyObject_SetAttrString(%s, "%s", %s) < 0) %s' % (
739 namespace,
740 self.entry.name,
741 rhs.result,
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)
747 else:
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")
762 return
763 code.putln(
764 'if (PyObject_DelAttrString(%s, "%s") < 0) %s' % (
765 Naming.module_cname,
766 self.entry.name,
767 code.error_goto(self.pos)))
770 class BackquoteNode(ExprNode):
771 # `expr`
773 # arg ExprNode
775 subexprs = ['arg']
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
781 self.is_temp = 1
783 def generate_result_code(self, code):
784 code.putln(
785 "%s = PyObject_Repr(%s); if (!%s) %s" % (
786 self.result,
787 self.arg.result,
788 self.result,
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)
805 if self.name_list:
806 self.name_list.analyse_types(env)
807 self.type = PyrexTypes.py_object_type
808 self.is_temp = 1
809 env.use_utility_code(import_utility_code)
811 def generate_result_code(self, code):
812 if self.name_list:
813 name_list_code = self.name_list.result
814 else:
815 name_list_code = "0"
816 code.putln(
817 "%s = __Pyx_Import(%s, %s); if (!%s) %s" % (
818 self.result,
819 self.module_name.result,
820 name_list_code,
821 self.result,
822 code.error_goto(self.pos)))
825 class IteratorNode(ExprNode):
826 # Used as part of for statement implementation.
827 # Implements result = iter(sequence)
829 # sequence ExprNode
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
837 self.is_temp = 1
839 def generate_result_code(self, code):
840 code.putln(
841 "%s = PyObject_GetIter(%s); if (!%s) %s" % (
842 self.result,
843 self.sequence.result,
844 self.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.
854 # iterator ExprNode
856 def __init__(self, iterator, env):
857 self.pos = iterator.pos
858 self.iterator = iterator
859 self.type = PyrexTypes.py_object_type
860 self.is_temp = 1
862 def generate_result_code(self, code):
863 code.putln(
864 "%s = PyIter_Next(%s);" % (
865 self.result,
866 self.iterator.result))
867 code.putln(
868 "if (!%s) {" %
869 self.result)
870 code.putln(
871 "if (PyErr_Occurred()) %s" %
872 code.error_goto(self.pos))
873 code.putln(
874 "break;")
875 code.putln(
876 "}")
879 class ExcValueNode(AtomicExprNode):
880 # Node created during analyse_types phase
881 # of an ExceptClauseNode to fetch the current
882 # exception value.
884 def __init__(self, pos, env):
885 ExprNode.__init__(self, pos)
886 self.type = PyrexTypes.py_object_type
887 self.is_temp = 1
888 env.use_utility_code(get_exception_utility_code)
890 def generate_result_code(self, code):
891 code.putln(
892 "%s = __Pyx_GetExcValue(); if (!%s) %s" % (
893 self.result,
894 self.result,
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)
904 self.type = type
905 self.is_temp = 1
907 def generate_result_code(self, code):
908 pass
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 #-------------------------------------------------------------------
920 # Trailer nodes
922 #-------------------------------------------------------------------
924 class IndexNode(ExprNode):
925 # Sequence indexing.
927 # base ExprNode
928 # index ExprNode
930 subexprs = ['base', 'index']
932 def analyse_target_declaration(self, env):
933 pass
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
941 self.is_temp = 1
942 else:
943 if self.base.type.is_ptr or self.base.type.is_array:
944 self.type = self.base.type.base_type
945 else:
946 error(self.pos,
947 "Attempting to index non-array type '%s'" %
948 self.base.type)
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:
954 error(self.pos,
955 "Invalid index type '%s'" %
956 self.index.type)
958 def check_const_addr(self):
959 self.base.check_const_addr()
960 self.index.check_const()
962 def is_lvalue(self):
963 return 1
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:
971 code.putln(
972 "%s = PyObject_GetItem(%s, %s); if (!%s) %s" % (
973 self.result,
974 self.base.result,
975 self.index.result,
976 self.result,
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:
982 code.putln(
983 "if (PyObject_SetItem(%s, %s, %s) < 0) %s" % (
984 self.base.result,
985 self.index.result,
986 rhs.result,
987 code.error_goto(self.pos)))
988 self.generate_subexpr_disposal_code(code)
989 else:
990 code.putln(
991 "%s = %s;" % (
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)
997 code.putln(
998 "if (PyObject_DelItem(%s, %s) < 0) %s" % (
999 self.base.result,
1000 self.index.result,
1001 code.error_goto(self.pos)))
1002 self.generate_subexpr_disposal_code(code)
1005 class SliceIndexNode(ExprNode):
1006 # 2-element slice indexing
1008 # base ExprNode
1009 # start ExprNode or None
1010 # stop ExprNode or None
1012 subexprs = ['base', 'start', 'stop']
1014 def analyse_target_declaration(self, env):
1015 pass
1017 def analyse_types(self, env):
1018 self.base.analyse_types(env)
1019 if self.start:
1020 self.start.analyse_types(env)
1021 if self.stop:
1022 self.stop.analyse_types(env)
1023 self.base = self.base.coerce_to_pyobject(env)
1024 c_int = PyrexTypes.c_int_type
1025 if self.start:
1026 self.start = self.start.coerce_to(c_int, env)
1027 if self.stop:
1028 self.stop = self.stop.coerce_to(c_int, env)
1029 self.type = PyrexTypes.py_object_type
1030 self.is_temp = 1
1032 def generate_result_code(self, code):
1033 code.putln(
1034 "%s = PySequence_GetSlice(%s, %s, %s); if (!%s) %s" % (
1035 self.result,
1036 self.base.result,
1037 self.start_code(),
1038 self.stop_code(),
1039 self.result,
1040 code.error_goto(self.pos)))
1042 def generate_assignment_code(self, rhs, code):
1043 self.generate_subexpr_evaluation_code(code)
1044 code.putln(
1045 "if (PySequence_SetSlice(%s, %s, %s, %s) < 0) %s" % (
1046 self.base.result,
1047 self.start_code(),
1048 self.stop_code(),
1049 rhs.result,
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)
1056 code.putln(
1057 "if (PySequence_DelSlice(%s, %s, %s) < 0) %s" % (
1058 self.base.result,
1059 self.start_code(),
1060 self.stop_code(),
1061 code.error_goto(self.pos)))
1062 self.generate_subexpr_disposal_code(code)
1064 def start_code(self):
1065 if self.start:
1066 return self.start.result
1067 else:
1068 return "0"
1070 def stop_code(self):
1071 if self.stop:
1072 return self.stop.result
1073 else:
1074 return "0x7fffffff"
1076 def result_code(self):
1077 # self.result is not used, but this method must exist
1078 return "<unused>"
1081 class SliceNode(ExprNode):
1082 # start:stop:step in subscript list
1084 # start ExprNode
1085 # stop ExprNode
1086 # step ExprNode
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
1098 self.is_temp = 1
1100 def generate_result_code(self, code):
1101 code.putln(
1102 "%s = PySlice_New(%s, %s, %s); if (!%s) %s" % (
1103 self.result,
1104 self.start.result,
1105 self.stop.result,
1106 self.step.result,
1107 self.result,
1108 code.error_goto(self.pos)))
1111 class SimpleCallNode(ExprNode):
1112 # Function call without keyword, * or ** args.
1114 # function ExprNode
1115 # args [ExprNode]
1116 # arg_tuple ExprNode used internally
1118 subexprs = ['function', 'args', 'arg_tuple']
1120 arg_tuple = None
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)
1126 self.args = None
1127 self.arg_tuple.analyse_types(env)
1128 self.type = PyrexTypes.py_object_type
1129 self.is_temp = 1
1130 else:
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'" %
1145 func_type)
1146 self.type = PyrexTypes.error_type
1147 self.result = "<error>"
1148 return
1149 # Check no. of args
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
1157 error(self.pos,
1158 "Call with wrong number of arguments (expected %s, got %s)"
1159 % (expected_str, actual_nargs))
1160 self.args = None
1161 self.type = PyrexTypes.error_type
1162 self.result = "<error>"
1163 return
1164 # Coerce arguments
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:
1177 self.is_temp = 1
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:
1187 return "<error>"
1188 formal_args = self.function.type.args
1189 arg_list_code = []
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()
1194 else:
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
1203 return result
1205 def generate_result_code(self, code):
1206 #print_call_chain("SimpleCallNode.generate_result_code") ###
1207 if self.function.type.is_pyobject:
1208 code.putln(
1209 "%s = PyObject_CallObject(%s, %s); if (!%s) %s" % (
1210 self.result,
1211 self.function.result,
1212 self.arg_tuple.result,
1213 self.result,
1214 code.error_goto(self.pos)))
1215 else:
1216 exc_checks = []
1217 if self.type.is_pyobject:
1218 exc_checks.append("!%s" % self.result)
1219 else:
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))
1224 if exc_check:
1225 exc_checks.append("PyErr_Occurred()")
1226 if self.is_temp or exc_checks:
1227 if self.result:
1228 lhs = "%s = " % self.result
1229 else:
1230 lhs = ""
1231 code.putln(
1232 "%s%s; if (%s) %s" % (
1233 lhs,
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.
1243 # function ExprNode
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
1264 self.is_temp = 1
1266 def generate_result_code(self, code):
1267 if self.keyword_args and self.starstar_arg:
1268 code.putln(
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
1278 else:
1279 keyword_code = None
1280 if not keyword_code:
1281 call_code = "PyObject_CallObject(%s, %s)" % (
1282 self.function.result,
1283 self.positional_args.result)
1284 else:
1285 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
1286 self.function.result,
1287 self.positional_args.result,
1288 keyword_code)
1289 code.putln(
1290 "%s = %s; if (!%s) %s" % (
1291 self.result,
1292 call_code,
1293 self.result,
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.
1301 # arg ExprNode
1303 subexprs = ['arg']
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
1309 self.is_temp = 1
1311 def generate_result_code(self, code):
1312 code.putln(
1313 "%s = PySequence_Tuple(%s); if (!%s) %s" % (
1314 self.result,
1315 self.arg.result,
1316 self.result,
1317 code.error_goto(self.pos)))
1320 class AttributeNode(ExprNode):
1321 # obj.attribute
1323 # obj ExprNode
1324 # attribute string
1326 # Used internally:
1328 # is_py_attr boolean Is a Python getattr operation
1329 # member string C name of struct member
1331 subexprs = ['obj']
1333 type = PyrexTypes.error_type
1334 result = "<error>"
1336 def analyse_target_declaration(self, env):
1337 pass
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
1350 # returns 0.
1351 module_scope = self.obj.analyse_as_module(env)
1352 if module_scope:
1353 entry = module_scope.lookup_here(self.attribute)
1354 if entry and (
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
1359 self.entry = entry
1360 del self.obj
1361 del self.attribute
1362 if target:
1363 NameNode.analyse_target_types(self, env)
1364 else:
1365 NameNode.analyse_entry(self, env)
1366 return 1
1367 return 0
1369 def analyse_as_module(self, env):
1370 module_scope = self.obj.analyse_as_module(env)
1371 if module_scope:
1372 entry = module_scope.lookup_here(self.attribute)
1373 if entry and entry.as_module:
1374 return entry.as_module
1375 return None
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()
1383 if self.is_py_attr:
1384 if not target:
1385 self.is_temp = 1
1387 def analyse_attribute(self, env):
1388 # Look up attribute and set self.type and self.member.
1389 self.is_py_attr = 0
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
1394 if obj_type.is_ptr:
1395 obj_type = obj_type.base_type
1396 self.op = "->"
1397 elif obj_type.is_extension_type:
1398 self.op = "->"
1399 else:
1400 self.op = "."
1401 if obj_type.has_attributes:
1402 entry = None
1403 if obj_type.attributes_known():
1404 entry = obj_type.scope.lookup_here(self.attribute)
1405 else:
1406 error(self.pos,
1407 "Cannot select attribute of incomplete type '%s'"
1408 % obj_type)
1409 obj_type = PyrexTypes.error_type
1410 if entry:
1411 if entry.is_variable:
1412 self.type = entry.type
1413 self.member = entry.cname
1414 return
1415 else:
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.
1418 pass
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
1422 # reference.
1423 if obj_type.is_pyobject:
1424 self.type = PyrexTypes.py_object_type
1425 self.is_py_attr = 1
1426 else:
1427 if not obj_type.is_error:
1428 error(self.pos,
1429 "Object of type '%s' has no attribute '%s'" %
1430 (obj_type, self.attribute))
1432 def is_simple(self):
1433 if self.obj:
1434 return self.result_in_temp() or self.obj.is_simple()
1435 else:
1436 return NameNode.is_simple(self)
1438 def is_lvalue(self):
1439 if self.obj:
1440 return 1
1441 else:
1442 return NameNode.is_lvalue(self)
1444 def is_ephemeral(self):
1445 if self.obj:
1446 return ExprNode.is_ephemeral(self)
1447 else:
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
1460 return 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(""),
1468 # obj_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):
1473 if self.is_py_attr:
1474 code.putln(
1475 '%s = PyObject_GetAttrString(%s, "%s"); if (!%s) %s' % (
1476 self.result,
1477 self.obj.result,
1478 self.attribute,
1479 self.result,
1480 code.error_goto(self.pos)))
1481 #elif self.type.is_pyobject:
1482 # code.put("%s = %s; " % (
1483 # self.result,
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)
1489 if self.is_py_attr:
1490 code.putln(
1491 'if (PyObject_SetAttrString(%s, "%s", %s) < 0) %s' % (
1492 self.obj.result,
1493 self.attribute,
1494 rhs.result,
1495 code.error_goto(self.pos)))
1496 rhs.generate_disposal_code(code)
1497 else:
1498 select_code = self.select_code()
1499 if self.type.is_pyobject:
1500 rhs.make_owned_reference(code)
1501 code.put_decref(select_code)
1502 code.putln(
1503 "%s = %s;" % (
1504 select_code,
1505 rhs.result))
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)
1511 if self.is_py_attr:
1512 code.putln(
1513 'if (PyObject_DelAttrString(%s, "%s") < 0) %s' % (
1514 self.obj.result,
1515 self.attribute,
1516 code.error_goto(self.pos)))
1517 else:
1518 error(self.pos, "Cannot delete C attribute of extension type")
1519 self.obj.generate_disposal_code(code)
1521 #-------------------------------------------------------------------
1523 # Constructor nodes
1525 #-------------------------------------------------------------------
1527 class SequenceNode(ExprNode):
1528 # Base class for list and tuple constructor nodes.
1529 # Contains common code for performing sequence unpacking.
1531 # args [ExprNode]
1532 # unpacked_items [ExprNode] or None
1533 # coerced_unpacked_items [ExprNode] or None
1535 subexprs = ['args']
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)):
1546 arg = self.args[i]
1547 arg.analyse_types(env)
1548 self.args[i] = arg.coerce_to_pyobject(env)
1549 self.type = PyrexTypes.py_object_type
1550 self.is_temp = 1
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
1583 code.putln(
1584 "%s = __Pyx_UnpackItem(%s, %s); if (!%s) %s" % (
1585 unpack_result,
1586 rhs.result,
1588 unpack_result,
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)
1593 code.putln(
1594 "if (__Pyx_EndUnpack(%s, %s) < 0) %s" % (
1595 rhs.result,
1596 len(self.args),
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):
1608 code.putln(
1609 "%s = PyTuple_New(%s); if (!%s) %s" % (
1610 self.result,
1611 len(self.args),
1612 self.result,
1613 code.error_goto(self.pos)))
1614 for i in range(len(self.args)):
1615 arg = self.args[i]
1616 if not arg.result_in_temp():
1617 code.put_incref(arg.result)
1618 code.putln(
1619 "PyTuple_SET_ITEM(%s, %s, %s);" % (
1620 self.result,
1622 arg.result))
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):
1633 # List constructor.
1635 def generate_operation_code(self, code):
1636 code.putln("%s = PyList_New(%s); if (!%s) %s" %
1637 (self.result,
1638 len(self.args),
1639 self.result,
1640 code.error_goto(self.pos)))
1641 for i in range(len(self.args)):
1642 arg = self.args[i]
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);" %
1647 (self.result,
1649 arg.result))
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):
1665 new_pairs = []
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
1674 self.is_temp = 1
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.
1689 code.putln(
1690 "%s = PyDict_New(); if (!%s) %s" % (
1691 self.result,
1692 self.result,
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)
1697 code.putln(
1698 "if (PyDict_SetItem(%s, %s, %s) < 0) %s" % (
1699 self.result,
1700 key.result,
1701 value.result,
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)
1723 if self.doc:
1724 self.doc.analyse_types(env)
1725 self.doc = self.doc.coerce_to_pyobject(env)
1726 self.type = PyrexTypes.py_object_type
1727 self.is_temp = 1
1729 def generate_result_code(self, code):
1730 if self.doc:
1731 code.putln(
1732 'if (PyDict_SetItemString(%s, "__doc__", %s) < 0) %s' % (
1733 self.dict.result,
1734 self.doc.result,
1735 code.error_goto(self.pos)))
1736 code.putln(
1737 '%s = PyClass_New(%s, %s, %s); if (!%s) %s' % (
1738 self.result,
1739 self.bases.result,
1740 self.dict.result,
1741 self.name.result,
1742 self.result,
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
1759 self.is_temp = 1
1761 def generate_result_code(self, code):
1762 code.putln(
1763 "%s = PyMethod_New(%s, 0, %s); if (!%s) %s" % (
1764 self.result,
1765 self.function.result,
1766 self.class_cname,
1767 self.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
1780 self.is_temp = 1
1782 def generate_result_code(self, code):
1783 code.putln(
1784 "%s = PyCFunction_New(&%s, 0); if (!%s) %s" % (
1785 self.result,
1786 self.pymethdef_cname,
1787 self.result,
1788 code.error_goto(self.pos)))
1790 #-------------------------------------------------------------------
1792 # Unary operator nodes
1794 #-------------------------------------------------------------------
1796 class UnopNode(ExprNode):
1797 # operator string
1798 # operand 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
1815 self.is_temp = 1
1816 else:
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)
1831 else:
1832 if self.is_temp:
1833 self.generate_c_operation_code(code)
1835 def generate_py_operation_code(self, code):
1836 function = self.py_operation_function()
1837 code.putln(
1838 "%s = %s(%s); if (!%s) %s" % (
1839 self.result,
1840 function,
1841 self.operand.result,
1842 self.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):
1853 # 'not' operator
1855 # operand 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):
1868 pass
1871 class UnaryPlusNode(UnopNode):
1872 # unary '+' operator
1874 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
1889 operator = '-'
1891 def analyse_c_operation(self, env):
1892 if self.operand.type.is_numeric:
1893 self.type = self.operand.type
1894 else:
1895 self.type_error()
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
1910 else:
1911 self.type_error()
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.
1923 # operand ExprNode
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")
1932 return
1933 if argtype.is_pyobject:
1934 self.error("Cannot take address of Python variable")
1935 return
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):
1950 pass
1953 unop_node_classes = {
1954 "+": UnaryPlusNode,
1955 "-": UnaryMinusNode,
1956 "~": TildeNode,
1959 def unop_node(pos, operator, operand):
1960 # Construct unnop node of appropriate class for
1961 # given operator.
1962 return unop_node_classes[operator](pos,
1963 operator = operator,
1964 operand = operand)
1967 class TypecastNode(ExprNode):
1968 # C type cast
1970 # base_type CBaseTypeNode
1971 # declarator CDeclaratorNode
1972 # operand ExprNode
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")
1984 #if to_py:
1985 if to_py and not from_py:
1986 self.is_temp = 1
1988 def check_const(self):
1989 self.operand.check_const()
1991 def result_code(self):
1992 if self.type.is_pyobject:
1993 cast = "PyObject *"
1994 else:
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):
2004 if self.is_temp:
2005 code.putln(
2006 "%s = (PyObject *)%s;" % (
2007 self.result,
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):
2017 pass
2019 def generate_result_code(self, code):
2020 pass
2023 class SizeofTypeNode(SizeofNode):
2024 # C sizeof function applied to a type
2026 # base_type CBaseTypeNode
2027 # declarator CDeclaratorNode
2029 subexprs = []
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
2051 # operand ExprNode
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):
2063 pass
2066 #-------------------------------------------------------------------
2068 # Binary operator nodes
2070 #-------------------------------------------------------------------
2072 class BinopNode(ExprNode):
2073 # operator string
2074 # operand1 ExprNode
2075 # operand2 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
2093 self.is_temp = 1
2094 else:
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"
2114 else:
2115 extra_args = ""
2116 code.putln(
2117 "%s = %s(%s, %s%s); if (!%s) %s" % (
2118 self.result,
2119 function,
2120 self.operand1.result,
2121 self.operand2.result,
2122 extra_args,
2123 self.result,
2124 code.error_goto(self.pos)))
2125 else:
2126 if self.is_temp:
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)
2145 if not self.type:
2146 self.type_error()
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)
2151 else:
2152 return None
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,
2160 self.operator,
2161 self.operand2.result)
2163 def py_operation_function(self):
2164 return self.py_functions[self.operator]
2166 py_functions = {
2167 "|": "PyNumber_Or",
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):
2189 # '+' operator.
2191 def is_py_operation(self):
2192 if self.operand1.type.is_string \
2193 and self.operand2.type.is_string:
2194 return 1
2195 else:
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:
2200 return type1
2201 elif type1.is_int and type2.is_ptr:
2202 return type2
2203 else:
2204 return NumBinopNode.compute_c_result_type(
2205 self, type1, type2)
2208 class SubNode(NumBinopNode):
2209 # '-' operator.
2211 def compute_c_result_type(self, type1, type2):
2212 if type1.is_ptr and type2.is_int:
2213 return type1
2214 elif type1.is_ptr and type2.is_ptr:
2215 return PyrexTypes.c_int_type
2216 else:
2217 return NumBinopNode.compute_c_result_type(
2218 self, type1, type2)
2221 class MulNode(NumBinopNode):
2222 # '*' operator.
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):
2229 return 1
2230 else:
2231 return NumBinopNode.is_py_operation(self)
2234 class ModNode(IntBinopNode):
2235 # '%' operator.
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):
2244 # '**' operator.
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
2253 else:
2254 return None
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.
2264 # operator string
2265 # operand1 ExprNode
2266 # operand2 ExprNode
2267 # temp_bool ExprNode used internally
2269 temp_bool = None
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
2283 else:
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)
2294 self.is_temp = 1
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
2303 # be necessary.
2304 self.allocate_temp(env, result)
2305 self.operand1.allocate_temps(env, self.result)
2306 if self.temp_bool:
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
2316 # be released.
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':
2334 sense = ""
2335 else:
2336 sense = "!"
2337 code.putln(
2338 "if (%s%s) {" % (
2339 sense,
2340 test_result))
2341 self.operand1.generate_disposal_code(code)
2342 self.operand2.generate_evaluation_code(code)
2343 code.putln(
2344 "}")
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
2350 code.putln(
2351 "%s = PyObject_IsTrue(%s); if (%s < 0) %s" % (
2352 test_result,
2353 self.operand1.result,
2354 test_result,
2355 code.error_goto(self.pos)))
2356 else:
2357 test_result = self.operand1.result
2358 return test_result
2361 class CmpNode:
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:
2379 return 1
2380 if type1.is_pyobject: # type2 will be, too
2381 return 1
2382 elif type1.is_ptr:
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')):
2387 return 1
2388 else:
2389 return 0
2391 def generate_operation_code(self, code, result,
2392 operand1, op , operand2):
2393 if op == 'in' or op == 'not_in':
2394 code.putln(
2395 "%s = PySequence_Contains(%s, %s); if (%s < 0) %s" % (
2396 result,
2397 operand2.result,
2398 operand1.result,
2399 result,
2400 code.error_goto(self.pos)))
2401 if op == 'not_in':
2402 code.putln(
2403 "%s = !%s;" % (
2404 result, result))
2405 elif (operand1.type.is_pyobject
2406 and op not in ('is', 'is_not')):
2407 code.putln(
2408 "if (PyObject_Cmp(%s, %s, &%s) < 0) %s" % (
2409 operand1.result,
2410 operand2.result,
2411 result,
2412 code.error_goto(self.pos)))
2413 code.putln(
2414 "%s = %s %s 0;" % (
2415 result, result, op))
2416 else:
2417 code.putln("%s = %s %s %s;" % (
2418 result,
2419 operand1.result,
2420 self.c_operator(op),
2421 operand2.result))
2423 def c_operator(self, op):
2424 if op == 'is':
2425 return "=="
2426 elif op == 'is_not':
2427 return "!="
2428 else:
2429 return op
2432 class PrimaryCmpNode(ExprNode, CmpNode):
2433 # Non-cascaded comparison or first comparison of
2434 # a cascaded sequence.
2436 # operator string
2437 # operand1 ExprNode
2438 # operand2 ExprNode
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
2444 # which use it.
2446 cascade = None
2448 def analyse_types(self, env):
2449 self.operand1.analyse_types(env)
2450 self.operand2.analyse_types(env)
2451 if self.cascade:
2452 self.cascade.analyse_types(env, self.operand2)
2453 self.is_pycmp = self.is_python_comparison()
2454 if self.is_pycmp:
2455 self.coerce_operands_to_pyobjects(env)
2456 if self.cascade:
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:
2463 self.is_temp = 1
2465 def check_operand_types(self, env):
2466 self.check_types(env,
2467 self.operand1, self.operator, self.operand2)
2468 if self.cascade:
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)
2478 if self.cascade:
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)
2484 if self.cascade:
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)
2490 if self.cascade:
2491 self.cascade.release_subexpr_temps(env)
2493 def check_const(self):
2494 self.operand1.check_const()
2495 self.operand2.check_const()
2496 if self.cascade:
2497 self.not_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)
2508 if self.is_temp:
2509 self.generate_operation_code(code, self.result,
2510 self.operand1, self.operator, self.operand2)
2511 if self.cascade:
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.
2530 # operator string
2531 # operand2 ExprNode
2532 # cascade CascadedCmpNode
2534 cascade = None
2536 def analyse_types(self, env, operand1):
2537 self.operand2.analyse_types(env)
2538 if self.cascade:
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)
2544 if self.cascade:
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)
2552 if self.cascade:
2553 self.cascade.coerce_operands_to_pyobjects(env)
2555 def coerce_cascaded_operands_to_temp(self, env):
2556 if self.cascade:
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)
2563 if self.cascade:
2564 self.cascade.allocate_subexpr_temps(env)
2566 def release_subexpr_temps(self, env):
2567 self.operand2.release_temp(env)
2568 if self.cascade:
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)
2576 if self.cascade:
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)
2581 code.putln("}")
2584 binop_node_classes = {
2585 "or": BoolBinopNode,
2586 "and": BoolBinopNode,
2587 "|": IntBinopNode,
2588 "^": IntBinopNode,
2589 "&": IntBinopNode,
2590 "<<": IntBinopNode,
2591 ">>": IntBinopNode,
2592 "+": AddNode,
2593 "-": SubNode,
2594 "*": MulNode,
2595 "/": NumBinopNode,
2596 "%": ModNode,
2597 "**": PowNode
2600 def binop_node(pos, operator, operand1, operand2):
2601 # Construct binop node of appropriate class for
2602 # given operator.
2603 return binop_node_classes[operator](pos,
2604 operator = operator,
2605 operand1 = operand1,
2606 operand2 = operand2)
2608 #-------------------------------------------------------------------
2610 # Coercion nodes
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
2615 # of that phase.
2617 #-------------------------------------------------------------------
2619 class CoercionNode(ExprNode):
2620 # Abstract base class for coercion nodes.
2622 # arg ExprNode node being coerced
2624 subexprs = ['arg']
2626 def __init__(self, arg):
2627 self.pos = arg.pos
2628 self.arg = arg
2629 if debug_coercion:
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(""),
2657 self.arg.result)
2659 def generate_result_code(self, code):
2660 if self.type.typeobj_is_available():
2661 code.putln(
2662 "if (!__Pyx_TypeTest(%s, %s)) %s" % (
2663 self.result,
2664 self.type.typeptr_cname,
2665 code.error_goto(self.pos)))
2666 else:
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:
2682 error(arg.pos,
2683 "Cannot convert '%s' to Python object" % arg.type)
2684 self.is_temp = 1
2686 def generate_result_code(self, code):
2687 function = self.arg.type.to_py_function
2688 code.putln('%s = %s(%s); if (!%s) %s' % (
2689 self.result,
2690 function,
2691 self.arg.result,
2692 self.result,
2693 code.error_goto(self.pos)))
2696 class CoerceFromPyTypeNode(CoercionNode):
2697 # This node is used to convert a Python object
2698 # to a C data type.
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:
2704 error(arg.pos,
2705 "Cannot convert Python object to '%s'" % result_type)
2706 if self.type.is_string and self.arg.is_ephemeral():
2707 error(arg.pos,
2708 "Obtaining char * from temporary Python value")
2709 self.is_temp = 1
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' % (
2715 self.result,
2716 function,
2717 self.arg.result,
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:
2729 self.is_temp = 1
2731 def check_const(self):
2732 if self.is_temp:
2733 self.not_const()
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:
2741 code.putln(
2742 "%s = PyObject_IsTrue(%s); if (%s < 0) %s" % (
2743 self.result,
2744 self.arg.result,
2745 self.result,
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):
2760 # pass
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
2771 self.is_temp = 1
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):
2800 pass
2803 #------------------------------------------------------------------------------------
2805 # Runtime support code
2807 #------------------------------------------------------------------------------------
2809 get_name_utility_code = \
2811 static PyObject *__Pyx_GetName(PyObject *dict, char *name) {
2812 PyObject *result;
2813 result = PyObject_GetAttrString(dict, name);
2814 if (!result)
2815 PyErr_SetString(PyExc_NameError, name);
2816 return result;
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;
2830 PyObject *list;
2831 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
2832 if (!__import__)
2833 goto bad;
2834 if (from_list)
2835 list = from_list;
2836 else {
2837 empty_list = PyList_New(0);
2838 if (!empty_list)
2839 goto bad;
2840 list = empty_list;
2842 global_dict = PyModule_GetDict(%(GLOBALS)s);
2843 if (!global_dict)
2844 goto bad;
2845 empty_dict = PyDict_New();
2846 if (!empty_dict)
2847 goto bad;
2848 module = PyObject_CallFunction(__import__, "OOOO",
2849 name, global_dict, empty_dict, list);
2850 bad:
2851 Py_XDECREF(empty_list);
2852 Py_XDECREF(__import__);
2853 Py_XDECREF(empty_dict);
2854 return module;
2856 """ % {
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())
2872 goto bad;
2873 if (!value) {
2874 value = Py_None;
2875 Py_INCREF(value);
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;
2883 result = value;
2884 Py_XINCREF(result);
2885 type = 0;
2886 value = 0;
2887 tb = 0;
2888 bad:
2889 Py_XDECREF(type);
2890 Py_XDECREF(value);
2891 Py_XDECREF(tb);
2892 return result;
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) {
2905 PyObject *item;
2906 if (!(item = PySequence_GetItem(seq, i))) {
2907 if (PyErr_ExceptionMatches(PyExc_IndexError))
2908 __Pyx_UnpackError();
2910 return item;
2913 static int __Pyx_EndUnpack(PyObject *seq, int i) {
2914 PyObject *item;
2915 if (item = PySequence_GetItem(seq, i)) {
2916 Py_DECREF(item);
2917 __Pyx_UnpackError();
2918 return -1;
2920 PyErr_Clear();
2921 return 0;
2925 #------------------------------------------------------------------------------------
2927 type_test_utility_code = \
2929 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
2930 if (!type) {
2931 PyErr_Format(PyExc_SystemError, "Missing type object");
2932 return 0;
2934 if (obj == Py_None || PyObject_TypeCheck(obj, type))
2935 return 1;
2936 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
2937 obj->ob_type->tp_name, type->tp_name);
2938 return 0;
2942 #------------------------------------------------------------------------------------