invalidate the cache of all subtypes when updating a type's tp_dict (algorithm copied...
[cython.git] / Cython / Compiler / ExprNodes.py
1 #
2 #   Pyrex - Parse tree nodes for expressions
3 #
4
5 import operator
6 from string import join
7
8 from Errors import error, warning, InternalError
9 import Naming
10 from Nodes import Node
11 import PyrexTypes
12 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
13 from Builtin import list_type, tuple_type, dict_type
14 import Symtab
15 import Options
16 from Annotate import AnnotationItem
17
18 from Cython.Debugging import print_call_chain
19 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
20     debug_coercion
21
22
23 class ExprNode(Node):
24     #  subexprs     [string]     Class var holding names of subexpr node attrs
25     #  type         PyrexType    Type of the result
26     #  result_code  string       Code fragment
27     #  result_ctype string       C type of result_code if different from type
28     #  is_temp      boolean      Result is in a temporary variable
29     #  is_sequence_constructor  
30     #               boolean      Is a list or tuple constructor expression
31     #  saved_subexpr_nodes
32     #               [ExprNode or [ExprNode or None] or None]
33     #                            Cached result of subexpr_nodes()
34     
35     result_ctype = None
36     type = None
37
38     #  The Analyse Expressions phase for expressions is split
39     #  into two sub-phases:
40     #
41     #    Analyse Types
42     #      Determines the result type of the expression based
43     #      on the types of its sub-expressions, and inserts
44     #      coercion nodes into the expression tree where needed.
45     #      Marks nodes which will need to have temporary variables
46     #      allocated.
47     #
48     #    Allocate Temps
49     #      Allocates temporary variables where needed, and fills
50     #      in the result_code field of each node.
51     #
52     #  ExprNode provides some convenience routines which
53     #  perform both of the above phases. These should only
54     #  be called from statement nodes, and only when no
55     #  coercion nodes need to be added around the expression
56     #  being analysed. In that case, the above two phases
57     #  should be invoked separately.
58     #
59     #  Framework code in ExprNode provides much of the common
60     #  processing for the various phases. It makes use of the
61     #  'subexprs' class attribute of ExprNodes, which should
62     #  contain a list of the names of attributes which can
63     #  hold sub-nodes or sequences of sub-nodes.
64     #  
65     #  The framework makes use of a number of abstract methods. 
66     #  Their responsibilities are as follows.
67     #
68     #    Declaration Analysis phase
69     #
70     #      analyse_target_declaration
71     #        Called during the Analyse Declarations phase to analyse
72     #        the LHS of an assignment or argument of a del statement.
73     #        Nodes which cannot be the LHS of an assignment need not
74     #        implement it.
75     #
76     #    Expression Analysis phase
77     #
78     #      analyse_types
79     #        - Call analyse_types on all sub-expressions.
80     #        - Check operand types, and wrap coercion nodes around
81     #          sub-expressions where needed.
82     #        - Set the type of this node.
83     #        - If a temporary variable will be required for the
84     #          result, set the is_temp flag of this node.
85     #
86     #      analyse_target_types
87     #        Called during the Analyse Types phase to analyse
88     #        the LHS of an assignment or argument of a del 
89     #        statement. Similar responsibilities to analyse_types.
90     #
91     #      allocate_temps
92     #        - Call allocate_temps for all sub-nodes.
93     #        - Call allocate_temp for this node.
94     #        - If a temporary was allocated, call release_temp on 
95     #          all sub-expressions.
96     #
97     #      allocate_target_temps
98     #        - Call allocate_temps on sub-nodes and allocate any other
99     #          temps used during assignment.
100     #        - Fill in result_code with a C lvalue if needed.
101     #        - If a rhs node is supplied, call release_temp on it.
102     #        - Call release_temp on sub-nodes and release any other
103     #          temps used during assignment.
104     #
105     #      calculate_result_code
106     #        - Called during the Allocate Temps phase. Should return a
107     #          C code fragment evaluating to the result. This is only
108     #          called when the result is not a temporary.
109     #
110     #      target_code
111     #        Called by the default implementation of allocate_target_temps.
112     #        Should return a C lvalue for assigning to the node. The default
113     #        implementation calls calculate_result_code.
114     #
115     #      check_const
116     #        - Check that this node and its subnodes form a
117     #          legal constant expression. If so, do nothing,
118     #          otherwise call not_const. 
119     #
120     #        The default implementation of check_const 
121     #        assumes that the expression is not constant.
122     #
123     #      check_const_addr
124     #        - Same as check_const, except check that the
125     #          expression is a C lvalue whose address is
126     #          constant. Otherwise, call addr_not_const.
127     #
128     #        The default implementation of calc_const_addr
129     #        assumes that the expression is not a constant 
130     #        lvalue.
131     #
132     #   Code Generation phase
133     #
134     #      generate_evaluation_code
135     #        - Call generate_evaluation_code for sub-expressions.
136     #        - Perform the functions of generate_result_code
137     #          (see below).
138     #        - If result is temporary, call generate_disposal_code
139     #          on all sub-expressions.
140     #
141     #        A default implementation of generate_evaluation_code
142     #        is provided which uses the following abstract method:
143     #
144     #          generate_result_code
145     #            - Generate any C statements necessary to calculate
146     #              the result of this node from the results of its
147     #              sub-expressions.
148     #
149     #      generate_assignment_code
150     #        Called on the LHS of an assignment.
151     #        - Call generate_evaluation_code for sub-expressions.
152     #        - Generate code to perform the assignment.
153     #        - If the assignment absorbed a reference, call
154     #          generate_post_assignment_code on the RHS,
155     #          otherwise call generate_disposal_code on it.
156     #
157     #      generate_deletion_code
158     #        Called on an argument of a del statement.
159     #        - Call generate_evaluation_code for sub-expressions.
160     #        - Generate code to perform the deletion.
161     #        - Call generate_disposal_code on all sub-expressions.
162     #
163     #
164     
165     is_sequence_constructor = 0
166     is_attribute = 0
167     
168     saved_subexpr_nodes = None
169     is_temp = 0
170
171     def get_child_attrs(self):
172         """Automatically provide the contents of subexprs as children, unless child_attr
173         has been declared. See Nodes.Node.get_child_accessors."""
174         if self.child_attrs is not None:
175             return self.child_attrs
176         elif self.subexprs is not None:
177             return self.subexprs
178         
179     def not_implemented(self, method_name):
180         print_call_chain(method_name, "not implemented") ###
181         raise InternalError(
182             "%s.%s not implemented" %
183                 (self.__class__.__name__, method_name))         
184                 
185     def is_lvalue(self):
186         return 0
187     
188     def is_ephemeral(self):
189         #  An ephemeral node is one whose result is in
190         #  a Python temporary and we suspect there are no
191         #  other references to it. Certain operations are
192         #  disallowed on such values, since they are
193         #  likely to result in a dangling pointer.
194         return self.type.is_pyobject and self.is_temp
195
196     def subexpr_nodes(self):
197         #  Extract a list of subexpression nodes based
198         #  on the contents of the subexprs class attribute.
199         if self.saved_subexpr_nodes is None:
200             nodes = []
201             for name in self.subexprs:
202                 item = getattr(self, name)
203                 if item:
204                     if isinstance(item, ExprNode):
205                         nodes.append(item)
206                     else:
207                         nodes.extend(item)
208             self.saved_subexpr_nodes = nodes
209         return self.saved_subexpr_nodes
210     
211     def result_as(self, type = None):
212         #  Return the result code cast to the specified C type.
213         return typecast(type, self.ctype(), self.result_code)
214     
215     def py_result(self):
216         #  Return the result code cast to PyObject *.
217         return self.result_as(py_object_type)
218     
219     def ctype(self):
220         #  Return the native C type of the result (i.e. the
221         #  C type of the result_code expression).
222         return self.result_ctype or self.type
223     
224     def compile_time_value(self, denv):
225         #  Return value of compile-time expression, or report error.
226         error(self.pos, "Invalid compile-time expression")
227     
228     def compile_time_value_error(self, e):
229         error(self.pos, "Error in compile-time expression: %s: %s" % (
230             e.__class__.__name__, e))
231     
232     # ------------- Declaration Analysis ----------------
233     
234     def analyse_target_declaration(self, env):
235         error(self.pos, "Cannot assign to or delete this")
236     
237     # ------------- Expression Analysis ----------------
238     
239     def analyse_const_expression(self, env):
240         #  Called during the analyse_declarations phase of a
241         #  constant expression. Analyses the expression's type,
242         #  checks whether it is a legal const expression,
243         #  and determines its value.
244         self.analyse_types(env)
245         self.allocate_temps(env)
246         self.check_const()
247     
248     def analyse_expressions(self, env):
249         #  Convenience routine performing both the Type
250         #  Analysis and Temp Allocation phases for a whole 
251         #  expression.
252         self.analyse_types(env)
253         self.allocate_temps(env)
254     
255     def analyse_target_expression(self, env, rhs):
256         #  Convenience routine performing both the Type
257         #  Analysis and Temp Allocation phases for the LHS of
258         #  an assignment.
259         self.analyse_target_types(env)
260         self.allocate_target_temps(env, rhs)
261     
262     def analyse_boolean_expression(self, env):
263         #  Analyse expression and coerce to a boolean.
264         self.analyse_types(env)
265         bool = self.coerce_to_boolean(env)
266         bool.allocate_temps(env)
267         return bool
268     
269     def analyse_temp_boolean_expression(self, env):
270         #  Analyse boolean expression and coerce result into
271         #  a temporary. This is used when a branch is to be
272         #  performed on the result and we won't have an
273         #  opportunity to ensure disposal code is executed
274         #  afterwards. By forcing the result into a temporary,
275         #  we ensure that all disposal has been done by the
276         #  time we get the result.
277         self.analyse_types(env)
278         bool = self.coerce_to_boolean(env)
279         temp_bool = bool.coerce_to_temp(env)
280         temp_bool.allocate_temps(env)
281         return temp_bool
282     
283     # --------------- Type Analysis ------------------
284     
285     def analyse_as_module(self, env):
286         # If this node can be interpreted as a reference to a
287         # cimported module, return its scope, else None.
288         return None
289     
290     def analyse_as_extension_type(self, env):
291         # If this node can be interpreted as a reference to an
292         # extension type, return its type, else None.
293         return None
294     
295     def analyse_types(self, env):
296         self.not_implemented("analyse_types")
297     
298     def analyse_target_types(self, env):
299         self.analyse_types(env)
300     
301     def check_const(self):
302         self.not_const()
303     
304     def not_const(self):
305         error(self.pos, "Not allowed in a constant expression")
306     
307     def check_const_addr(self):
308         self.addr_not_const()
309     
310     def addr_not_const(self):
311         error(self.pos, "Address is not constant")
312     
313     # ----------------- Result Allocation -----------------
314     
315     def result_in_temp(self):
316         #  Return true if result is in a temporary owned by
317         #  this node or one of its subexpressions. Overridden
318         #  by certain nodes which can share the result of
319         #  a subnode.
320         return self.is_temp
321             
322     def allocate_target_temps(self, env, rhs):
323         #  Perform temp allocation for the LHS of an assignment.
324         if debug_temp_alloc:
325             print("%s Allocating target temps" % self)
326         self.allocate_subexpr_temps(env)
327         self.result_code = self.target_code()
328         if rhs:
329             rhs.release_temp(env)
330         self.release_subexpr_temps(env)
331     
332     def allocate_temps(self, env, result = None):
333         #  Allocate temporary variables for this node and
334         #  all its sub-expressions. If a result is specified,
335         #  this must be a temp node and the specified variable
336         #  is used as the result instead of allocating a new
337         #  one.
338         if debug_temp_alloc:
339             print("%s Allocating temps" % self)
340         self.allocate_subexpr_temps(env)
341         self.allocate_temp(env, result)
342         if self.is_temp:
343             self.release_subexpr_temps(env)
344     
345     def allocate_subexpr_temps(self, env):
346         #  Allocate temporary variables for all sub-expressions
347         #  of this node.
348         if debug_temp_alloc:
349             print("%s Allocating temps for: %s" % (self, self.subexprs))
350         for node in self.subexpr_nodes():
351             if node:
352                 if debug_temp_alloc:
353                     print("%s Allocating temps for %s" % (self, node))
354                 node.allocate_temps(env)
355     
356     def allocate_temp(self, env, result = None):
357         #  If this node requires a temporary variable for its
358         #  result, allocate one, otherwise set the result to
359         #  a C code fragment. If a result is specified,
360         #  this must be a temp node and the specified variable
361         #  is used as the result instead of allocating a new
362         #  one.
363         if debug_temp_alloc:
364             print("%s Allocating temp" % self)
365         if result:
366             if not self.is_temp:
367                 raise InternalError("Result forced on non-temp node")
368             self.result_code = result
369         elif self.is_temp:
370             type = self.type
371             if not type.is_void:
372                 if type.is_pyobject:
373                     type = PyrexTypes.py_object_type
374                 self.result_code = env.allocate_temp(type)
375             else:
376                 self.result_code = None
377             if debug_temp_alloc:
378                 print("%s Allocated result %s" % (self, self.result_code))
379         else:
380             self.result_code = self.calculate_result_code()
381     
382     def target_code(self):
383         #  Return code fragment for use as LHS of a C assignment.
384         return self.calculate_result_code()
385     
386     def calculate_result_code(self):
387         self.not_implemented("calculate_result_code")
388     
389 #       def release_target_temp(self, env):
390 #               #  Release temporaries used by LHS of an assignment.
391 #               self.release_subexpr_temps(env)
392
393     def release_temp(self, env):
394         #  If this node owns a temporary result, release it,
395         #  otherwise release results of its sub-expressions.
396         if self.is_temp:
397             if debug_temp_alloc:
398                 print("%s Releasing result %s" % (self, self.result_code))
399             env.release_temp(self.result_code)
400         else:
401             self.release_subexpr_temps(env)
402     
403     def release_subexpr_temps(self, env):
404         #  Release the results of all sub-expressions of
405         #  this node.
406         for node in self.subexpr_nodes():
407             if node:
408                 node.release_temp(env)
409     
410     # ---------------- Code Generation -----------------
411     
412     def make_owned_reference(self, code):
413         #  If result is a pyobject, make sure we own
414         #  a reference to it.
415         if self.type.is_pyobject and not self.result_in_temp():
416             code.put_incref(self.result_code, self.ctype())
417     
418     def generate_evaluation_code(self, code):
419         code.mark_pos(self.pos)
420         #  Generate code to evaluate this node and
421         #  its sub-expressions, and dispose of any
422         #  temporary results of its sub-expressions.
423         self.generate_subexpr_evaluation_code(code)
424         self.generate_result_code(code)
425         if self.is_temp:
426             self.generate_subexpr_disposal_code(code)
427     
428     def generate_subexpr_evaluation_code(self, code):
429         for node in self.subexpr_nodes():
430             node.generate_evaluation_code(code)
431     
432     def generate_result_code(self, code):
433         self.not_implemented("generate_result_code")
434     
435     def generate_disposal_code(self, code):
436         # If necessary, generate code to dispose of 
437         # temporary Python reference.
438         if self.is_temp:
439             if self.type.is_pyobject:
440                 code.put_decref_clear(self.result_code, self.ctype())
441         else:
442             self.generate_subexpr_disposal_code(code)
443     
444     def generate_subexpr_disposal_code(self, code):
445         #  Generate code to dispose of temporary results
446         #  of all sub-expressions.
447         for node in self.subexpr_nodes():
448             node.generate_disposal_code(code)
449     
450     def generate_post_assignment_code(self, code):
451         # Same as generate_disposal_code except that
452         # assignment will have absorbed a reference to
453         # the result if it is a Python object.
454         if self.is_temp:
455             if self.type.is_pyobject:
456                 code.putln("%s = 0;" % self.result_code)
457         else:
458             self.generate_subexpr_disposal_code(code)
459     
460     def generate_assignment_code(self, rhs, code):
461         #  Stub method for nodes which are not legal as
462         #  the LHS of an assignment. An error will have 
463         #  been reported earlier.
464         pass
465     
466     def generate_deletion_code(self, code):
467         #  Stub method for nodes that are not legal as
468         #  the argument of a del statement. An error
469         #  will have been reported earlier.
470         pass
471     
472     # ---------------- Annotation ---------------------
473     
474     def annotate(self, code):
475         for node in self.subexpr_nodes():
476             node.annotate(code)
477     
478     # ----------------- Coercion ----------------------
479     
480     def coerce_to(self, dst_type, env):
481         #   Coerce the result so that it can be assigned to
482         #   something of type dst_type. If processing is necessary,
483         #   wraps this node in a coercion node and returns that.
484         #   Otherwise, returns this node unchanged.
485         #
486         #   This method is called during the analyse_expressions
487         #   phase of the src_node's processing.
488         src = self
489         src_type = self.type
490         src_is_py_type = src_type.is_pyobject
491         dst_is_py_type = dst_type.is_pyobject
492         
493         if dst_type.is_pyobject:
494             if not src.type.is_pyobject:
495                 src = CoerceToPyTypeNode(src, env)
496             if not src.type.subtype_of(dst_type):
497                 if not isinstance(src, NoneNode):
498                     src = PyTypeTestNode(src, dst_type, env)
499         elif src.type.is_pyobject:
500             src = CoerceFromPyTypeNode(dst_type, src, env)
501         else: # neither src nor dst are py types
502             # Added the string comparison, since for c types that
503             # is enough, but Cython gets confused when the types are
504             # in different files.
505             if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
506                 error(self.pos, "Cannot assign type '%s' to '%s'" %
507                     (src.type, dst_type))
508         return src
509
510     def coerce_to_pyobject(self, env):
511         return self.coerce_to(PyrexTypes.py_object_type, env)
512
513     def coerce_to_boolean(self, env):
514         #  Coerce result to something acceptable as
515         #  a boolean value.
516         type = self.type
517         if type.is_pyobject or type.is_ptr or type.is_float:
518             return CoerceToBooleanNode(self, env)
519         else:
520             if not type.is_int and not type.is_error:
521                 error(self.pos, 
522                     "Type '%s' not acceptable as a boolean" % type)
523             return self
524     
525     def coerce_to_integer(self, env):
526         # If not already some C integer type, coerce to longint.
527         if self.type.is_int:
528             return self
529         else:
530             return self.coerce_to(PyrexTypes.c_long_type, env)
531     
532     def coerce_to_temp(self, env):
533         #  Ensure that the result is in a temporary.
534         if self.result_in_temp():
535             return self
536         else:
537             return CoerceToTempNode(self, env)
538     
539     def coerce_to_simple(self, env):
540         #  Ensure that the result is simple (see is_simple).
541         if self.is_simple():
542             return self
543         else:
544             return self.coerce_to_temp(env)
545     
546     def is_simple(self):
547         #  A node is simple if its result is something that can
548         #  be referred to without performing any operations, e.g.
549         #  a constant, local var, C global var, struct member
550         #  reference, or temporary.
551         return self.result_in_temp()
552
553
554 class AtomicExprNode(ExprNode):
555     #  Abstract base class for expression nodes which have
556     #  no sub-expressions.
557     
558     subexprs = []
559
560
561 class PyConstNode(AtomicExprNode):
562     #  Abstract base class for constant Python values.
563     
564     is_literal = 1
565     
566     def is_simple(self):
567         return 1
568     
569     def analyse_types(self, env):
570         self.type = py_object_type
571     
572     def calculate_result_code(self):
573         return self.value
574
575     def generate_result_code(self, code):
576         pass
577
578
579 class NoneNode(PyConstNode):
580     #  The constant value None
581     
582     value = "Py_None"
583     
584     def compile_time_value(self, denv):
585         return None
586     
587 class BoolNode(PyConstNode):
588     #  The constant value True or False
589     
590     def compile_time_value(self, denv):
591         return self.value
592     
593     def calculate_result_code(self):
594         if self.value:
595             return "Py_True"
596         else:
597             return "Py_False"
598
599     def coerce_to(self, dst_type, env):
600         value = self.value
601         if dst_type.is_numeric:
602             return IntNode(self.pos, value=int(self.value)).coerce_to(dst_type, env)
603         else:
604             return PyConstNode.coerce_to(self, dst_type, env)
605
606 class EllipsisNode(PyConstNode):
607     #  '...' in a subscript list.
608     
609     value = "Py_Ellipsis"
610
611     def compile_time_value(self, denv):
612         return Ellipsis
613
614
615 class ConstNode(AtomicExprNode):
616     # Abstract base type for literal constant nodes.
617     #
618     # value     string      C code fragment
619     
620     is_literal = 1
621     
622     def is_simple(self):
623         return 1
624     
625     def analyse_types(self, env):
626         pass # Types are held in class variables
627     
628     def check_const(self):
629         pass
630     
631     def calculate_result_code(self):
632         return str(self.value)
633
634     def generate_result_code(self, code):
635         pass
636
637
638 class NullNode(ConstNode):
639     type = PyrexTypes.c_null_ptr_type
640     value = "NULL"
641
642
643 class CharNode(ConstNode):
644     type = PyrexTypes.c_char_type
645     
646     def compile_time_value(self, denv):
647         return ord(self.value)
648     
649     def calculate_result_code(self):
650         return "'%s'" % self.value
651
652
653 class IntNode(ConstNode):
654     type = PyrexTypes.c_long_type
655
656     def coerce_to(self, dst_type, env):
657         # Arrange for a Python version of the string to be pre-allocated
658         # when coercing to a Python type.
659         if dst_type.is_pyobject:
660             self.entry = env.get_py_num(self.value)
661             self.type = PyrexTypes.py_object_type
662         # We still need to perform normal coerce_to processing on the
663         # result, because we might be coercing to an extension type,
664         # in which case a type test node will be needed.
665         return ConstNode.coerce_to(self, dst_type, env)
666
667     def calculate_result_code(self):
668         if self.type.is_pyobject:
669             return self.entry.cname
670         else:
671             return str(self.value)
672
673     def compile_time_value(self, denv):
674         return int(self.value, 0)
675
676
677 class FloatNode(ConstNode):
678     type = PyrexTypes.c_double_type
679
680     def compile_time_value(self, denv):
681         return float(self.value)
682     
683     def calculate_result_code(self):
684         strval = str(self.value)
685         if strval == 'nan':
686             return "(Py_HUGE_VAL * 0)"
687         elif strval == 'inf':
688             return "Py_HUGE_VAL"
689         elif strval == '-inf':
690             return "(-Py_HUGE_VAL)"
691         else:
692             return strval
693
694
695 class StringNode(ConstNode):
696     #  entry   Symtab.Entry
697     
698     type = PyrexTypes.c_char_ptr_type
699
700     def compile_time_value(self, denv):
701         return self.value
702     
703     def analyse_types(self, env):
704         self.entry = env.add_string_const(self.value)
705     
706     def coerce_to(self, dst_type, env):
707         if dst_type.is_int:
708             if not self.type.is_pyobject and len(self.entry.init) == 1:
709                 # we use the *encoded* value here
710                 return CharNode(self.pos, value=self.entry.init)
711             else:
712                 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
713                 return self
714         # Arrange for a Python version of the string to be pre-allocated
715         # when coercing to a Python type.
716         if dst_type.is_pyobject and not self.type.is_pyobject:
717             node = self.as_py_string_node(env)
718         else:
719             node = self
720         # We still need to perform normal coerce_to processing on the
721         # result, because we might be coercing to an extension type,
722         # in which case a type test node will be needed.
723         return ConstNode.coerce_to(node, dst_type, env)
724
725     def as_py_string_node(self, env):
726         # Return a new StringNode with the same entry as this node
727         # but whose type is a Python type instead of a C type.
728         entry = self.entry
729         env.add_py_string(entry)
730         return StringNode(self.pos, entry = entry, type = py_object_type)
731             
732     def calculate_result_code(self):
733         if self.type.is_pyobject:
734             return self.entry.pystring_cname
735         else:
736             return self.entry.cname
737
738
739 class IdentifierStringNode(ConstNode):
740     # A Python string that behaves like an identifier, e.g. for
741     # keyword arguments in a call, or for imported names
742     type = PyrexTypes.py_object_type
743
744     def analyse_types(self, env):
745         self.cname = env.intern_identifier(self.value)
746
747     def calculate_result_code(self):
748         return self.cname
749
750
751 class LongNode(AtomicExprNode):
752     #  Python long integer literal
753     #
754     #  value   string
755     
756     def compile_time_value(self, denv):
757         return long(self.value)
758     
759     def analyse_types(self, env):
760         self.type = py_object_type
761         self.is_temp = 1
762     
763     def generate_evaluation_code(self, code):
764         code.putln(
765             '%s = PyLong_FromString("%s", 0, 0); %s' % (
766                 self.result_code,
767                 self.value,
768                 code.error_goto_if_null(self.result_code, self.pos)))
769
770
771 class ImagNode(AtomicExprNode):
772     #  Imaginary number literal
773     #
774     #  value   float    imaginary part
775     
776     def compile_time_value(self, denv):
777         return complex(0.0, self.value)
778     
779     def analyse_types(self, env):
780         self.type = py_object_type
781         self.is_temp = 1
782     
783     def generate_evaluation_code(self, code):
784         code.putln(
785             "%s = PyComplex_FromDoubles(0.0, %s); %s" % (
786                 self.result_code,
787                 self.value,
788                 code.error_goto_if_null(self.result_code, self.pos)))
789
790
791 class NameNode(AtomicExprNode):
792     #  Reference to a local or global variable name.
793     #
794     #  name            string    Python name of the variable
795     #
796     #  entry           Entry     Symbol table entry
797     #  interned_cname  string
798     
799     is_name = 1
800     
801     def compile_time_value(self, denv):
802         try:
803             return denv.lookup(self.name)
804         except KeyError:
805             error(self.pos, "Compile-time name '%s' not defined" % self.name)
806     
807     def coerce_to(self, dst_type, env):
808         #  If coercing to a generic pyobject and this is a builtin
809         #  C function with a Python equivalent, manufacture a NameNode
810         #  referring to the Python builtin.
811         #print "NameNode.coerce_to:", self.name, dst_type ###
812         if dst_type is py_object_type:
813             entry = self.entry
814             if entry and entry.is_cfunction:
815                 var_entry = entry.as_variable
816                 if var_entry:
817                     if var_entry.is_builtin and Options.cache_builtins:
818                         var_entry = env.declare_builtin(var_entry.name, self.pos)
819                     node = NameNode(self.pos, name = self.name)
820                     node.entry = var_entry
821                     node.analyse_rvalue_entry(env)
822                     return node
823         return AtomicExprNode.coerce_to(self, dst_type, env)
824     
825     def analyse_as_module(self, env):
826         # Try to interpret this as a reference to a cimported module.
827         # Returns the module scope, or None.
828         entry = env.lookup(self.name)
829         if entry and entry.as_module:
830             return entry.as_module
831         return None
832     
833     def analyse_as_extension_type(self, env):
834         # Try to interpret this as a reference to an extension type.
835         # Returns the extension type, or None.
836         entry = env.lookup(self.name)
837         if entry and entry.is_type and entry.type.is_extension_type:
838             return entry.type
839         else:
840             return None
841     
842     def analyse_target_declaration(self, env):
843         self.entry = env.lookup_here(self.name)
844         if not self.entry:
845             self.entry = env.declare_var(self.name, py_object_type, self.pos)
846         env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
847         env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
848         if self.entry.is_declared_generic:
849             self.result_ctype = py_object_type
850         if self.entry.is_pyglobal and self.entry.is_member:
851             env.use_utility_code(type_cache_invalidation_code)
852     
853     def analyse_types(self, env):
854         self.entry = env.lookup(self.name)
855         if not self.entry:
856             self.entry = env.declare_builtin(self.name, self.pos)
857         if not self.entry:
858             self.type = PyrexTypes.error_type
859             return
860         self.analyse_rvalue_entry(env)
861         
862     def analyse_target_types(self, env):
863         self.analyse_entry(env)
864         if not self.is_lvalue():
865             error(self.pos, "Assignment to non-lvalue '%s'"
866                 % self.name)
867             self.type = PyrexTypes.error_type
868         self.entry.used = 1
869         
870     def analyse_rvalue_entry(self, env):
871         #print "NameNode.analyse_rvalue_entry:", self.name ###
872         #print "Entry:", self.entry.__dict__ ###
873         self.analyse_entry(env)
874         entry = self.entry
875         if entry.is_declared_generic:
876             self.result_ctype = py_object_type
877         if entry.is_pyglobal or entry.is_builtin:
878             if Options.cache_builtins and entry.is_builtin:
879                 self.is_temp = 0
880             else:
881                 self.is_temp = 1
882             env.use_utility_code(get_name_interned_utility_code)
883     
884     def analyse_entry(self, env):
885         #print "NameNode.analyse_entry:", self.name ###
886         self.check_identifier_kind()
887         entry = self.entry
888         type = entry.type
889         self.type = type
890         if entry.is_pyglobal or entry.is_builtin:
891             assert type.is_pyobject, "Python global or builtin not a Python object"
892             self.interned_cname = self.entry.interned_cname = \
893                 env.intern_identifier(self.entry.name)
894
895     def check_identifier_kind(self):
896         #print "NameNode.check_identifier_kind:", self.entry.name ###
897         #print self.entry.__dict__ ###
898         entry = self.entry
899         #entry.used = 1
900         if not (entry.is_const or entry.is_variable 
901             or entry.is_builtin or entry.is_cfunction):
902                 if self.entry.as_variable:
903                     self.entry = self.entry.as_variable
904                 else:
905                     error(self.pos, 
906                         "'%s' is not a constant, variable or function identifier" % self.name)
907     
908     def is_simple(self):
909         #  If it's not a C variable, it'll be in a temp.
910         return 1
911     
912     def calculate_target_results(self, env):
913         pass
914     
915     def check_const(self):
916         entry = self.entry
917         if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
918             self.not_const()
919     
920     def check_const_addr(self):
921         entry = self.entry
922         if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
923             self.addr_not_const()
924
925     def is_lvalue(self):
926         return self.entry.is_variable and \
927             not self.entry.type.is_array and \
928             not self.entry.is_readonly
929     
930     def is_ephemeral(self):
931         #  Name nodes are never ephemeral, even if the
932         #  result is in a temporary.
933         return 0
934     
935     def allocate_temp(self, env, result = None):
936         AtomicExprNode.allocate_temp(self, env, result)
937         entry = self.entry
938         if entry:
939             entry.used = 1
940             if entry.utility_code:
941                 env.use_utility_code(entry.utility_code)
942         
943     def calculate_result_code(self):
944         entry = self.entry
945         if not entry:
946             return "<error>" # There was an error earlier
947         return entry.cname
948     
949     def generate_result_code(self, code):
950         assert hasattr(self, 'entry')
951         entry = self.entry
952         if entry is None:
953             return # There was an error earlier
954         if entry.is_builtin and Options.cache_builtins:
955             return # Lookup already cached
956         elif entry.is_pyglobal or entry.is_builtin:
957             if entry.is_builtin:
958                 namespace = Naming.builtins_cname
959             else: # entry.is_pyglobal
960                 namespace = entry.namespace_cname
961             code.putln(
962                 '%s = __Pyx_GetName(%s, %s); %s' % (
963                 self.result_code,
964                 namespace, 
965                 self.interned_cname,
966                 code.error_goto_if_null(self.result_code, self.pos)))           
967         elif entry.is_local and False:
968             # control flow not good enough yet
969             assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
970             if assigned is False:
971                 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
972             elif not Options.init_local_none and assigned is None:
973                 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
974                 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
975
976     def generate_assignment_code(self, rhs, code):
977         #print "NameNode.generate_assignment_code:", self.name ###
978         entry = self.entry
979         if entry is None:
980             return # There was an error earlier
981
982         # is_pyglobal seems to be True for module level-globals only.
983         # We use this to access class->tp_dict if necessary.
984         if entry.is_pyglobal:
985             namespace = self.entry.namespace_cname
986             if entry.is_member:
987                 # if the entry is a member we have to cheat: SetAttr does not work
988                 # on types, so we create a descriptor which is then added to tp_dict
989                 code.put_error_if_neg(self.pos,
990                     'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
991                         namespace,
992                         self.interned_cname,
993                         rhs.py_result()))
994                 # in Py2.6+, we need to invalidate the method cache
995                 code.putln("__Pyx_TypeModified((PyTypeObject*)%s);" %
996                            entry.scope.parent_type.typeptr_cname)
997             else: 
998                 code.put_error_if_neg(self.pos,
999                     'PyObject_SetAttr(%s, %s, %s)' % (
1000                         namespace,
1001                         self.interned_cname,
1002                         rhs.py_result()))
1003                 if debug_disposal_code:
1004                     print("NameNode.generate_assignment_code:")
1005                     print("...generating disposal code for %s" % rhs)
1006                 rhs.generate_disposal_code(code)
1007                 
1008         else:
1009             if self.type.is_pyobject:
1010                 #print "NameNode.generate_assignment_code: to", self.name ###
1011                 #print "...from", rhs ###
1012                 #print "...LHS type", self.type, "ctype", self.ctype() ###
1013                 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1014                 rhs.make_owned_reference(code)
1015                 if entry.is_local and not Options.init_local_none:
1016                     initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1017                     if initalized is True:
1018                         code.put_decref(self.result_code, self.ctype())
1019                     elif initalized is None:
1020                         code.put_xdecref(self.result_code, self.ctype())
1021                 else:
1022                     code.put_decref(self.result_code, self.ctype())
1023             code.putln('%s = %s;' % (self.result_code, rhs.result_as(self.ctype())))
1024             if debug_disposal_code:
1025                 print("NameNode.generate_assignment_code:")
1026                 print("...generating post-assignment code for %s" % rhs)
1027             rhs.generate_post_assignment_code(code)
1028     
1029     def generate_deletion_code(self, code):
1030         if self.entry is None:
1031             return # There was an error earlier
1032         if not self.entry.is_pyglobal:
1033             error(self.pos, "Deletion of local or C global name not supported")
1034             return
1035         code.put_error_if_neg(self.pos, 
1036             'PyObject_DelAttrString(%s, "%s")' % (
1037                 Naming.module_cname,
1038                 self.entry.name))
1039                 
1040     def annotate(self, code):
1041         if hasattr(self, 'is_called') and self.is_called:
1042             pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1043             if self.type.is_pyobject:
1044                 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1045             else:
1046                 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1047             
1048
1049 class BackquoteNode(ExprNode):
1050     #  `expr`
1051     #
1052     #  arg    ExprNode
1053     
1054     subexprs = ['arg']
1055     
1056     def analyse_types(self, env):
1057         self.arg.analyse_types(env)
1058         self.arg = self.arg.coerce_to_pyobject(env)
1059         self.type = py_object_type
1060         self.is_temp = 1
1061     
1062     def generate_result_code(self, code):
1063         code.putln(
1064             "%s = PyObject_Repr(%s); %s" % (
1065                 self.result_code,
1066                 self.arg.py_result(),
1067                 code.error_goto_if_null(self.result_code, self.pos)))
1068
1069
1070 class ImportNode(ExprNode):
1071     #  Used as part of import statement implementation.
1072     #  Implements result = 
1073     #    __import__(module_name, globals(), None, name_list)
1074     #
1075     #  module_name   IdentifierStringNode     dotted name of module
1076     #  name_list     ListNode or None         list of names to be imported
1077     
1078     subexprs = ['module_name', 'name_list']
1079
1080     def analyse_types(self, env):
1081         self.module_name.analyse_types(env)
1082         self.module_name = self.module_name.coerce_to_pyobject(env)
1083         if self.name_list:
1084             self.name_list.analyse_types(env)
1085         self.type = py_object_type
1086         self.is_temp = 1
1087         env.use_utility_code(import_utility_code)
1088     
1089     def generate_result_code(self, code):
1090         if self.name_list:
1091             name_list_code = self.name_list.py_result()
1092         else:
1093             name_list_code = "0"
1094         code.putln(
1095             "%s = __Pyx_Import(%s, %s); %s" % (
1096                 self.result_code,
1097                 self.module_name.py_result(),
1098                 name_list_code,
1099                 code.error_goto_if_null(self.result_code, self.pos)))
1100
1101
1102 class IteratorNode(ExprNode):
1103     #  Used as part of for statement implementation.
1104     #  Implements result = iter(sequence)
1105     #
1106     #  sequence   ExprNode
1107     
1108     subexprs = ['sequence']
1109     
1110     def analyse_types(self, env):
1111         self.sequence.analyse_types(env)
1112         self.sequence = self.sequence.coerce_to_pyobject(env)
1113         self.type = py_object_type
1114         self.is_temp = 1
1115         
1116         self.counter = TempNode(self.pos, PyrexTypes.c_py_ssize_t_type, env)
1117         self.counter.allocate_temp(env)
1118         
1119     def release_temp(self, env):
1120         env.release_temp(self.result_code)
1121         self.counter.release_temp(env)
1122     
1123     def generate_result_code(self, code):
1124         code.putln(
1125             "if (PyList_CheckExact(%s)) { %s = 0; %s = %s; Py_INCREF(%s); }" % (
1126                 self.sequence.py_result(),
1127                 self.counter.result_code,
1128                 self.result_code,
1129                 self.sequence.py_result(),
1130                 self.result_code))
1131         code.putln("else { %s = PyObject_GetIter(%s); %s }" % (
1132                 self.result_code,
1133                 self.sequence.py_result(),
1134                 code.error_goto_if_null(self.result_code, self.pos)))
1135
1136
1137 class NextNode(AtomicExprNode):
1138     #  Used as part of for statement implementation.
1139     #  Implements result = iterator.next()
1140     #  Created during analyse_types phase.
1141     #  The iterator is not owned by this node.
1142     #
1143     #  iterator   ExprNode
1144     
1145     def __init__(self, iterator, env):
1146         self.pos = iterator.pos
1147         self.iterator = iterator
1148         self.type = py_object_type
1149         self.is_temp = 1
1150     
1151     def generate_result_code(self, code):
1152         code.putln(
1153             "if (PyList_CheckExact(%s)) { if (%s >= PyList_GET_SIZE(%s)) break; %s = PyList_GET_ITEM(%s, %s++); Py_INCREF(%s); }" % (
1154                 self.iterator.py_result(),
1155                 self.iterator.counter.result_code,
1156                 self.iterator.py_result(),
1157                 self.result_code,
1158                 self.iterator.py_result(),
1159                 self.iterator.counter.result_code,
1160                 self.result_code))
1161         code.putln("else {")
1162         code.putln(
1163             "%s = PyIter_Next(%s);" % (
1164                 self.result_code,
1165                 self.iterator.py_result()))
1166         code.putln(
1167             "if (!%s) {" %
1168                 self.result_code)
1169         code.error_goto_if_PyErr(self.pos)
1170         code.putln("break;")
1171         code.putln("}")
1172         code.putln("}")
1173
1174
1175 class ExcValueNode(AtomicExprNode):
1176     #  Node created during analyse_types phase
1177     #  of an ExceptClauseNode to fetch the current
1178     #  exception value.
1179     
1180     def __init__(self, pos, env, var):
1181         ExprNode.__init__(self, pos)
1182         self.type = py_object_type
1183         self.var = var
1184     
1185     def calculate_result_code(self):
1186         return self.var
1187
1188     def generate_result_code(self, code):
1189         pass
1190
1191
1192 class TempNode(AtomicExprNode):
1193     #  Node created during analyse_types phase
1194     #  of some nodes to hold a temporary value.
1195     
1196     def __init__(self, pos, type, env):
1197         ExprNode.__init__(self, pos)
1198         self.type = type
1199         if type.is_pyobject:
1200             self.result_ctype = py_object_type
1201         self.is_temp = 1
1202         
1203     def analyse_types(self, env):
1204         return self.type
1205     
1206     def generate_result_code(self, code):
1207         pass
1208
1209
1210 class PyTempNode(TempNode):
1211     #  TempNode holding a Python value.
1212     
1213     def __init__(self, pos, env):
1214         TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1215
1216
1217 #-------------------------------------------------------------------
1218 #
1219 #  Trailer nodes
1220 #
1221 #-------------------------------------------------------------------
1222
1223 class IndexNode(ExprNode):
1224     #  Sequence indexing.
1225     #
1226     #  base     ExprNode
1227     #  index    ExprNode
1228     
1229     subexprs = ['base', 'index', 'py_index']
1230     
1231     def compile_time_value(self, denv):
1232         base = self.base.compile_time_value(denv)
1233         index = self.index.compile_time_value(denv)
1234         try:
1235             return base[index]
1236         except Exception, e:
1237             self.compile_time_value_error(e)
1238     
1239     def is_ephemeral(self):
1240         return self.base.is_ephemeral()
1241     
1242     def analyse_target_declaration(self, env):
1243         pass
1244     
1245     def analyse_types(self, env):
1246         self.base.analyse_types(env)
1247         self.index.analyse_types(env)
1248         if self.base.type.is_pyobject:
1249             if self.index.type.is_int:
1250                 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1251                 self.py_index = CloneNode(self.index).coerce_to_pyobject(env)
1252             else:
1253                 self.index = self.index.coerce_to_pyobject(env)
1254                 self.py_index = CloneNode(self.index)
1255             self.type = py_object_type
1256             self.is_temp = 1
1257         else:
1258             self.py_index = CloneNode(self.index) # so that it exists for subexpr processing
1259             if self.base.type.is_ptr or self.base.type.is_array:
1260                 self.type = self.base.type.base_type
1261             else:
1262                 error(self.pos,
1263                     "Attempting to index non-array type '%s'" %
1264                         self.base.type)
1265                 self.type = PyrexTypes.error_type
1266             if self.index.type.is_pyobject:
1267                 self.index = self.index.coerce_to(
1268                     PyrexTypes.c_py_ssize_t_type, env)
1269             if not self.index.type.is_int:
1270                 error(self.pos,
1271                     "Invalid index type '%s'" %
1272                         self.index.type)
1273     
1274     def check_const_addr(self):
1275         self.base.check_const_addr()
1276         self.index.check_const()
1277     
1278     def is_lvalue(self):
1279         return 1
1280     
1281     def calculate_result_code(self):
1282         return "(%s[%s])" % (
1283             self.base.result_code, self.index.result_code)
1284
1285     def generate_subexpr_evaluation_code(self, code):
1286         # do not evaluate self.py_index in case we don't need it
1287         self.base.generate_evaluation_code(code)
1288         self.index.generate_evaluation_code(code)
1289         
1290     def generate_subexpr_disposal_code(self, code):
1291         # if we used self.py_index, it will be disposed of manually
1292         self.base.generate_disposal_code(code)
1293         self.index.generate_disposal_code(code)
1294
1295     def generate_result_code(self, code):
1296         if self.type.is_pyobject:
1297             if self.index.type.is_int:
1298                 code.putln("if (PyList_CheckExact(%s) && 0 <= %s && %s < PyList_GET_SIZE(%s)) {" % (
1299                         self.base.py_result(),
1300                         self.index.result_code,
1301                         self.index.result_code,
1302                         self.base.py_result()))
1303                 code.putln("%s = PyList_GET_ITEM(%s, %s); Py_INCREF(%s);" % (
1304                         self.result_code,
1305                         self.base.py_result(),
1306                         self.index.result_code,
1307                         self.result_code))
1308                 code.putln("} else if (PyTuple_CheckExact(%s) && 0 <= %s && %s < PyTuple_GET_SIZE(%s)) {" % (
1309                         self.base.py_result(),
1310                         self.index.result_code,
1311                         self.index.result_code,
1312                         self.base.py_result()))
1313                 code.putln("%s = PyTuple_GET_ITEM(%s, %s); Py_INCREF(%s);" % (
1314                         self.result_code,
1315                         self.base.py_result(),
1316                         self.index.result_code,
1317                         self.result_code))
1318                 code.putln("} else {")
1319                 self.generate_generic_code_result(code)
1320                 code.putln("}")
1321             else:
1322                 self.generate_generic_code_result(code)
1323
1324     def generate_generic_code_result(self, code):
1325         self.py_index.generate_result_code(code)
1326         code.putln(
1327             "%s = PyObject_GetItem(%s, %s); %s" % (
1328                 self.result_code,
1329                 self.base.py_result(),
1330                 self.py_index.py_result(),
1331                 code.error_goto_if_null(self.result_code, self.pos)))
1332         if self.is_temp:
1333             self.py_index.generate_disposal_code(code)
1334
1335     def generate_assignment_code(self, rhs, code):
1336         self.generate_subexpr_evaluation_code(code)
1337         if self.type.is_pyobject:
1338             if self.index.type.is_int:
1339                 code.putln("if (PyList_CheckExact(%s) && 0 <= %s && %s < PyList_GET_SIZE(%s)) {" % (
1340                         self.base.py_result(),
1341                         self.index.result_code,
1342                         self.index.result_code,
1343                         self.base.py_result()))
1344                 code.putln("Py_DECREF(PyList_GET_ITEM(%s, %s)); Py_INCREF(%s);" % (
1345                         self.base.py_result(),
1346                         self.index.result_code,
1347                         rhs.py_result()))
1348                 code.putln("PyList_SET_ITEM(%s, %s, %s);" % (
1349                         self.base.py_result(),
1350                         self.index.result_code,
1351                         rhs.py_result()))
1352                 code.putln("} else {")
1353                 self.generate_generic_assignment_code(rhs, code)
1354                 code.putln("}")
1355             else:
1356                 self.generate_generic_assignment_code(rhs, code)
1357         else:
1358             code.putln(
1359                 "%s = %s;" % (
1360                     self.result_code, rhs.result_code))
1361         self.generate_subexpr_disposal_code(code)
1362         rhs.generate_disposal_code(code)
1363     
1364     def generate_generic_assignment_code(self, rhs, code):
1365         self.py_index.generate_result_code(code)
1366         code.put_error_if_neg(self.pos, 
1367             "PyObject_SetItem(%s, %s, %s)" % (
1368                 self.base.py_result(),
1369                 self.py_index.py_result(),
1370                 rhs.py_result()))
1371         if self.is_temp:
1372             self.py_index.generate_disposal_code(code)
1373     
1374     def generate_deletion_code(self, code):
1375         self.generate_subexpr_evaluation_code(code)
1376         self.py_index.generate_evaluation_code(code)
1377         code.put_error_if_neg(self.pos, 
1378             "PyObject_DelItem(%s, %s)" % (
1379                 self.base.py_result(),
1380                 self.py_index.py_result()))
1381         self.generate_subexpr_disposal_code(code)
1382         self.py_index.generate_disposal_code(code)
1383
1384
1385 class SliceIndexNode(ExprNode):
1386     #  2-element slice indexing
1387     #
1388     #  base      ExprNode
1389     #  start     ExprNode or None
1390     #  stop      ExprNode or None
1391     
1392     subexprs = ['base', 'start', 'stop']
1393     
1394     def compile_time_value(self, denv):
1395         base = self.base.compile_time_value(denv)
1396         start = self.start.compile_time_value(denv)
1397         stop = self.stop.compile_time_value(denv)
1398         try:
1399             return base[start:stop]
1400         except Exception, e:
1401             self.compile_time_value_error(e)
1402     
1403     def analyse_target_declaration(self, env):
1404         pass
1405
1406     def analyse_types(self, env):
1407         self.base.analyse_types(env)
1408         if self.start:
1409             self.start.analyse_types(env)
1410         if self.stop:
1411             self.stop.analyse_types(env)
1412         self.base = self.base.coerce_to_pyobject(env)
1413         c_int = PyrexTypes.c_py_ssize_t_type
1414         if self.start:
1415             self.start = self.start.coerce_to(c_int, env)
1416         if self.stop:
1417             self.stop = self.stop.coerce_to(c_int, env)
1418         self.type = py_object_type
1419         self.is_temp = 1
1420     
1421     def generate_result_code(self, code):
1422         code.putln(
1423             "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1424                 self.result_code,
1425                 self.base.py_result(),
1426                 self.start_code(),
1427                 self.stop_code(),
1428                 code.error_goto_if_null(self.result_code, self.pos)))
1429     
1430     def generate_assignment_code(self, rhs, code):
1431         self.generate_subexpr_evaluation_code(code)
1432         code.put_error_if_neg(self.pos, 
1433             "PySequence_SetSlice(%s, %s, %s, %s)" % (
1434                 self.base.py_result(),
1435                 self.start_code(),
1436                 self.stop_code(),
1437                 rhs.result_code))
1438         self.generate_subexpr_disposal_code(code)
1439         rhs.generate_disposal_code(code)
1440
1441     def generate_deletion_code(self, code):
1442         self.generate_subexpr_evaluation_code(code)
1443         code.put_error_if_neg(self.pos,
1444             "PySequence_DelSlice(%s, %s, %s)" % (
1445                 self.base.py_result(),
1446                 self.start_code(),
1447                 self.stop_code()))
1448         self.generate_subexpr_disposal_code(code)
1449     
1450     def start_code(self):
1451         if self.start:
1452             return self.start.result_code
1453         else:
1454             return "0"
1455     
1456     def stop_code(self):
1457         if self.stop:
1458             return self.stop.result_code
1459         else:
1460             return "PY_SSIZE_T_MAX"
1461     
1462     def calculate_result_code(self):
1463         # self.result_code is not used, but this method must exist
1464         return "<unused>"
1465     
1466
1467 class SliceNode(ExprNode):
1468     #  start:stop:step in subscript list
1469     #
1470     #  start     ExprNode
1471     #  stop      ExprNode
1472     #  step      ExprNode
1473     
1474     def compile_time_value(self, denv):
1475         start = self.start.compile_time_value(denv)
1476         stop = self.stop.compile_time_value(denv)
1477         step = step.step.compile_time_value(denv)
1478         try:
1479             return slice(start, stop, step)
1480         except Exception, e:
1481             self.compile_time_value_error(e)
1482
1483     subexprs = ['start', 'stop', 'step']
1484     
1485     def analyse_types(self, env):
1486         self.start.analyse_types(env)
1487         self.stop.analyse_types(env)
1488         self.step.analyse_types(env)
1489         self.start = self.start.coerce_to_pyobject(env)
1490         self.stop = self.stop.coerce_to_pyobject(env)
1491         self.step = self.step.coerce_to_pyobject(env)
1492         self.type = py_object_type
1493         self.is_temp = 1
1494     
1495     def generate_result_code(self, code):
1496         code.putln(
1497             "%s = PySlice_New(%s, %s, %s); %s" % (
1498                 self.result_code,
1499                 self.start.py_result(), 
1500                 self.stop.py_result(), 
1501                 self.step.py_result(),
1502                 code.error_goto_if_null(self.result_code, self.pos)))
1503
1504 class SimpleCallNode(ExprNode):
1505     #  Function call without keyword, * or ** args.
1506     #
1507     #  function       ExprNode
1508     #  args           [ExprNode]
1509     #  arg_tuple      ExprNode or None     used internally
1510     #  self           ExprNode or None     used internally
1511     #  coerced_self   ExprNode or None     used internally
1512     #  wrapper_call   bool                 used internally
1513     
1514     subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
1515     
1516     self = None
1517     coerced_self = None
1518     arg_tuple = None
1519     wrapper_call = False
1520     
1521     def compile_time_value(self, denv):
1522         function = self.function.compile_time_value(denv)
1523         args = [arg.compile_time_value(denv) for arg in self.args]
1524         try:
1525             return function(*args)
1526         except Exception, e:
1527             self.compile_time_value_error(e)
1528
1529     def analyse_types(self, env):
1530         function = self.function
1531         function.is_called = 1
1532         self.function.analyse_types(env)
1533         if function.is_attribute and function.is_py_attr and \
1534            function.attribute == "append" and len(self.args) == 1:
1535             # L.append(x) is almost always applied to a list
1536             self.py_func = self.function
1537             self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
1538             self.function.analyse_types(env)
1539             self.self = self.py_func.obj
1540             function.obj = CloneNode(self.self)
1541             env.use_utility_code(append_utility_code)
1542         if function.is_attribute and function.entry and function.entry.is_cmethod:
1543             # Take ownership of the object from which the attribute
1544             # was obtained, because we need to pass it as 'self'.
1545             self.self = function.obj
1546             function.obj = CloneNode(self.self)
1547         func_type = self.function_type()
1548         if func_type.is_pyobject:
1549             self.arg_tuple = TupleNode(self.pos, args = self.args)
1550             self.arg_tuple.analyse_types(env)
1551             self.args = None
1552             self.type = py_object_type
1553             self.is_temp = 1
1554         else:
1555             for arg in self.args:
1556                 arg.analyse_types(env)
1557             if self.self and func_type.args:
1558                 # Coerce 'self' to the type expected by the method.
1559                 expected_type = func_type.args[0].type
1560                 self.coerced_self = CloneNode(self.self).coerce_to(
1561                     expected_type, env)
1562                 # Insert coerced 'self' argument into argument list.
1563                 self.args.insert(0, self.coerced_self)
1564             self.analyse_c_function_call(env)
1565     
1566     def function_type(self):
1567         # Return the type of the function being called, coercing a function
1568         # pointer to a function if necessary.
1569         func_type = self.function.type
1570         if func_type.is_ptr:
1571             func_type = func_type.base_type
1572         return func_type
1573     
1574     def analyse_c_function_call(self, env):
1575         func_type = self.function_type()
1576         # Check function type
1577         if not func_type.is_cfunction:
1578             if not func_type.is_error:
1579                 error(self.pos, "Calling non-function type '%s'" %
1580                     func_type)
1581             self.type = PyrexTypes.error_type
1582             self.result_code = "<error>"
1583             return
1584         # Check no. of args
1585         max_nargs = len(func_type.args)
1586         expected_nargs = max_nargs - func_type.optional_arg_count
1587         actual_nargs = len(self.args)
1588         if actual_nargs < expected_nargs \
1589             or (not func_type.has_varargs and actual_nargs > max_nargs):
1590                 expected_str = str(expected_nargs)
1591                 if func_type.has_varargs:
1592                     expected_str = "at least " + expected_str
1593                 elif func_type.optional_arg_count:
1594                     if actual_nargs < max_nargs:
1595                         expected_str = "at least " + expected_str
1596                     else:
1597                         expected_str = "at most " + str(max_nargs)
1598                 error(self.pos, 
1599                     "Call with wrong number of arguments (expected %s, got %s)"
1600                         % (expected_str, actual_nargs))
1601                 self.args = None
1602                 self.type = PyrexTypes.error_type
1603                 self.result_code = "<error>"
1604                 return
1605         # Coerce arguments
1606         for i in range(min(max_nargs, actual_nargs)):
1607             formal_type = func_type.args[i].type
1608             self.args[i] = self.args[i].coerce_to(formal_type, env)
1609         for i in range(max_nargs, actual_nargs):
1610             if self.args[i].type.is_pyobject:
1611                 error(self.args[i].pos, 
1612                     "Python object cannot be passed as a varargs parameter")
1613         # Calc result type and code fragment
1614         self.type = func_type.return_type
1615         if self.type.is_pyobject \
1616             or func_type.exception_value is not None \
1617             or func_type.exception_check:
1618                 self.is_temp = 1
1619                 if self.type.is_pyobject:
1620                     self.result_ctype = py_object_type
1621         # C++ exception handler
1622         if func_type.exception_check == '+':
1623             if func_type.exception_value is None:
1624                 env.use_utility_code(cpp_exception_utility_code)
1625
1626     def calculate_result_code(self):
1627         return self.c_call_code()
1628     
1629     def c_call_code(self):
1630         func_type = self.function_type()
1631         if self.args is None or not func_type.is_cfunction:
1632             return "<error>"
1633         formal_args = func_type.args
1634         arg_list_code = []
1635         args = zip(formal_args, self.args)
1636         max_nargs = len(func_type.args)
1637         expected_nargs = max_nargs - func_type.optional_arg_count
1638         actual_nargs = len(self.args)
1639         for formal_arg, actual_arg in args[:expected_nargs]:
1640                 arg_code = actual_arg.result_as(formal_arg.type)
1641                 arg_list_code.append(arg_code)
1642                 
1643         if func_type.optional_arg_count:
1644             if expected_nargs == actual_nargs:
1645                 optional_args = 'NULL'
1646             else:
1647                 optional_arg_code = [str(actual_nargs - expected_nargs)]
1648                 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
1649                     arg_code = actual_arg.result_as(formal_arg.type)
1650                     optional_arg_code.append(arg_code)
1651 #                for formal_arg in formal_args[actual_nargs:max_nargs]:
1652 #                    optional_arg_code.append(formal_arg.type.cast_code('0'))
1653                 optional_arg_struct = '{%s}' % ','.join(optional_arg_code)
1654                 optional_args = PyrexTypes.c_void_ptr_type.cast_code(
1655                     '&' + func_type.op_arg_struct.base_type.cast_code(optional_arg_struct))
1656             arg_list_code.append(optional_args)
1657             
1658         for actual_arg in self.args[len(formal_args):]:
1659             arg_list_code.append(actual_arg.result_code)
1660         result = "%s(%s)" % (self.function.result_code,
1661             join(arg_list_code, ", "))
1662         if self.wrapper_call or \
1663                 self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
1664             result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
1665         return result
1666     
1667     def generate_result_code(self, code):
1668         func_type = self.function_type()
1669         if func_type.is_pyobject:
1670             arg_code = self.arg_tuple.py_result()
1671             code.putln(
1672                 "%s = PyObject_Call(%s, %s, NULL); %s" % (
1673                     self.result_code,
1674                     self.function.py_result(),
1675                     arg_code,
1676                     code.error_goto_if_null(self.result_code, self.pos)))
1677         elif func_type.is_cfunction:
1678             exc_checks = []
1679             if self.type.is_pyobject:
1680                 exc_checks.append("!%s" % self.result_code)
1681             else:
1682                 exc_val = func_type.exception_value
1683                 exc_check = func_type.exception_check
1684                 if exc_val is not None:
1685                     exc_checks.append("%s == %s" % (self.result_code, exc_val))
1686                 if exc_check:
1687                     exc_checks.append("PyErr_Occurred()")
1688             if self.is_temp or exc_checks:
1689                 rhs = self.c_call_code()
1690                 if self.result_code:
1691                     lhs = "%s = " % self.result_code
1692                     if self.is_temp and self.type.is_pyobject:
1693                         #return_type = self.type # func_type.return_type
1694                         #print "SimpleCallNode.generate_result_code: casting", rhs, \
1695                         #       "from", return_type, "to pyobject" ###
1696                         rhs = typecast(py_object_type, self.type, rhs)
1697                 else:
1698                     lhs = ""
1699                 if func_type.exception_check == '+':
1700                     if func_type.exception_value is None:
1701                         raise_py_exception = "__Pyx_CppExn2PyErr()"
1702                     elif func_type.exception_value.type.is_pyobject:
1703                         raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
1704                     else:
1705                         raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
1706                     code.putln(
1707                     "try {%s%s;} catch(...) {%s; %s}" % (
1708                         lhs,
1709                         rhs,
1710                         raise_py_exception,
1711                         code.error_goto(self.pos)))
1712                     return
1713                 code.putln(
1714                     "%s%s; %s" % (
1715                         lhs,
1716                         rhs,
1717                         code.error_goto_if(" && ".join(exc_checks), self.pos)))    
1718
1719 class GeneralCallNode(ExprNode):
1720     #  General Python function call, including keyword,
1721     #  * and ** arguments.
1722     #
1723     #  function         ExprNode
1724     #  positional_args  ExprNode          Tuple of positional arguments
1725     #  keyword_args     ExprNode or None  Dict of keyword arguments
1726     #  starstar_arg     ExprNode or None  Dict of extra keyword args
1727     
1728     subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
1729
1730     def compile_time_value(self, denv):
1731         function = self.function.compile_time_value(denv)
1732         positional_args = self.positional_args.compile_time_value(denv)
1733         keyword_args = self.keyword_args.compile_time_value(denv)
1734         starstar_arg = self.starstar_arg.compile_time_value(denv)
1735         try:
1736             keyword_args.update(starstar_arg)
1737             return function(*positional_args, **keyword_args)
1738         except Exception, e:
1739             self.compile_time_value_error(e)
1740
1741     def analyse_types(self, env):
1742         self.function.analyse_types(env)
1743         self.positional_args.analyse_types(env)
1744         if self.keyword_args:
1745             self.keyword_args.analyse_types(env)
1746         if self.starstar_arg:
1747             self.starstar_arg.analyse_types(env)
1748         self.function = self.function.coerce_to_pyobject(env)
1749         self.positional_args = \
1750             self.positional_args.coerce_to_pyobject(env)
1751         if self.starstar_arg:
1752             self.starstar_arg = \
1753                 self.starstar_arg.coerce_to_pyobject(env)
1754         self.type = py_object_type
1755         self.is_temp = 1
1756         
1757     def generate_result_code(self, code):
1758         if self.keyword_args and self.starstar_arg:
1759             code.put_error_if_neg(self.pos, 
1760                 "PyDict_Update(%s, %s)" % (
1761                     self.keyword_args.py_result(), 
1762                     self.starstar_arg.py_result()))
1763             keyword_code = self.keyword_args.py_result()
1764         elif self.keyword_args:
1765             keyword_code = self.keyword_args.py_result()
1766         elif self.starstar_arg:
1767             keyword_code = self.starstar_arg.py_result()
1768         else:
1769             keyword_code = None
1770         if not keyword_code:
1771             call_code = "PyObject_Call(%s, %s, NULL)" % (
1772                 self.function.py_result(),
1773                 self.positional_args.py_result())
1774         else:
1775             call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
1776                 self.function.py_result(),
1777                 self.positional_args.py_result(),
1778                 keyword_code)
1779         code.putln(
1780             "%s = %s; %s" % (
1781                 self.result_code,
1782                 call_code,
1783                 code.error_goto_if_null(self.result_code, self.pos)))
1784
1785
1786 class AsTupleNode(ExprNode):
1787     #  Convert argument to tuple. Used for normalising
1788     #  the * argument of a function call.
1789     #
1790     #  arg    ExprNode
1791     
1792     subexprs = ['arg']
1793     
1794     def compile_time_value(self, denv):
1795         arg = self.arg.compile_time_value(denv)
1796         try:
1797             return tuple(arg)
1798         except Exception, e:
1799             self.compile_time_value_error(e)
1800
1801     def analyse_types(self, env):
1802         self.arg.analyse_types(env)
1803         self.arg = self.arg.coerce_to_pyobject(env)
1804         self.type = py_object_type
1805         self.is_temp = 1
1806     
1807     def generate_result_code(self, code):
1808         code.putln(
1809             "%s = PySequence_Tuple(%s); %s" % (
1810                 self.result_code,
1811                 self.arg.py_result(),
1812                 code.error_goto_if_null(self.result_code, self.pos)))
1813     
1814
1815 class AttributeNode(ExprNode):
1816     #  obj.attribute
1817     #
1818     #  obj          ExprNode
1819     #  attribute    string
1820     #
1821     #  Used internally:
1822     #
1823     #  is_py_attr           boolean   Is a Python getattr operation
1824     #  member               string    C name of struct member
1825     #  is_called            boolean   Function call is being done on result
1826     #  entry                Entry     Symbol table entry of attribute
1827     #  interned_attr_cname  string    C name of interned attribute name
1828     
1829     is_attribute = 1
1830     subexprs = ['obj']
1831     
1832     type = PyrexTypes.error_type
1833     result = "<error>"
1834     entry = None
1835     is_called = 0
1836
1837     def coerce_to(self, dst_type, env):
1838         #  If coercing to a generic pyobject and this is a cpdef function
1839         #  we can create the corresponding attribute
1840         if dst_type is py_object_type:
1841             entry = self.entry
1842             if entry and entry.is_cfunction and entry.as_variable:
1843                 # must be a cpdef function
1844                 self.is_temp = 1
1845                 self.entry = entry.as_variable
1846                 self.analyse_as_python_attribute(env) 
1847                 return self
1848         return ExprNode.coerce_to(self, dst_type, env)
1849     
1850     def compile_time_value(self, denv):
1851         attr = self.attribute
1852         if attr.beginswith("__") and attr.endswith("__"):
1853             self.error("Invalid attribute name '%s' in compile-time expression"
1854                 % attr)
1855             return None
1856         obj = self.arg.compile_time_value(denv)
1857         try:
1858             return getattr(obj, attr)
1859         except Exception, e:
1860             self.compile_time_value_error(e)
1861
1862     def analyse_target_declaration(self, env):
1863         pass
1864     
1865     def analyse_target_types(self, env):
1866         self.analyse_types(env, target = 1)
1867     
1868     def analyse_types(self, env, target = 0):
1869         if self.analyse_as_cimported_attribute(env, target):
1870             return
1871         if not target and self.analyse_as_unbound_cmethod(env):
1872             return
1873         self.analyse_as_ordinary_attribute(env, target)
1874     
1875     def analyse_as_cimported_attribute(self, env, target):
1876         # Try to interpret this as a reference to an imported
1877         # C const, type, var or function. If successful, mutates
1878         # this node into a NameNode and returns 1, otherwise
1879         # returns 0.
1880         module_scope = self.obj.analyse_as_module(env)
1881         if module_scope:
1882             entry = module_scope.lookup_here(self.attribute)
1883             if entry and (
1884                 entry.is_cglobal or entry.is_cfunction
1885                 or entry.is_type or entry.is_const):
1886                     self.mutate_into_name_node(env, entry, target)
1887                     return 1
1888         return 0
1889     
1890     def analyse_as_unbound_cmethod(self, env):
1891         # Try to interpret this as a reference to an unbound
1892         # C method of an extension type. If successful, mutates
1893         # this node into a NameNode and returns 1, otherwise
1894         # returns 0.
1895         type = self.obj.analyse_as_extension_type(env)
1896         if type:
1897             entry = type.scope.lookup_here(self.attribute)
1898             if entry and entry.is_cmethod:
1899                 # Create a temporary entry describing the C method
1900                 # as an ordinary function.
1901                 ubcm_entry = Symtab.Entry(entry.name,
1902                     "%s->%s" % (type.vtabptr_cname, entry.cname),
1903                     entry.type)
1904                 ubcm_entry.is_cfunction = 1
1905                 ubcm_entry.func_cname = entry.func_cname
1906                 ubcm_entry.is_unbound_cmethod = 1
1907                 self.mutate_into_name_node(env, ubcm_entry, None)
1908                 return 1
1909         return 0
1910     
1911     def analyse_as_extension_type(self, env):
1912         # Try to interpret this as a reference to an extension type
1913         # in a cimported module. Returns the extension type, or None.
1914         module_scope = self.obj.analyse_as_module(env)
1915         if module_scope:
1916             entry = module_scope.lookup_here(self.attribute)
1917             if entry and entry.is_type and entry.type.is_extension_type:
1918                 return entry.type
1919         return None
1920     
1921     def analyse_as_module(self, env):
1922         # Try to interpret this as a reference to a cimported module
1923         # in another cimported module. Returns the module scope, or None.
1924         module_scope = self.obj.analyse_as_module(env)
1925         if module_scope:
1926             entry = module_scope.lookup_here(self.attribute)
1927             if entry and entry.as_module:
1928                 return entry.as_module
1929         return None
1930                 
1931     def mutate_into_name_node(self, env, entry, target):
1932         # Mutate this node into a NameNode and complete the
1933         # analyse_types phase.
1934         self.__class__ = NameNode
1935         self.name = self.attribute
1936         self.entry = entry
1937         del self.obj
1938         del self.attribute
1939         if target:
1940             NameNode.analyse_target_types(self, env)
1941         else:
1942             NameNode.analyse_rvalue_entry(self, env)
1943     
1944     def analyse_as_ordinary_attribute(self, env, target):
1945         self.obj.analyse_types(env)
1946         self.analyse_attribute(env)
1947         if self.entry and self.entry.is_cmethod and not self.is_called:
1948 #            error(self.pos, "C method can only be called")
1949             pass
1950         ## Reference to C array turns into pointer to first element.
1951         #while self.type.is_array:
1952         #       self.type = self.type.element_ptr_type()
1953         if self.is_py_attr:
1954             if not target:
1955                 self.is_temp = 1
1956                 self.result_ctype = py_object_type
1957     
1958     def analyse_attribute(self, env):
1959         # Look up attribute and set self.type and self.member.
1960         self.is_py_attr = 0
1961         self.member = self.attribute
1962         if self.obj.type.is_string:
1963             self.obj = self.obj.coerce_to_pyobject(env)
1964         obj_type = self.obj.type
1965         if obj_type.is_ptr or obj_type.is_array:
1966             obj_type = obj_type.base_type
1967             self.op = "->"
1968         elif obj_type.is_extension_type:
1969             self.op = "->"
1970         else:
1971             self.op = "."
1972         if obj_type.has_attributes:
1973             entry = None
1974             if obj_type.attributes_known():
1975                 entry = obj_type.scope.lookup_here(self.attribute)
1976                 if entry and entry.is_member:
1977                     entry = None
1978             else:
1979                 error(self.pos, 
1980                     "Cannot select attribute of incomplete type '%s'" 
1981                     % obj_type)
1982                 obj_type = PyrexTypes.error_type
1983             self.entry = entry
1984             if entry:
1985                 if obj_type.is_extension_type and entry.name == "__weakref__":
1986                     error(self.pos, "Illegal use of special attribute __weakref__")
1987                 # methods need the normal attribute lookup
1988                 # because they do not have struct entries
1989                 if entry.is_variable or entry.is_cmethod:
1990                     self.type = entry.type
1991                     self.member = entry.cname
1992                     return
1993                 else:
1994                     # If it's not a variable or C method, it must be a Python
1995                     # method of an extension type, so we treat it like a Python
1996                     # attribute.
1997                     pass
1998         # If we get here, the base object is not a struct/union/extension 
1999         # type, or it is an extension type and the attribute is either not
2000         # declared or is declared as a Python method. Treat it as a Python
2001         # attribute reference.
2002         self.analyse_as_python_attribute(env)
2003                     
2004     def analyse_as_python_attribute(self, env):
2005         obj_type = self.obj.type
2006         self.member = self.attribute
2007         if obj_type.is_pyobject:
2008             self.type = py_object_type
2009             self.is_py_attr = 1
2010             self.interned_attr_cname = env.intern_identifier(self.attribute)
2011         else:
2012             if not obj_type.is_error:
2013                 error(self.pos, 
2014                     "Object of type '%s' has no attribute '%s'" %
2015                     (obj_type, self.attribute))
2016         
2017     def is_simple(self):
2018         if self.obj:
2019             return self.result_in_temp() or self.obj.is_simple()
2020         else:
2021             return NameNode.is_simple(self)
2022
2023     def is_lvalue(self):
2024         if self.obj:
2025             return 1
2026         else:
2027             return NameNode.is_lvalue(self)
2028     
2029     def is_ephemeral(self):
2030         if self.obj:
2031             return self.obj.is_ephemeral()
2032         else:
2033             return NameNode.is_ephemeral(self)
2034     
2035     def calculate_result_code(self):
2036         #print "AttributeNode.calculate_result_code:", self.member ###
2037         #print "...obj node =", self.obj, "code", self.obj.result_code ###
2038         #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2039         obj = self.obj
2040         obj_code = obj.result_as(obj.type)
2041         #print "...obj_code =", obj_code ###
2042         if self.entry and self.entry.is_cmethod:
2043             if obj.type.is_extension_type:
2044                 return "((struct %s *)%s%s%s)->%s" % (
2045                     obj.type.vtabstruct_cname, obj_code, self.op, 
2046                     obj.type.vtabslot_cname, self.member)
2047             else:
2048                 return self.member
2049         else:
2050             return "%s%s%s" % (obj_code, self.op, self.member)
2051     
2052     def generate_result_code(self, code):
2053         if self.is_py_attr:
2054             code.putln(
2055                 '%s = PyObject_GetAttr(%s, %s); %s' % (
2056                     self.result_code,
2057                     self.obj.py_result(),
2058                     self.interned_attr_cname,
2059                     code.error_goto_if_null(self.result_code, self.pos)))
2060     
2061     def generate_assignment_code(self, rhs, code):
2062         self.obj.generate_evaluation_code(code)
2063         if self.is_py_attr:
2064             code.put_error_if_neg(self.pos, 
2065                 'PyObject_SetAttr(%s, %s, %s)' % (
2066                     self.obj.py_result(),
2067                     self.interned_attr_cname,
2068                     rhs.py_result()))
2069             rhs.generate_disposal_code(code)
2070         else:
2071             select_code = self.result_code
2072             if self.type.is_pyobject:
2073                 rhs.make_owned_reference(code)
2074                 code.put_decref(select_code, self.ctype())
2075             code.putln(
2076                 "%s = %s;" % (
2077                     select_code,
2078                     rhs.result_as(self.ctype())))
2079                     #rhs.result_code))
2080             rhs.generate_post_assignment_code(code)
2081         self.obj.generate_disposal_code(code)
2082     
2083     def generate_deletion_code(self, code):
2084         self.obj.generate_evaluation_code(code)
2085         if self.is_py_attr:
2086             code.put_error_if_neg(self.pos,
2087                 'PyObject_DelAttr(%s, %s)' % (
2088                     self.obj.py_result(),
2089                     self.interned_attr_cname))
2090         else:
2091             error(self.pos, "Cannot delete C attribute of extension type")
2092         self.obj.generate_disposal_code(code)
2093         
2094     def annotate(self, code):
2095         if self.is_py_attr:
2096             code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2097         else:
2098             code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2099
2100 #-------------------------------------------------------------------
2101 #
2102 #  Constructor nodes
2103 #
2104 #-------------------------------------------------------------------
2105
2106 class SequenceNode(ExprNode):
2107     #  Base class for list and tuple constructor nodes.
2108     #  Contains common code for performing sequence unpacking.
2109     #
2110     #  args                    [ExprNode]
2111     #  iterator                ExprNode
2112     #  unpacked_items          [ExprNode] or None
2113     #  coerced_unpacked_items  [ExprNode] or None
2114     
2115     subexprs = ['args']
2116     
2117     is_sequence_constructor = 1
2118     unpacked_items = None
2119     
2120     def compile_time_value_list(self, denv):
2121         return [arg.compile_time_value(denv) for arg in self.args]
2122
2123     def analyse_target_declaration(self, env):
2124         for arg in self.args:
2125             arg.analyse_target_declaration(env)
2126
2127     def analyse_types(self, env):
2128         for i in range(len(self.args)):
2129             arg = self.args[i]
2130             arg.analyse_types(env)
2131             self.args[i] = arg.coerce_to_pyobject(env)
2132         self.type = py_object_type
2133         self.is_temp = 1
2134     
2135     def analyse_target_types(self, env):
2136         self.iterator = PyTempNode(self.pos, env)
2137         self.unpacked_items = []
2138         self.coerced_unpacked_items = []
2139         for arg in self.args:
2140             arg.analyse_target_types(env)
2141             unpacked_item = PyTempNode(self.pos, env)
2142             coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2143             self.unpacked_items.append(unpacked_item)
2144             self.coerced_unpacked_items.append(coerced_unpacked_item)
2145         self.type = py_object_type
2146         env.use_utility_code(unpacking_utility_code)
2147     
2148     def allocate_target_temps(self, env, rhs):
2149         self.iterator.allocate_temps(env)
2150         for arg, node in zip(self.args, self.coerced_unpacked_items):
2151             node.allocate_temps(env)
2152             arg.allocate_target_temps(env, node)
2153             #arg.release_target_temp(env)
2154             #node.release_temp(env)
2155         if rhs:
2156             rhs.release_temp(env)
2157         self.iterator.release_temp(env)
2158     
2159 #       def release_target_temp(self, env):
2160 #               #for arg in self.args:
2161 #               #       arg.release_target_temp(env)
2162 #               #for node in self.coerced_unpacked_items:
2163 #               #       node.release_temp(env)
2164 #               self.iterator.release_temp(env)
2165     
2166     def generate_result_code(self, code):
2167         self.generate_operation_code(code)
2168     
2169     def generate_assignment_code(self, rhs, code):
2170         code.putln(
2171             "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
2172                 rhs.py_result(), 
2173                 rhs.py_result(), 
2174                 len(self.args)))
2175         code.putln("PyObject* tuple = %s;" % rhs.py_result())
2176         for i in range(len(self.args)):
2177             item = self.unpacked_items[i]
2178             code.putln(
2179                 "%s = PyTuple_GET_ITEM(tuple, %s);" % (
2180                     item.result_code,
2181                     i))
2182             code.put_incref(item.result_code, item.ctype())
2183             value_node = self.coerced_unpacked_items[i]
2184             value_node.generate_evaluation_code(code)
2185             self.args[i].generate_assignment_code(value_node, code)
2186             
2187         rhs.generate_disposal_code(code)
2188         code.putln("}")
2189         code.putln("else {")
2190
2191         code.putln(
2192             "%s = PyObject_GetIter(%s); %s" % (
2193                 self.iterator.result_code,
2194                 rhs.py_result(),
2195                 code.error_goto_if_null(self.iterator.result_code, self.pos)))
2196         rhs.generate_disposal_code(code)
2197         for i in range(len(self.args)):
2198             item = self.unpacked_items[i]
2199             unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
2200                 self.iterator.py_result(), i)
2201             code.putln(
2202                 "%s = %s; %s" % (
2203                     item.result_code,
2204                     typecast(item.ctype(), py_object_type, unpack_code),
2205                     code.error_goto_if_null(item.result_code, self.pos)))
2206             value_node = self.coerced_unpacked_items[i]
2207             value_node.generate_evaluation_code(code)
2208             self.args[i].generate_assignment_code(value_node, code)
2209         code.put_error_if_neg(self.pos, 
2210             "__Pyx_EndUnpack(%s)" % (
2211                 self.iterator.py_result()))
2212         if debug_disposal_code:
2213             print("UnpackNode.generate_assignment_code:")
2214             print("...generating disposal code for %s" % self.iterator)
2215         self.iterator.generate_disposal_code(code)
2216
2217         code.putln("}")
2218         
2219     def annotate(self, code):
2220         for arg in self.args:
2221             arg.annotate(code)
2222         if self.unpacked_items:
2223             for arg in self.unpacked_items:
2224                 arg.annotate(code)
2225             for arg in self.coerced_unpacked_items:
2226                 arg.annotate(code)
2227
2228
2229 class TupleNode(SequenceNode):
2230     #  Tuple constructor.
2231     
2232     def analyse_types(self, env):
2233         if len(self.args) == 0:
2234             self.is_temp = 0
2235             self.is_literal = 1
2236         else:
2237             SequenceNode.analyse_types(self, env)
2238         self.type = tuple_type
2239             
2240     def calculate_result_code(self):
2241         if len(self.args) > 0:
2242             error(self.pos, "Positive length tuples must be constructed.")
2243         else:
2244             return Naming.empty_tuple
2245
2246     def compile_time_value(self, denv):
2247         values = self.compile_time_value_list(denv)
2248         try:
2249             return tuple(values)
2250         except Exception, e:
2251             self.compile_time_value_error(e)
2252     
2253     def generate_operation_code(self, code):
2254         if len(self.args) == 0:
2255             # result_code is Naming.empty_tuple
2256             return
2257         code.putln(
2258             "%s = PyTuple_New(%s); %s" % (
2259                 self.result_code,
2260                 len(self.args),
2261                 code.error_goto_if_null(self.result_code, self.pos)))
2262         for i in range(len(self.args)):
2263             arg = self.args[i]
2264             if not arg.result_in_temp():
2265                 code.put_incref(arg.result_code, arg.ctype())
2266             code.putln(
2267                 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2268                     self.result_code,
2269                     i,
2270                     arg.py_result()))
2271     
2272     def generate_subexpr_disposal_code(self, code):
2273         # We call generate_post_assignment_code here instead
2274         # of generate_disposal_code, because values were stored
2275         # in the tuple using a reference-stealing operation.
2276         for arg in self.args:
2277             arg.generate_post_assignment_code(code)             
2278
2279
2280 class ListNode(SequenceNode):
2281     #  List constructor.
2282     
2283     def analyse_types(self, env):
2284         SequenceNode.analyse_types(self, env)
2285         self.type = list_type
2286
2287     def compile_time_value(self, denv):
2288         return self.compile_time_value_list(denv)
2289
2290     def generate_operation_code(self, code):
2291         code.putln("%s = PyList_New(%s); %s" %
2292             (self.result_code,
2293             len(self.args),
2294             code.error_goto_if_null(self.result_code, self.pos)))
2295         for i in range(len(self.args)):
2296             arg = self.args[i]
2297             #if not arg.is_temp:
2298             if not arg.result_in_temp():
2299                 code.put_incref(arg.result_code, arg.ctype())
2300             code.putln("PyList_SET_ITEM(%s, %s, %s);" %
2301                 (self.result_code,
2302                 i,
2303                 arg.py_result()))
2304                 
2305     def generate_subexpr_disposal_code(self, code):
2306         # We call generate_post_assignment_code here instead
2307         # of generate_disposal_code, because values were stored
2308         # in the list using a reference-stealing operation.
2309         for arg in self.args:
2310             arg.generate_post_assignment_code(code)             
2311
2312             
2313 class ListComprehensionNode(SequenceNode):
2314
2315     subexprs = []
2316     is_sequence_constructor = 0 # not unpackable
2317
2318     def analyse_types(self, env): 
2319         self.type = list_type
2320         self.is_temp = 1
2321         self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
2322         
2323     def allocate_temps(self, env, result = None): 
2324         if debug_temp_alloc:
2325             print("%s Allocating temps" % self)
2326         self.allocate_temp(env, result)
2327         self.loop.analyse_declarations(env)
2328         self.loop.analyse_expressions(env)
2329         
2330     def generate_operation_code(self, code):
2331         code.putln("%s = PyList_New(%s); %s" %
2332             (self.result_code,
2333             0,
2334             code.error_goto_if_null(self.result_code, self.pos)))
2335         self.loop.generate_execution_code(code)
2336         
2337     def annotate(self, code):
2338         self.loop.annotate(code)
2339
2340
2341 class ListComprehensionAppendNode(ExprNode):
2342
2343     subexprs = ['expr']
2344     
2345     def analyse_types(self, env):
2346         self.expr.analyse_types(env)
2347         if self.expr.type != py_object_type:
2348             self.expr = self.expr.coerce_to_pyobject(env)
2349         self.type = PyrexTypes.c_int_type
2350         self.is_temp = 1
2351     
2352     def generate_result_code(self, code):
2353         code.putln("%s = PyList_Append(%s, %s); %s" %
2354             (self.result_code,
2355             self.target.result_code,
2356             self.expr.result_code,
2357             code.error_goto_if(self.result_code, self.pos)))
2358
2359
2360 class DictNode(ExprNode):
2361     #  Dictionary constructor.
2362     #
2363     #  key_value_pairs  [DictItemNode]
2364     
2365     subexprs = ['key_value_pairs']
2366     
2367     def compile_time_value(self, denv):
2368         pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
2369             for item in self.key_value_pairs]
2370         try:
2371             return dict(pairs)
2372         except Exception, e:
2373             self.compile_time_value_error(e)
2374     
2375     def analyse_types(self, env):
2376         for item in self.key_value_pairs:
2377             item.analyse_types(env)
2378         self.type = dict_type
2379         self.is_temp = 1
2380     
2381     def allocate_temps(self, env, result = None):
2382         #  Custom method used here because key-value
2383         #  pairs are evaluated and used one at a time.
2384         self.allocate_temp(env, result)
2385         for item in self.key_value_pairs:
2386             item.key.allocate_temps(env)
2387             item.value.allocate_temps(env)
2388             item.key.release_temp(env)
2389             item.value.release_temp(env)
2390     
2391     def generate_evaluation_code(self, code):
2392         #  Custom method used here because key-value
2393         #  pairs are evaluated and used one at a time.
2394         code.putln(
2395             "%s = PyDict_New(); %s" % (
2396                 self.result_code,
2397                 code.error_goto_if_null(self.result_code, self.pos)))
2398         for item in self.key_value_pairs:
2399             item.generate_evaluation_code(code)
2400             code.put_error_if_neg(self.pos, 
2401                 "PyDict_SetItem(%s, %s, %s)" % (
2402                     self.result_code,
2403                     item.key.py_result(),
2404                     item.value.py_result()))
2405             item.generate_disposal_code(code)
2406             
2407     def annotate(self, code):
2408         for item in self.key_value_pairs:
2409             item.annotate(code)
2410             
2411 class DictItemNode(ExprNode):
2412     # Represents a single item in a DictNode
2413     #
2414     # key          ExprNode
2415     # value        ExprNode
2416     subexprs = ['key', 'value']
2417             
2418     def analyse_types(self, env):
2419         self.key.analyse_types(env)
2420         self.value.analyse_types(env)
2421         self.key = self.key.coerce_to_pyobject(env)
2422         self.value = self.value.coerce_to_pyobject(env)
2423         
2424     def generate_evaluation_code(self, code):
2425         self.key.generate_evaluation_code(code)
2426         self.value.generate_evaluation_code(code)
2427         
2428     def generate_disposal_code(self, code):
2429         self.key.generate_disposal_code(code)
2430         self.value.generate_disposal_code(code)
2431
2432
2433 class ClassNode(ExprNode):
2434     #  Helper class used in the implementation of Python
2435     #  class definitions. Constructs a class object given
2436     #  a name, tuple of bases and class dictionary.
2437     #
2438     #  name         EncodedString      Name of the class
2439     #  cname        string             Class name as a Python string
2440     #  bases        ExprNode           Base class tuple
2441     #  dict         ExprNode           Class dict (not owned by this node)
2442     #  doc          ExprNode or None   Doc string
2443     #  module_name  string             Name of defining module
2444     
2445     subexprs = ['bases', 'doc']
2446
2447     def analyse_types(self, env):
2448         self.cname = env.intern_identifier(self.name)
2449         self.bases.analyse_types(env)
2450         if self.doc:
2451             self.doc.analyse_types(env)
2452             self.doc = self.doc.coerce_to_pyobject(env)
2453         self.module_name = env.global_scope().qualified_name
2454         self.type = py_object_type
2455         self.is_temp = 1
2456         env.use_utility_code(create_class_utility_code);
2457
2458     def generate_result_code(self, code):
2459         if self.doc:
2460             code.put_error_if_neg(self.pos, 
2461                 'PyDict_SetItemString(%s, "__doc__", %s)' % (
2462                     self.dict.py_result(),
2463                     self.doc.py_result()))
2464         code.putln(
2465             '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
2466                 self.result_code,
2467                 self.bases.py_result(),
2468                 self.dict.py_result(),
2469                 self.cname,
2470                 self.module_name,
2471                 code.error_goto_if_null(self.result_code, self.pos)))
2472
2473
2474 class UnboundMethodNode(ExprNode):
2475     #  Helper class used in the implementation of Python
2476     #  class definitions. Constructs an unbound method
2477     #  object from a class and a function.
2478     #
2479     #  class_cname   string     C var holding the class object
2480     #  function      ExprNode   Function object
2481     
2482     subexprs = ['function']
2483     
2484     def analyse_types(self, env):
2485         self.function.analyse_types(env)
2486         self.type = py_object_type
2487         self.is_temp = 1
2488     
2489     def generate_result_code(self, code):
2490         code.putln(
2491             "%s = PyMethod_New(%s, 0, %s); %s" % (
2492                 self.result_code,
2493                 self.function.py_result(),
2494                 self.class_cname,
2495                 code.error_goto_if_null(self.result_code, self.pos)))
2496
2497
2498 class PyCFunctionNode(AtomicExprNode):
2499     #  Helper class used in the implementation of Python
2500     #  class definitions. Constructs a PyCFunction object
2501     #  from a PyMethodDef struct.
2502     #
2503     #  pymethdef_cname   string   PyMethodDef structure
2504     
2505     def analyse_types(self, env):
2506         self.type = py_object_type
2507         self.is_temp = 1
2508     
2509     def generate_result_code(self, code):
2510         code.putln(
2511             "%s = PyCFunction_New(&%s, 0); %s" % (
2512                 self.result_code,
2513                 self.pymethdef_cname,
2514                 code.error_goto_if_null(self.result_code, self.pos)))
2515
2516 #-------------------------------------------------------------------
2517 #
2518 #  Unary operator nodes
2519 #
2520 #-------------------------------------------------------------------
2521
2522 compile_time_unary_operators = {
2523     'not': operator.not_,
2524     '~': operator.inv,
2525     '-': operator.neg,
2526     '+': operator.pos,
2527 }
2528
2529 class UnopNode(ExprNode):
2530     #  operator     string
2531     #  operand      ExprNode
2532     #
2533     #  Processing during analyse_expressions phase:
2534     #
2535     #    analyse_c_operation
2536     #      Called when the operand is not a pyobject.
2537     #      - Check operand type and coerce if needed.
2538     #      - Determine result type and result code fragment.
2539     #      - Allocate temporary for result if needed.
2540     
2541     subexprs = ['operand']
2542     
2543     def compile_time_value(self, denv):
2544         func = compile_time_unary_operators.get(self.operator)
2545         if not func:
2546             error(self.pos,
2547                 "Unary '%s' not supported in compile-time expression"
2548                     % self.operator)
2549         operand = self.operand.compile_time_value(denv)
2550         try:
2551             return func(operand)
2552         except Exception, e:
2553             self.compile_time_value_error(e)
2554
2555     def analyse_types(self, env):
2556         self.operand.analyse_types(env)
2557         if self.is_py_operation():
2558             self.coerce_operand_to_pyobject(env)
2559             self.type = py_object_type
2560             self.is_temp = 1
2561         else:
2562             self.analyse_c_operation(env)
2563     
2564     def check_const(self):
2565         self.operand.check_const()
2566     
2567     def is_py_operation(self):
2568         return self.operand.type.is_pyobject
2569     
2570     def coerce_operand_to_pyobject(self, env):
2571         self.operand = self.operand.coerce_to_pyobject(env)
2572     
2573     def generate_result_code(self, code):
2574         if self.operand.type.is_pyobject:
2575             self.generate_py_operation_code(code)
2576         else:
2577             if self.is_temp:
2578                 self.generate_c_operation_code(code)
2579     
2580     def generate_py_operation_code(self, code):
2581         function = self.py_operation_function()
2582         code.putln(
2583             "%s = %s(%s); %s" % (
2584                 self.result_code, 
2585                 function, 
2586                 self.operand.py_result(),
2587                 code.error_goto_if_null(self.result_code, self.pos)))
2588         
2589     def type_error(self):
2590         if not self.operand.type.is_error:
2591             error(self.pos, "Invalid operand type for '%s' (%s)" %
2592                 (self.operator, self.operand.type))
2593         self.type = PyrexTypes.error_type
2594
2595
2596 class NotNode(ExprNode):
2597     #  'not' operator
2598     #
2599     #  operand   ExprNode
2600     
2601     def compile_time_value(self, denv):
2602         operand = self.operand.compile_time_value(denv)
2603         try:
2604             return not operand
2605         except Exception, e:
2606             self.compile_time_value_error(e)
2607
2608     subexprs = ['operand']
2609     
2610     def analyse_types(self, env):
2611         self.operand.analyse_types(env)
2612         self.operand = self.operand.coerce_to_boolean(env)
2613         self.type = PyrexTypes.c_bint_type
2614     
2615     def calculate_result_code(self):
2616         return "(!%s)" % self.operand.result_code
2617     
2618     def generate_result_code(self, code):
2619         pass
2620
2621
2622 class UnaryPlusNode(UnopNode):
2623     #  unary '+' operator
2624     
2625     operator = '+'
2626     
2627     def analyse_c_operation(self, env):
2628         self.type = self.operand.type
2629     
2630     def py_operation_function(self):
2631         return "PyNumber_Positive"
2632     
2633     def calculate_result_code(self):
2634         return self.operand.result_code
2635
2636
2637 class UnaryMinusNode(UnopNode):
2638     #  unary '-' operator
2639     
2640     operator = '-'
2641     
2642     def analyse_c_operation(self, env):
2643         if self.operand.type.is_numeric:
2644             self.type = self.operand.type
2645         else:
2646             self.type_error()
2647     
2648     def py_operation_function(self):
2649         return "PyNumber_Negative"
2650     
2651     def calculate_result_code(self):
2652         return "(-%s)" % self.operand.result_code
2653
2654
2655 class TildeNode(UnopNode):
2656     #  unary '~' operator
2657
2658     def analyse_c_operation(self, env):
2659         if self.operand.type.is_int:
2660             self.type = self.operand.type
2661         else:
2662             self.type_error()
2663
2664     def py_operation_function(self):
2665         return "PyNumber_Invert"
2666     
2667     def calculate_result_code(self):
2668         return "(~%s)" % self.operand.result_code
2669
2670
2671 class AmpersandNode(ExprNode):
2672     #  The C address-of operator.
2673     #
2674     #  operand  ExprNode
2675     
2676     subexprs = ['operand']
2677
2678     def analyse_types(self, env):
2679         self.operand.analyse_types(env)
2680         argtype = self.operand.type
2681         if not (argtype.is_cfunction or self.operand.is_lvalue()):
2682             self.error("Taking address of non-lvalue")
2683             return
2684         if argtype.is_pyobject:
2685             self.error("Cannot take address of Python variable")
2686             return
2687         self.type = PyrexTypes.c_ptr_type(argtype)
2688     
2689     def check_const(self):
2690         self.operand.check_const_addr()
2691     
2692     def error(self, mess):
2693         error(self.pos, mess)
2694         self.type = PyrexTypes.error_type
2695         self.result_code = "<error>"
2696     
2697     def calculate_result_code(self):
2698         return "(&%s)" % self.operand.result_code
2699
2700     def generate_result_code(self, code):
2701         pass
2702     
2703
2704 unop_node_classes = {
2705     "+":  UnaryPlusNode,
2706     "-":  UnaryMinusNode,
2707     "~":  TildeNode,
2708 }
2709
2710 def unop_node(pos, operator, operand):
2711     # Construct unnop node of appropriate class for 
2712     # given operator.
2713     if isinstance(operand, IntNode) and operator == '-':
2714         return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
2715     elif isinstance(operand, UnopNode) and operand.operator == operator:
2716         warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
2717     return unop_node_classes[operator](pos, 
2718         operator = operator, 
2719         operand = operand)
2720
2721
2722 class TypecastNode(ExprNode):
2723     #  C type cast
2724     #
2725     #  base_type    CBaseTypeNode
2726     #  declarator   CDeclaratorNode
2727     #  operand      ExprNode
2728     
2729     subexprs = ['operand']
2730     
2731     def analyse_types(self, env):
2732         base_type = self.base_type.analyse(env)
2733         _, self.type = self.declarator.analyse(base_type, env)
2734         self.operand.analyse_types(env)
2735         to_py = self.type.is_pyobject
2736         from_py = self.operand.type.is_pyobject
2737         if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
2738             error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
2739         if to_py and not from_py:
2740             self.result_ctype = py_object_type
2741             self.is_temp = 1
2742             if self.operand.type.to_py_function:
2743                 self.operand = self.operand.coerce_to_pyobject(env)
2744             else:
2745                 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
2746         elif from_py and not to_py:
2747             if self.type.from_py_function:
2748                 self.operand = self.operand.coerce_to(self.type, env)
2749             else:
2750                 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
2751         elif from_py and to_py:
2752             if self.typecheck and self.type.is_extension_type:
2753                 self.operand = PyTypeTestNode(self.operand, self.type, env)
2754     
2755     def check_const(self):
2756         self.operand.check_const()
2757     
2758     def calculate_result_code(self):
2759         opnd = self.operand
2760         result_code = self.type.cast_code(opnd.result_code)
2761         return result_code
2762     
2763     def result_as(self, type):
2764         if self.type.is_pyobject and not self.is_temp:
2765             #  Optimise away some unnecessary casting
2766             return self.operand.result_as(type)
2767         else:
2768             return ExprNode.result_as(self, type)
2769
2770     def generate_result_code(self, code):
2771         if self.is_temp:
2772             code.putln(
2773                 "%s = (PyObject *)%s;" % (
2774                     self.result_code,
2775                     self.operand.result_code))
2776             code.put_incref(self.result_code, self.ctype())
2777
2778
2779 class SizeofNode(ExprNode):
2780     #  Abstract base class for sizeof(x) expression nodes.
2781
2782     def check_const(self):
2783         pass
2784
2785     def generate_result_code(self, code):
2786         pass
2787
2788
2789 class SizeofTypeNode(SizeofNode):
2790     #  C sizeof function applied to a type
2791     #
2792     #  base_type   CBaseTypeNode
2793     #  declarator  CDeclaratorNode
2794     
2795     subexprs = []
2796     
2797     def analyse_types(self, env):
2798         base_type = self.base_type.analyse(env)
2799         _, arg_type = self.declarator.analyse(base_type, env)
2800         self.arg_type = arg_type
2801         if arg_type.is_pyobject and not arg_type.is_extension_type:
2802             error(self.pos, "Cannot take sizeof Python object")
2803         elif arg_type.is_void:
2804             error(self.pos, "Cannot take sizeof void")
2805         elif not arg_type.is_complete():
2806             error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
2807         self.type = PyrexTypes.c_int_type
2808         
2809     def calculate_result_code(self):
2810         if self.arg_type.is_extension_type:
2811             # the size of the pointer is boring
2812             # we want the size of the actual struct
2813             arg_code = self.arg_type.declaration_code("", deref=1)
2814         else:
2815             arg_code = self.arg_type.declaration_code("")
2816         return "(sizeof(%s))" % arg_code
2817     
2818
2819 class SizeofVarNode(SizeofNode):
2820     #  C sizeof function applied to a variable
2821     #
2822     #  operand   ExprNode
2823     
2824     subexprs = ['operand']
2825     
2826     def analyse_types(self, env):
2827         self.operand.analyse_types(env)
2828         self.type = PyrexTypes.c_int_type
2829     
2830     def calculate_result_code(self):
2831         return "(sizeof(%s))" % self.operand.result_code
2832     
2833     def generate_result_code(self, code):
2834         pass
2835
2836
2837 #-------------------------------------------------------------------
2838 #
2839 #  Binary operator nodes
2840 #
2841 #-------------------------------------------------------------------
2842
2843 def _not_in(x, seq):
2844     return x not in seq
2845
2846 compile_time_binary_operators = {
2847     '<': operator.lt,
2848     '<=': operator.le,
2849     '==': operator.eq,
2850     '!=': operator.ne,
2851     '>=': operator.ge,
2852     '>': operator.gt,
2853     'is': operator.is_,
2854     'is_not': operator.is_not,
2855     '+': operator.add,
2856     '&': operator.and_,
2857     '/': operator.div,
2858     '//': operator.floordiv,
2859     '<<': operator.lshift,
2860     '%': operator.mod,
2861     '*': operator.mul,
2862     '|': operator.or_,
2863     '**': operator.pow,
2864     '>>': operator.rshift,
2865     '-': operator.sub,
2866     #'/': operator.truediv,
2867     '^': operator.xor,
2868     'in': operator.contains,
2869     'not_in': _not_in,
2870 }
2871
2872 def get_compile_time_binop(node):
2873     func = compile_time_binary_operators.get(node.operator)
2874     if not func:
2875         error(node.pos,
2876             "Binary '%s' not supported in compile-time expression"
2877                 % node.operator)
2878     return func
2879
2880 class BinopNode(ExprNode):
2881     #  operator     string
2882     #  operand1     ExprNode
2883     #  operand2     ExprNode
2884     #
2885     #  Processing during analyse_expressions phase:
2886     #
2887     #    analyse_c_operation
2888     #      Called when neither operand is a pyobject.
2889     #      - Check operand types and coerce if needed.
2890     #      - Determine result type and result code fragment.
2891     #      - Allocate temporary for result if needed.
2892     
2893     subexprs = ['operand1', 'operand2']
2894     
2895     def compile_time_value(self, denv):
2896         func = get_compile_time_binop(self)
2897         operand1 = self.operand1.compile_time_value(denv)
2898         operand2 = self.operand2.compile_time_value(denv)
2899         try:
2900             return func(operand1, operand2)
2901         except Exception, e:
2902             self.compile_time_value_error(e)
2903
2904     def analyse_types(self, env):
2905         self.operand1.analyse_types(env)
2906         self.operand2.analyse_types(env)
2907         if self.is_py_operation():
2908             self.coerce_operands_to_pyobjects(env)
2909             self.type = py_object_type
2910             self.is_temp = 1
2911             if Options.incref_local_binop and self.operand1.type.is_pyobject:
2912                 self.operand1 = self.operand1.coerce_to_temp(env)
2913         else:
2914             self.analyse_c_operation(env)
2915     
2916     def is_py_operation(self):
2917         return (self.operand1.type.is_pyobject 
2918             or self.operand2.type.is_pyobject)
2919     
2920     def coerce_operands_to_pyobjects(self, env):
2921         self.operand1 = self.operand1.coerce_to_pyobject(env)
2922         self.operand2 = self.operand2.coerce_to_pyobject(env)
2923     
2924     def check_const(self):
2925         self.operand1.check_const()
2926         self.operand2.check_const()
2927     
2928     def generate_result_code(self, code):
2929         #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
2930         if self.operand1.type.is_pyobject:
2931             function = self.py_operation_function()
2932             if function == "PyNumber_Power":
2933                 extra_args = ", Py_None"
2934             else:
2935                 extra_args = ""
2936             code.putln(
2937                 "%s = %s(%s, %s%s); %s" % (
2938                     self.result_code, 
2939                     function, 
2940                     self.operand1.py_result(),
2941                     self.operand2.py_result(),
2942                     extra_args,
2943                     code.error_goto_if_null(self.result_code, self.pos)))
2944         else:
2945             if self.is_temp:
2946                 self.generate_c_operation_code(code)
2947     
2948     def type_error(self):
2949         if not (self.operand1.type.is_error
2950                 or self.operand2.type.is_error):
2951             error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
2952                 (self.operator, self.operand1.type, 
2953                     self.operand2.type))
2954         self.type = PyrexTypes.error_type
2955
2956
2957 class NumBinopNode(BinopNode):
2958     #  Binary operation taking numeric arguments.
2959     
2960     def analyse_c_operation(self, env):
2961         type1 = self.operand1.type
2962         type2 = self.operand2.type
2963         if self.operator == "**" and type1.is_int and type2.is_int:
2964             error(self.pos, "** with two C int types is ambiguous")
2965             self.type = error_type
2966             return
2967         self.type = self.compute_c_result_type(type1, type2)
2968         if not self.type:
2969             self.type_error()
2970     
2971     def compute_c_result_type(self, type1, type2):
2972         if self.c_types_okay(type1, type2):
2973             return PyrexTypes.widest_numeric_type(type1, type2)
2974         else:
2975             return None
2976     
2977     def c_types_okay(self, type1, type2):
2978         #print "NumBinopNode.c_types_okay:", type1, type2 ###
2979         return (type1.is_numeric  or type1.is_enum) \
2980             and (type2.is_numeric  or type2.is_enum)
2981
2982     def calculate_result_code(self):
2983         return "(%s %s %s)" % (
2984             self.operand1.result_code, 
2985             self.operator, 
2986             self.operand2.result_code)
2987     
2988     def py_operation_function(self):
2989         return self.py_functions[self.operator]
2990
2991     py_functions = {
2992         "|":            "PyNumber_Or",
2993         "^":            "PyNumber_Xor",
2994         "&":            "PyNumber_And",
2995         "<<":           "PyNumber_Lshift",
2996         ">>":           "PyNumber_Rshift",
2997         "+":            "PyNumber_Add",
2998         "-":            "PyNumber_Subtract",
2999         "*":            "PyNumber_Multiply",
3000         "/":            "PyNumber_Divide",
3001         "//":           "PyNumber_FloorDivide",
3002         "%":            "PyNumber_Remainder",
3003         "**":       "PyNumber_Power"
3004     }
3005
3006
3007 class IntBinopNode(NumBinopNode):
3008     #  Binary operation taking integer arguments.
3009     
3010     def c_types_okay(self, type1, type2):
3011         #print "IntBinopNode.c_types_okay:", type1, type2 ###
3012         return (type1.is_int or type1.is_enum) \
3013             and (type2.is_int or type2.is_enum)
3014
3015     
3016 class AddNode(NumBinopNode):
3017     #  '+' operator.
3018     
3019     def is_py_operation(self):
3020         if self.operand1.type.is_string \
3021             and self.operand2.type.is_string:
3022                 return 1
3023         else:
3024             return NumBinopNode.is_py_operation(self)
3025
3026     def compute_c_result_type(self, type1, type2):
3027         #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
3028         if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3029             return type1
3030         elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
3031             return type2
3032         else:
3033             return NumBinopNode.compute_c_result_type(
3034                 self, type1, type2)
3035
3036
3037 class SubNode(NumBinopNode):
3038     #  '-' operator.
3039     
3040     def compute_c_result_type(self, type1, type2):
3041         if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3042             return type1
3043         elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
3044             return PyrexTypes.c_int_type
3045         else:
3046             return NumBinopNode.compute_c_result_type(
3047                 self, type1, type2)
3048
3049
3050 class MulNode(NumBinopNode):
3051     #  '*' operator.
3052     
3053     def is_py_operation(self):
3054         type1 = self.operand1.type
3055         type2 = self.operand2.type
3056         if (type1.is_string and type2.is_int) \
3057             or (type2.is_string and type1.is_int):
3058                 return 1
3059         else:
3060             return NumBinopNode.is_py_operation(self)
3061
3062
3063 class FloorDivNode(NumBinopNode):
3064     #  '//' operator.
3065     
3066     def calculate_result_code(self):
3067         return "(%s %s %s)" % (
3068             self.operand1.result_code, 
3069             "/",  # c division is by default floor-div 
3070             self.operand2.result_code)
3071
3072
3073 class ModNode(IntBinopNode):
3074     #  '%' operator.
3075     
3076     def is_py_operation(self):
3077         return (self.operand1.type.is_string
3078             or self.operand2.type.is_string
3079             or IntBinopNode.is_py_operation(self))
3080
3081
3082 class PowNode(NumBinopNode):
3083     #  '**' operator.
3084
3085     def analyse_types(self, env):
3086         env.pow_function_used = 1
3087         NumBinopNode.analyse_types(self, env)
3088
3089     def compute_c_result_type(self, type1, type2):
3090         if self.c_types_okay(type1, type2):
3091             return PyrexTypes.c_double_type
3092         else:
3093             return None
3094
3095     def c_types_okay(self, type1, type2):
3096         return type1.is_float or type2.is_float
3097
3098     def type_error(self):
3099         if not (self.operand1.type.is_error or self.operand2.type.is_error):
3100             if self.operand1.type.is_int and self.operand2.type.is_int:
3101                 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
3102                     (self.operator, self.operand1.type, self.operand2.type))
3103             else:
3104                 NumBinopNode.type_error(self)
3105         self.type = PyrexTypes.error_type
3106
3107     def calculate_result_code(self):
3108         return "pow(%s, %s)" % (
3109             self.operand1.result_code, self.operand2.result_code)
3110
3111
3112 class BoolBinopNode(ExprNode):
3113     #  Short-circuiting boolean operation.
3114     #
3115     #  operator     string
3116     #  operand1     ExprNode
3117     #  operand2     ExprNode
3118     #  temp_bool    ExprNode     used internally
3119     
3120     temp_bool = None
3121     
3122     subexprs = ['operand1', 'operand2', 'temp_bool']
3123     
3124     def compile_time_value(self, denv):
3125         if self.operator == 'and':
3126             return self.operand1.compile_time_value(denv) \
3127                 and self.operand2.compile_time_value(denv)
3128         else:
3129             return self.operand1.compile_time_value(denv) \
3130                 or self.operand2.compile_time_value(denv)
3131
3132     def analyse_types(self, env):
3133         self.operand1.analyse_types(env)
3134         self.operand2.analyse_types(env)
3135         if self.operand1.type.is_pyobject or \
3136                 self.operand2.type.is_pyobject:
3137             self.operand1 = self.operand1.coerce_to_pyobject(env)
3138             self.operand2 = self.operand2.coerce_to_pyobject(env)
3139             self.temp_bool = TempNode(self.pos, PyrexTypes.c_bint_type, env)
3140             self.type = py_object_type
3141         else:
3142             self.operand1 = self.operand1.coerce_to_boolean(env)
3143             self.operand2 = self.operand2.coerce_to_boolean(env)
3144             self.type = PyrexTypes.c_bint_type
3145         # For what we're about to do, it's vital that
3146         # both operands be temp nodes.
3147         self.operand1 = self.operand1.coerce_to_temp(env) #CTT
3148         self.operand2 = self.operand2.coerce_to_temp(env)
3149         # coerce_to_simple does not seem to be sufficient
3150         #self.operand1 = self.operand1.coerce_to_simple(env)
3151         #self.operand2 = self.operand2.coerce_to_simple(env)
3152         self.is_temp = 1
3153     
3154     def allocate_temps(self, env, result_code = None):
3155         #  We don't need both operands at the same time, and
3156         #  one of the operands will also be our result. So we
3157         #  use an allocation strategy here which results in
3158         #  this node and both its operands sharing the same
3159         #  result variable. This allows us to avoid some 
3160         #  assignments and increfs/decrefs that would otherwise
3161         #  be necessary.
3162         self.allocate_temp(env, result_code)
3163         self.operand1.allocate_temps(env, self.result_code)
3164         if self.temp_bool:
3165             self.temp_bool.allocate_temp(env)
3166             self.temp_bool.release_temp(env)
3167         self.operand2.allocate_temps(env, self.result_code)
3168         #  We haven't called release_temp on either operand,
3169         #  because although they are temp nodes, they don't own 
3170         #  their result variable. And because they are temp
3171         #  nodes, any temps in their subnodes will have been
3172         #  released before their allocate_temps returned.
3173         #  Therefore, they contain no temp vars that need to
3174         #  be released.
3175
3176     def check_const(self):
3177         self.operand1.check_const()
3178         self.operand2.check_const()
3179     
3180     def calculate_result_code(self):
3181         return "(%s %s %s)" % (
3182             self.operand1.result_code,
3183             self.py_to_c_op[self.operator],
3184             self.operand2.result_code)
3185     
3186     py_to_c_op = {'and': "&&", 'or': "||"}
3187
3188     def generate_evaluation_code(self, code):
3189         self.operand1.generate_evaluation_code(code)
3190         test_result = self.generate_operand1_test(code)
3191         if self.operator == 'and':
3192             sense = ""
3193         else:
3194             sense = "!"
3195         code.putln(
3196             "if (%s%s) {" % (
3197                 sense,
3198                 test_result))
3199         self.operand1.generate_disposal_code(code)
3200         self.operand2.generate_evaluation_code(code)
3201         code.putln(
3202             "}")
3203     
3204     def generate_operand1_test(self, code):
3205         #  Generate code to test the truth of the first operand.
3206         if self.type.is_pyobject:
3207             test_result = self.temp_bool.result_code
3208             code.putln(
3209                 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3210                     test_result,
3211                     self.operand1.py_result(),
3212                     code.error_goto_if_neg(test_result, self.pos)))
3213         else:
3214             test_result = self.operand1.result_code
3215         return test_result
3216
3217
3218 class CondExprNode(ExprNode):
3219     #  Short-circuiting conditional expression.
3220     #
3221     #  test        ExprNode
3222     #  true_val    ExprNode
3223     #  false_val   ExprNode
3224     
3225     temp_bool = None
3226     
3227     subexprs = ['test', 'true_val', 'false_val']
3228     
3229     def analyse_types(self, env):
3230         self.test.analyse_types(env)
3231         self.test = self.test.coerce_to_boolean(env)
3232         self.true_val.analyse_types(env)
3233         self.false_val.analyse_types(env)
3234         self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
3235         if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
3236             self.true_val = self.true_val.coerce_to(self.type, env)
3237             self.false_val = self.false_val.coerce_to(self.type, env)
3238         # must be tmp variables so they can share a result
3239         self.true_val = self.true_val.coerce_to_temp(env)
3240         self.false_val = self.false_val.coerce_to_temp(env)
3241         self.is_temp = 1
3242         if self.type == PyrexTypes.error_type:
3243             self.type_error()
3244     
3245     def allocate_temps(self, env, result_code = None):
3246         #  We only ever evaluate one side, and this is 
3247         #  after evaluating the truth value, so we may
3248         #  use an allocation strategy here which results in
3249         #  this node and both its operands sharing the same
3250         #  result variable. This allows us to avoid some 
3251         #  assignments and increfs/decrefs that would otherwise
3252         #  be necessary.
3253         self.allocate_temp(env, result_code)
3254         self.test.allocate_temps(env, result_code)
3255         self.true_val.allocate_temps(env, self.result_code)
3256         self.false_val.allocate_temps(env, self.result_code)
3257         #  We haven't called release_temp on either value,
3258         #  because although they are temp nodes, they don't own 
3259         #  their result variable. And because they are temp
3260         #  nodes, any temps in their subnodes will have been
3261         #  released before their allocate_temps returned.
3262         #  Therefore, they contain no temp vars that need to
3263         #  be released.
3264         
3265     def compute_result_type(self, type1, type2):
3266         if type1 == type2:
3267             return type1
3268         elif type1.is_numeric and type2.is_numeric:
3269             return PyrexTypes.widest_numeric_type(type1, type2)
3270         elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
3271             return type2
3272         elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
3273             return type1
3274         elif type1.is_pyobject or type2.is_pyobject:
3275             return py_object_type
3276         elif type1.assignable_from(type2):
3277             return type1
3278         elif type2.assignable_from(type1):
3279             return type2
3280         else:
3281             return PyrexTypes.error_type
3282         
3283     def type_error(self):
3284         if not (self.true_val.type.is_error or self.false_val.type.is_error):
3285             error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
3286                 (self.true_val.type, self.false_val.type))
3287         self.type = PyrexTypes.error_type
3288     
3289     def check_const(self):
3290         self.test.check_const()
3291         self.true_val.check_const()
3292         self.false_val.check_const()
3293     
3294     def generate_evaluation_code(self, code):
3295         self.test.generate_evaluation_code(code)
3296         code.putln("if (%s) {" % self.test.result_code )
3297         self.true_val.generate_evaluation_code(code)
3298         code.putln("} else {")
3299         self.false_val.generate_evaluation_code(code)
3300         code.putln("}")
3301         self.test.generate_disposal_code(code)
3302
3303 richcmp_constants = {
3304     "<" : "Py_LT",
3305     "<=": "Py_LE",
3306     "==": "Py_EQ",
3307     "!=": "Py_NE",
3308     "<>": "Py_NE",
3309     ">" : "Py_GT",
3310     ">=": "Py_GE",
3311 }
3312
3313 class CmpNode:
3314     #  Mixin class containing code common to PrimaryCmpNodes
3315     #  and CascadedCmpNodes.
3316     
3317     def cascaded_compile_time_value(self, operand1, denv):
3318         func = get_compile_time_binop(self)
3319         operand2 = self.operand2.compile_time_value(denv)
3320         try:
3321             result = func(operand1, operand2)
3322         except Exception, e:
3323             self.compile_time_value_error(e)
3324             result = None
3325         if result:
3326             cascade = self.cascade
3327             if cascade:
3328                 result = result and cascade.compile_time_value(operand2, denv)
3329         return result
3330
3331     def is_python_comparison(self):
3332         return (self.has_python_operands()
3333             or (self.cascade and self.cascade.is_python_comparison())
3334             or self.operator in ('in', 'not_in'))
3335
3336     def is_python_result(self):
3337         return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
3338             or (self.cascade and self.cascade.is_python_result()))
3339
3340     def check_types(self, env, operand1, op, operand2):
3341         if not self.types_okay(operand1, op, operand2):
3342             error(self.pos, "Invalid types for '%s' (%s, %s)" %
3343                 (self.operator, operand1.type, operand2.type))
3344     
3345     def types_okay(self, operand1, op, operand2):
3346         type1 = operand1.type
3347         type2 = operand2.type
3348         if type1.is_error or type2.is_error:
3349             return 1
3350         if type1.is_pyobject: # type2 will be, too
3351             return 1
3352         elif type1.is_ptr or type1.is_array:
3353             return type1.is_null_ptr or type2.is_null_ptr \
3354                 or ((type2.is_ptr or type2.is_array)
3355                     and type1.base_type.same_as(type2.base_type))
3356         elif ((type1.is_numeric and type2.is_numeric
3357                     or type1.is_enum and (type1 is type2 or type2.is_int)
3358                     or type1.is_int and type2.is_enum)
3359                 and op not in ('is', 'is_not')):
3360             return 1
3361         else:
3362             return type1.is_cfunction and type1.is_cfunction and type1 == type2
3363
3364     def generate_operation_code(self, code, result_code, 
3365             operand1, op , operand2):
3366         if self.type is PyrexTypes.py_object_type:
3367             coerce_result = "__Pyx_PyBool_FromLong"
3368         else:
3369             coerce_result = ""
3370         if 'not' in op: negation = "!"
3371         else: negation = ""
3372         if op == 'in' or op == 'not_in':
3373             code.putln(
3374                 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
3375                     result_code, 
3376                     coerce_result, 
3377                     negation,
3378                     operand2.py_result(), 
3379                     operand1.py_result(), 
3380                     code.error_goto_if_neg(result_code, self.pos)))
3381         elif (operand1.type.is_pyobject
3382             and op not in ('is', 'is_not')):
3383                 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
3384                         result_code, 
3385                         operand1.py_result(), 
3386                         operand2.py_result(), 
3387                         richcmp_constants[op],
3388                         code.error_goto_if_null(result_code, self.pos)))
3389         else:
3390             type1 = operand1.type
3391             type2 = operand2.type
3392             if (type1.is_extension_type or type2.is_extension_type) \
3393                     and not type1.same_as(type2):
3394                 common_type = py_object_type
3395             elif type1.is_numeric:
3396                 common_type = PyrexTypes.widest_numeric_type(type1, type2)
3397             else:
3398                 common_type = type1
3399             code1 = operand1.result_as(common_type)
3400             code2 = operand2.result_as(common_type)
3401             code.putln("%s = %s(%s %s %s);" % (
3402                 result_code, 
3403                 coerce_result, 
3404                 code1, 
3405                 self.c_operator(op), 
3406                 code2))
3407
3408     def c_operator(self, op):
3409         if op == 'is':
3410             return "=="
3411         elif op == 'is_not':
3412             return "!="
3413         else:
3414             return op
3415     
3416
3417 class PrimaryCmpNode(ExprNode, CmpNode):
3418     #  Non-cascaded comparison or first comparison of
3419     #  a cascaded sequence.
3420     #
3421     #  operator      string
3422     #  operand1      ExprNode
3423     #  operand2      ExprNode
3424     #  cascade       CascadedCmpNode
3425     
3426     #  We don't use the subexprs mechanism, because
3427     #  things here are too complicated for it to handle.
3428     #  Instead, we override all the framework methods
3429     #  which use it.
3430     
3431     child_attrs = ['operand1', 'operand2', 'cascade']
3432     
3433     cascade = None
3434     
3435     def compile_time_value(self, denv):
3436         operand1 = self.operand1.compile_time_value(denv)
3437         return self.cascaded_compile_time_value(operand1, denv)
3438
3439     def analyse_types(self, env):
3440         self.operand1.analyse_types(env)
3441         self.operand2.analyse_types(env)
3442         if self.cascade:
3443             self.cascade.analyse_types(env, self.operand2)
3444         self.is_pycmp = self.is_python_comparison()
3445         if self.is_pycmp:
3446             self.coerce_operands_to_pyobjects(env)
3447         if self.has_int_operands():
3448             self.coerce_chars_to_ints(env)
3449         if self.cascade:
3450             #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
3451             self.operand2 = self.operand2.coerce_to_simple(env)
3452             self.cascade.coerce_cascaded_operands_to_temp(env)
3453         self.check_operand_types(env)
3454         if self.is_python_result():
3455             self.type = PyrexTypes.py_object_type
3456         else:
3457             self.type = PyrexTypes.c_bint_type
3458         cdr = self.cascade
3459         while cdr:
3460             cdr.type = self.type
3461             cdr = cdr.cascade
3462         if self.is_pycmp or self.cascade:
3463             self.is_temp = 1
3464     
3465     def check_operand_types(self, env):
3466         self.check_types(env, 
3467             self.operand1, self.operator, self.operand2)
3468         if self.cascade:
3469             self.cascade.check_operand_types(env, self.operand2)
3470     
3471     def has_python_operands(self):
3472         return (self.operand1.type.is_pyobject
3473             or self.operand2.type.is_pyobject)
3474             
3475     def coerce_operands_to_pyobjects(self, env):
3476         self.operand1 = self.operand1.coerce_to_pyobject(env)
3477         self.operand2 = self.operand2.coerce_to_pyobject(env)
3478         if self.cascade:
3479             self.cascade.coerce_operands_to_pyobjects(env)
3480         
3481     def has_int_operands(self):
3482         return (self.operand1.type.is_int or self.operand2.type.is_int) \
3483            or (self.cascade and self.cascade.has_int_operands())
3484     
3485     def coerce_chars_to_ints(self, env):
3486         if self.operand1.type.is_string:
3487             self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
3488         if self.operand2.type.is_string:
3489             self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3490         if self.cascade:
3491             self.cascade.coerce_chars_to_ints(env)
3492     
3493     def allocate_subexpr_temps(self, env):
3494         self.operand1.allocate_temps(env)
3495         self.operand2.allocate_temps(env)
3496         if self.cascade:
3497             self.cascade.allocate_subexpr_temps(env)
3498     
3499     def release_subexpr_temps(self, env):
3500         self.operand1.release_temp(env)
3501         self.operand2.release_temp(env)
3502         if self.cascade:
3503             self.cascade.release_subexpr_temps(env)
3504     
3505     def check_const(self):
3506         self.operand1.check_const()
3507         self.operand2.check_const()
3508         if self.cascade:
3509             self.not_const()
3510
3511     def calculate_result_code(self):
3512         return "(%s %s %s)" % (
3513             self.operand1.result_code,
3514             self.c_operator(self.operator),
3515             self.operand2.result_code)
3516     
3517     def generate_evaluation_code(self, code):
3518         self.operand1.generate_evaluation_code(code)
3519         self.operand2.generate_evaluation_code(code)
3520         if self.is_temp:
3521             self.generate_operation_code(code, self.result_code, 
3522                 self.operand1, self.operator, self.operand2)
3523             if self.cascade:
3524                 self.cascade.generate_evaluation_code(code,
3525                     self.result_code, self.operand2)
3526             self.operand1.generate_disposal_code(code)
3527             self.operand2.generate_disposal_code(code)
3528     
3529     def generate_subexpr_disposal_code(self, code):
3530         #  If this is called, it is a non-cascaded cmp,
3531         #  so only need to dispose of the two main operands.
3532         self.operand1.generate_disposal_code(code)
3533         self.operand2.generate_disposal_code(code)
3534         
3535     def annotate(self, code):
3536         self.operand1.annotate(code)
3537         self.operand2.annotate(code)
3538         if self.cascade:
3539             self.cascade.annotate(code)
3540
3541
3542 class CascadedCmpNode(Node, CmpNode):
3543     #  A CascadedCmpNode is not a complete expression node. It 
3544     #  hangs off the side of another comparison node, shares 
3545     #  its left operand with that node, and shares its result 
3546     #  with the PrimaryCmpNode at the head of the chain.
3547     #
3548     #  operator      string
3549     #  operand2      ExprNode
3550     #  cascade       CascadedCmpNode
3551
3552     child_attrs = ['operand2', 'cascade']
3553
3554     cascade = None
3555     
3556     def analyse_types(self, env, operand1):
3557         self.operand2.analyse_types(env)
3558         if self.cascade:
3559             self.cascade.analyse_types(env, self.operand2)
3560     
3561     def check_operand_types(self, env, operand1):
3562         self.check_types(env, 
3563             operand1, self.operator, self.operand2)
3564         if self.cascade:
3565             self.cascade.check_operand_types(env, self.operand2)
3566     
3567     def has_python_operands(self):
3568         return self.operand2.type.is_pyobject
3569         
3570     def coerce_operands_to_pyobjects(self, env):
3571         self.operand2 = self.operand2.coerce_to_pyobject(env)
3572         if self.cascade:
3573             self.cascade.coerce_operands_to_pyobjects(env)
3574
3575     def has_int_operands(self):
3576         return self.operand2.type.is_int
3577         
3578     def coerce_chars_to_ints(self, env):
3579         if self.operand2.type.is_string:
3580             self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3581
3582     def coerce_cascaded_operands_to_temp(self, env):
3583         if self.cascade:
3584             #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
3585             self.operand2 = self.operand2.coerce_to_simple(env)
3586             self.cascade.coerce_cascaded_operands_to_temp(env)
3587     
3588     def allocate_subexpr_temps(self, env):
3589         self.operand2.allocate_temps(env)
3590         if self.cascade:
3591             self.cascade.allocate_subexpr_temps(env)
3592     
3593     def release_subexpr_temps(self, env):
3594         self.operand2.release_temp(env)
3595         if self.cascade:
3596             self.cascade.release_subexpr_temps(env)
3597     
3598     def generate_evaluation_code(self, code, result, operand1):
3599         if self.type.is_pyobject:
3600             code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
3601         else:
3602             code.putln("if (%s) {" % result)
3603         self.operand2.generate_evaluation_code(code)
3604         self.generate_operation_code(code, result, 
3605             operand1, self.operator, self.operand2)
3606         if self.cascade:
3607             self.cascade.generate_evaluation_code(
3608                 code, result, self.operand2)
3609         # Cascaded cmp result is always temp
3610         self.operand2.generate_disposal_code(code)
3611         code.putln("}")
3612
3613     def annotate(self, code):
3614         self.operand2.annotate(code)
3615         if self.cascade:
3616             self.cascade.annotate(code)
3617
3618
3619 binop_node_classes = {
3620     "or":               BoolBinopNode,
3621     "and":      BoolBinopNode,
3622     "|":                IntBinopNode,
3623     "^":                IntBinopNode,
3624     "&":                IntBinopNode,
3625     "<<":               IntBinopNode,
3626     ">>":               IntBinopNode,
3627     "+":                AddNode,
3628     "-":                SubNode,
3629     "*":                MulNode,
3630     "/":                NumBinopNode,
3631     "//":               FloorDivNode,
3632     "%":                ModNode,
3633     "**":               PowNode
3634 }
3635
3636 def binop_node(pos, operator, operand1, operand2):
3637     # Construct binop node of appropriate class for 
3638     # given operator.
3639     return binop_node_classes[operator](pos, 
3640         operator = operator, 
3641         operand1 = operand1, 
3642         operand2 = operand2)
3643
3644 #-------------------------------------------------------------------
3645 #
3646 #  Coercion nodes
3647 #
3648 #  Coercion nodes are special in that they are created during
3649 #  the analyse_types phase of parse tree processing.
3650 #  Their __init__ methods consequently incorporate some aspects
3651 #  of that phase.
3652 #
3653 #-------------------------------------------------------------------
3654
3655 class CoercionNode(ExprNode):
3656     #  Abstract base class for coercion nodes.
3657     #
3658     #  arg       ExprNode       node being coerced
3659     
3660     subexprs = ['arg']
3661     
3662     def __init__(self, arg):
3663         self.pos = arg.pos
3664         self.arg = arg
3665         if debug_coercion:
3666             print("%s Coercing %s" % (self, self.arg))
3667             
3668     def annotate(self, code):
3669         self.arg.annotate(code)
3670         if self.arg.type != self.type:
3671             file, line, col = self.pos
3672             code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
3673
3674
3675 class CastNode(CoercionNode):
3676     #  Wrap a node in a C type cast.
3677     
3678     def __init__(self, arg, new_type):
3679         CoercionNode.__init__(self, arg)
3680         self.type = new_type
3681     
3682     def calculate_result_code(self):
3683         return self.arg.result_as(self.type)
3684
3685     def generate_result_code(self, code):
3686         self.arg.generate_result_code(code)
3687
3688
3689 class PyTypeTestNode(CoercionNode):
3690     #  This node is used to check that a generic Python
3691     #  object is an instance of a particular extension type.
3692     #  This node borrows the result of its argument node.
3693
3694     def __init__(self, arg, dst_type, env):
3695         #  The arg is know to be a Python object, and
3696         #  the dst_type is known to be an extension type.
3697         assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
3698         CoercionNode.__init__(self, arg)
3699         self.type = dst_type
3700         self.result_ctype = arg.ctype()
3701         env.use_utility_code(type_test_utility_code)
3702     
3703     def analyse_types(self, env):
3704         pass
3705     
3706     def result_in_temp(self):
3707         return self.arg.result_in_temp()
3708     
3709     def is_ephemeral(self):
3710         return self.arg.is_ephemeral()
3711     
3712     def calculate_result_code(self):
3713         return self.arg.result_code
3714     
3715     def generate_result_code(self, code):
3716         if self.type.typeobj_is_available():
3717             code.putln(
3718                 "if (!(%s)) %s" % (
3719                     self.type.type_test_code(self.arg.py_result()),
3720                     code.error_goto(self.pos)))
3721         else:
3722             error(self.pos, "Cannot test type of extern C class "
3723                 "without type object name specification")
3724                 
3725     def generate_post_assignment_code(self, code):
3726         self.arg.generate_post_assignment_code(code)
3727                 
3728                 
3729 class CoerceToPyTypeNode(CoercionNode):
3730     #  This node is used to convert a C data type
3731     #  to a Python object.
3732
3733     def __init__(self, arg, env):
3734         CoercionNode.__init__(self, arg)
3735         self.type = py_object_type
3736         self.is_temp = 1
3737         if not arg.type.to_py_function:
3738             error(arg.pos,
3739                 "Cannot convert '%s' to Python object" % arg.type)
3740     
3741     def generate_result_code(self, code):
3742         function = self.arg.type.to_py_function
3743         code.putln('%s = %s(%s); %s' % (
3744             self.result_code, 
3745             function, 
3746             self.arg.result_code, 
3747             code.error_goto_if_null(self.result_code, self.pos)))
3748
3749
3750 class CoerceFromPyTypeNode(CoercionNode):
3751     #  This node is used to convert a Python object
3752     #  to a C data type.
3753
3754     def __init__(self, result_type, arg, env):
3755         CoercionNode.__init__(self, arg)
3756         self.type = result_type
3757         self.is_temp = 1
3758         if not result_type.from_py_function:
3759             error(arg.pos,
3760                 "Cannot convert Python object to '%s'" % result_type)
3761         if self.type.is_string and self.arg.is_ephemeral():
3762             error(arg.pos,
3763                 "Obtaining char * from temporary Python value")
3764     
3765     def generate_result_code(self, code):
3766         function = self.type.from_py_function
3767         operand = self.arg.py_result()
3768         rhs = "%s(%s)" % (function, operand)
3769         if self.type.is_enum:
3770             rhs = typecast(self.type, c_long_type, rhs)
3771         code.putln('%s = %s; %s' % (
3772             self.result_code, 
3773             rhs,
3774             code.error_goto_if(self.type.error_condition(self.result_code), self.pos)))
3775
3776
3777 class CoerceToBooleanNode(CoercionNode):
3778     #  This node is used when a result needs to be used
3779     #  in a boolean context.
3780     
3781     def __init__(self, arg, env):
3782         CoercionNode.__init__(self, arg)
3783         self.type = PyrexTypes.c_bint_type
3784         if arg.type.is_pyobject:
3785             self.is_temp = 1
3786     
3787     def check_const(self):
3788         if self.is_temp:
3789             self.not_const()
3790         self.arg.check_const()
3791     
3792     def calculate_result_code(self):
3793         return "(%s != 0)" % self.arg.result_code
3794
3795     def generate_result_code(self, code):
3796         if self.arg.type.is_pyobject:
3797             code.putln(
3798                 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3799                     self.result_code, 
3800                     self.arg.py_result(), 
3801                     code.error_goto_if_neg(self.result_code, self.pos)))
3802
3803
3804 class CoerceToTempNode(CoercionNode):
3805     #  This node is used to force the result of another node
3806     #  to be stored in a temporary. It is only used if the
3807     #  argument node's result is not already in a temporary.
3808
3809     def __init__(self, arg, env):
3810         CoercionNode.__init__(self, arg)
3811         self.type = self.arg.type
3812         self.is_temp = 1
3813         if self.type.is_pyobject:
3814             self.result_ctype = py_object_type
3815     
3816     def generate_result_code(self, code):
3817         #self.arg.generate_evaluation_code(code) # Already done
3818         # by generic generate_subexpr_evaluation_code!
3819         code.putln("%s = %s;" % (
3820             self.result_code, self.arg.result_as(self.ctype())))
3821         if self.type.is_pyobject:
3822             code.put_incref(self.result_code, self.ctype())
3823
3824
3825 class CloneNode(CoercionNode):
3826     #  This node is employed when the result of another node needs
3827     #  to be used multiple times. The argument node's result must
3828     #  be in a temporary. This node "borrows" the result from the
3829     #  argument node, and does not generate any evaluation or
3830     #  disposal code for it. The original owner of the argument 
3831     #  node is responsible for doing those things.
3832     
3833     subexprs = [] # Arg is not considered a subexpr
3834     
3835     def __init__(self, arg):
3836         CoercionNode.__init__(self, arg)
3837         if hasattr(arg, 'type'):
3838             self.type = arg.type
3839             self.result_ctype = arg.result_ctype
3840         if hasattr(arg, 'entry'):
3841             self.entry = arg.entry
3842     
3843     def calculate_result_code(self):
3844         return self.arg.result_code
3845         
3846     def analyse_types(self, env):
3847         self.type = self.arg.type
3848         self.result_ctype = self.arg.result_ctype
3849         self.is_temp = 1
3850         if hasattr(self.arg, 'entry'):
3851             self.entry = self.arg.entry
3852     
3853     #def result_as_extension_type(self):
3854     #   return self.arg.result_as_extension_type()
3855     
3856     def generate_evaluation_code(self, code):
3857         pass
3858
3859     def generate_result_code(self, code):
3860         pass
3861         
3862     def generate_disposal_code(self, code):
3863         pass
3864                 
3865     def allocate_temps(self, env):
3866         self.result_code = self.calculate_result_code()
3867         
3868     def release_temp(self, env):
3869         pass
3870     
3871 #------------------------------------------------------------------------------------
3872 #
3873 #  Runtime support code
3874 #
3875 #------------------------------------------------------------------------------------
3876
3877 get_name_interned_utility_code = [
3878 """
3879 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
3880 ""","""
3881 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
3882     PyObject *result;
3883     result = PyObject_GetAttr(dict, name);
3884     if (!result)
3885         PyErr_SetObject(PyExc_NameError, name);
3886     return result;
3887 }
3888 """]
3889
3890 #------------------------------------------------------------------------------------
3891
3892 import_utility_code = [
3893 """
3894 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
3895 ""","""
3896 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
3897     PyObject *__import__ = 0;
3898     PyObject *empty_list = 0;
3899     PyObject *module = 0;
3900     PyObject *global_dict = 0;
3901     PyObject *empty_dict = 0;
3902     PyObject *list;
3903     __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
3904     if (!__import__)
3905         goto bad;
3906     if (from_list)
3907         list = from_list;
3908     else {
3909         empty_list = PyList_New(0);
3910         if (!empty_list)
3911             goto bad;
3912         list = empty_list;
3913     }
3914     global_dict = PyModule_GetDict(%(GLOBALS)s);
3915     if (!global_dict)
3916         goto bad;
3917     empty_dict = PyDict_New();
3918     if (!empty_dict)
3919         goto bad;
3920     module = PyObject_CallFunction(__import__, "OOOO",
3921         name, global_dict, empty_dict, list);
3922 bad:
3923     Py_XDECREF(empty_list);
3924     Py_XDECREF(__import__);
3925     Py_XDECREF(empty_dict);
3926     return module;
3927 }
3928 """ % {
3929     "BUILTINS": Naming.builtins_cname,
3930     "GLOBALS":  Naming.module_cname,
3931 }]
3932
3933 #------------------------------------------------------------------------------------
3934
3935 get_exception_utility_code = [
3936 """
3937 static PyObject *__Pyx_GetExcValue(void); /*proto*/
3938 ""","""
3939 static PyObject *__Pyx_GetExcValue(void) {
3940     PyObject *type = 0, *value = 0, *tb = 0;
3941     PyObject *tmp_type, *tmp_value, *tmp_tb;
3942     PyObject *result = 0;
3943     PyThreadState *tstate = PyThreadState_Get();
3944     PyErr_Fetch(&type, &value, &tb);
3945     PyErr_NormalizeException(&type, &value, &tb);
3946     if (PyErr_Occurred())
3947         goto bad;
3948     if (!value) {
3949         value = Py_None;
3950         Py_INCREF(value);
3951     }
3952     tmp_type = tstate->exc_type;
3953     tmp_value = tstate->exc_value;
3954     tmp_tb = tstate->exc_traceback;
3955     tstate->exc_type = type;
3956     tstate->exc_value = value;
3957     tstate->exc_traceback = tb;
3958     /* Make sure tstate is in a consistent state when we XDECREF
3959     these objects (XDECREF may run arbitrary code). */
3960     Py_XDECREF(tmp_type);
3961     Py_XDECREF(tmp_value);
3962     Py_XDECREF(tmp_tb);
3963     result = value;
3964     Py_XINCREF(result);
3965     type = 0;
3966     value = 0;
3967     tb = 0;
3968 bad:
3969     Py_XDECREF(type);
3970     Py_XDECREF(value);
3971     Py_XDECREF(tb);
3972     return result;
3973 }
3974 """]
3975
3976 #------------------------------------------------------------------------------------
3977
3978 unpacking_utility_code = [
3979 """
3980 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
3981 static int __Pyx_EndUnpack(PyObject *); /*proto*/
3982 ""","""
3983 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
3984     PyObject *item;
3985     if (!(item = PyIter_Next(iter))) {
3986         if (!PyErr_Occurred()) {
3987             PyErr_Format(PyExc_ValueError,
3988                 #if PY_VERSION_HEX < 0x02050000
3989                     "need more than %d values to unpack", (int)index);
3990                 #else
3991                     "need more than %zd values to unpack", index);
3992                 #endif
3993         }
3994     }
3995     return item;
3996 }
3997
3998 static int __Pyx_EndUnpack(PyObject *iter) {
3999     PyObject *item;
4000     if ((item = PyIter_Next(iter))) {
4001         Py_DECREF(item);
4002         PyErr_SetString(PyExc_ValueError, "too many values to unpack");
4003         return -1;
4004     }
4005     else if (!PyErr_Occurred())
4006         return 0;
4007     else
4008         return -1;
4009 }
4010 """]
4011
4012 #------------------------------------------------------------------------------------
4013
4014 type_test_utility_code = [
4015 """
4016 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
4017 ""","""
4018 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
4019     if (!type) {
4020         PyErr_Format(PyExc_SystemError, "Missing type object");
4021         return 0;
4022     }
4023     if (obj == Py_None || PyObject_TypeCheck(obj, type))
4024         return 1;
4025     PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
4026         Py_TYPE(obj)->tp_name, type->tp_name);
4027     return 0;
4028 }
4029 """]
4030
4031 #------------------------------------------------------------------------------------
4032
4033 create_class_utility_code = [
4034 """
4035 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
4036 ""","""
4037 static PyObject *__Pyx_CreateClass(
4038     PyObject *bases, PyObject *dict, PyObject *name, char *modname)
4039 {
4040     PyObject *py_modname;
4041     PyObject *result = 0;
4042
4043     #if PY_MAJOR_VERSION < 3
4044     py_modname = PyString_FromString(modname);
4045     #else
4046     py_modname = PyUnicode_FromString(modname);
4047     #endif
4048     if (!py_modname)
4049         goto bad;
4050     if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
4051         goto bad;
4052     #if PY_MAJOR_VERSION < 3
4053     result = PyClass_New(bases, dict, name);
4054     #else
4055     result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
4056     #endif
4057 bad:
4058     Py_XDECREF(py_modname);
4059     return result;
4060 }
4061 """]
4062
4063 #------------------------------------------------------------------------------------
4064
4065 cpp_exception_utility_code = [
4066 """
4067 #ifndef __Pyx_CppExn2PyErr
4068 static void __Pyx_CppExn2PyErr() {
4069   try {
4070     if (PyErr_Occurred())
4071       ; // let the latest Python exn pass through and ignore the current one
4072     else
4073       throw;
4074   } catch (const std::out_of_range& exn) {
4075     // catch out_of_range explicitly so the proper Python exn may be raised
4076     PyErr_SetString(PyExc_IndexError, exn.what());
4077   } catch (const std::exception& exn) {
4078     PyErr_SetString(PyExc_RuntimeError, exn.what());
4079   }
4080   catch (...)
4081   {
4082     PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
4083   }
4084 }
4085 #endif
4086 """,""]
4087
4088 #------------------------------------------------------------------------------------
4089
4090 append_utility_code = [
4091 """
4092 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
4093     if (likely(PyList_CheckExact(L))) {
4094         if (PyList_Append(L, x) < 0) return NULL;
4095         Py_INCREF(Py_None);
4096         return Py_None; // this is just to have an accurate signature
4097     }
4098     else {
4099         return PyObject_CallMethod(L, "append", "(O)", x);
4100     }
4101 }
4102 """,""
4103 ]
4104
4105 #------------------------------------------------------------------------------------
4106
4107 type_cache_invalidation_code = [
4108 """
4109 #if PY_VERSION_HEX >= 0x02060000
4110 static void __Pyx_TypeModified(PyTypeObject* type); /*proto*/
4111 #else
4112   #define __Pyx_TypeModified(t)
4113 #endif
4114 ""","""
4115 #if PY_VERSION_HEX >= 0x02060000
4116 /* copied from typeobject.c in Python 3.0a5 */
4117 static void __Pyx_TypeModified(PyTypeObject* type) {
4118     PyObject *raw, *ref;
4119     Py_ssize_t i, n;
4120
4121     if (!PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))
4122         return;
4123
4124     raw = type->tp_subclasses;
4125     if (raw != NULL) {
4126         n = PyList_GET_SIZE(raw);
4127         for (i = 0; i < n; i++) {
4128             ref = PyList_GET_ITEM(raw, i);
4129             ref = PyWeakref_GET_OBJECT(ref);
4130             if (ref != Py_None) {
4131                 __Pyx_TypeModified((PyTypeObject *)ref);
4132             }
4133         }
4134     }
4135     type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
4136 }
4137 #endif
4138 """
4139 ]