6372ea777da1f8e0ab2c7b4ca343cddb9d26a04a
[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     
851     def analyse_types(self, env):
852         self.entry = env.lookup(self.name)
853         if not self.entry:
854             self.entry = env.declare_builtin(self.name, self.pos)
855         if not self.entry:
856             self.type = PyrexTypes.error_type
857             return
858         self.analyse_rvalue_entry(env)
859         
860     def analyse_target_types(self, env):
861         self.analyse_entry(env)
862         if not self.is_lvalue():
863             error(self.pos, "Assignment to non-lvalue '%s'"
864                 % self.name)
865             self.type = PyrexTypes.error_type
866         self.entry.used = 1
867         
868     def analyse_rvalue_entry(self, env):
869         #print "NameNode.analyse_rvalue_entry:", self.name ###
870         #print "Entry:", self.entry.__dict__ ###
871         self.analyse_entry(env)
872         entry = self.entry
873         if entry.is_declared_generic:
874             self.result_ctype = py_object_type
875         if entry.is_pyglobal or entry.is_builtin:
876             if Options.cache_builtins and entry.is_builtin:
877                 self.is_temp = 0
878             else:
879                 self.is_temp = 1
880             env.use_utility_code(get_name_interned_utility_code)
881     
882     def analyse_entry(self, env):
883         #print "NameNode.analyse_entry:", self.name ###
884         self.check_identifier_kind()
885         entry = self.entry
886         type = entry.type
887         self.type = type
888         if entry.is_pyglobal or entry.is_builtin:
889             assert type.is_pyobject, "Python global or builtin not a Python object"
890             self.interned_cname = self.entry.interned_cname = \
891                 env.intern_identifier(self.entry.name)
892
893     def check_identifier_kind(self):
894         #print "NameNode.check_identifier_kind:", self.entry.name ###
895         #print self.entry.__dict__ ###
896         entry = self.entry
897         #entry.used = 1
898         if not (entry.is_const or entry.is_variable 
899             or entry.is_builtin or entry.is_cfunction):
900                 if self.entry.as_variable:
901                     self.entry = self.entry.as_variable
902                 else:
903                     error(self.pos, 
904                         "'%s' is not a constant, variable or function identifier" % self.name)
905     
906     def is_simple(self):
907         #  If it's not a C variable, it'll be in a temp.
908         return 1
909     
910     def calculate_target_results(self, env):
911         pass
912     
913     def check_const(self):
914         entry = self.entry
915         if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
916             self.not_const()
917     
918     def check_const_addr(self):
919         entry = self.entry
920         if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
921             self.addr_not_const()
922
923     def is_lvalue(self):
924         return self.entry.is_variable and \
925             not self.entry.type.is_array and \
926             not self.entry.is_readonly
927     
928     def is_ephemeral(self):
929         #  Name nodes are never ephemeral, even if the
930         #  result is in a temporary.
931         return 0
932     
933     def allocate_temp(self, env, result = None):
934         AtomicExprNode.allocate_temp(self, env, result)
935         entry = self.entry
936         if entry:
937             entry.used = 1
938             if entry.utility_code:
939                 env.use_utility_code(entry.utility_code)
940         
941     def calculate_result_code(self):
942         entry = self.entry
943         if not entry:
944             return "<error>" # There was an error earlier
945         return entry.cname
946     
947     def generate_result_code(self, code):
948         assert hasattr(self, 'entry')
949         entry = self.entry
950         if entry is None:
951             return # There was an error earlier
952         if entry.is_builtin and Options.cache_builtins:
953             return # Lookup already cached
954         elif entry.is_pyglobal or entry.is_builtin:
955             if entry.is_builtin:
956                 namespace = Naming.builtins_cname
957             else: # entry.is_pyglobal
958                 namespace = entry.namespace_cname
959             code.putln(
960                 '%s = __Pyx_GetName(%s, %s); %s' % (
961                 self.result_code,
962                 namespace, 
963                 self.interned_cname,
964                 code.error_goto_if_null(self.result_code, self.pos)))           
965         elif entry.is_local and False:
966             # control flow not good enough yet
967             assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
968             if assigned is False:
969                 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
970             elif not Options.init_local_none and assigned is None:
971                 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
972                 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
973
974     def generate_assignment_code(self, rhs, code):
975         #print "NameNode.generate_assignment_code:", self.name ###
976         entry = self.entry
977         if entry is None:
978             return # There was an error earlier
979
980         # is_pyglobal seems to be True for module level-globals only.
981         # We use this to access class->tp_dict if necessary.
982         if entry.is_pyglobal:
983             namespace = self.entry.namespace_cname
984             if entry.is_member:
985                 # if the entry is a member we have to cheat: SetAttr does not work
986                 # on types, so we create a descriptor which is then added to tp_dict
987                 code.put_error_if_neg(self.pos,
988                     'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
989                         namespace,
990                         self.interned_cname,
991                         rhs.py_result()))
992                 # in Py2.6+, we need to invalidate the method cache
993                 typeptr_cname = entry.scope.parent_type.typeptr_cname
994                 code.putln("#if PY_VERSION_HEX >= 0x02060000")
995                 code.putln("(%s)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;" %
996                            typeptr_cname)
997                 code.putln("#endif")
998             else: 
999                 code.put_error_if_neg(self.pos,
1000                     'PyObject_SetAttr(%s, %s, %s)' % (
1001                         namespace,
1002                         self.interned_cname,
1003                         rhs.py_result()))
1004                 if debug_disposal_code:
1005                     print("NameNode.generate_assignment_code:")
1006                     print("...generating disposal code for %s" % rhs)
1007                 rhs.generate_disposal_code(code)
1008                 
1009         else:
1010             if self.type.is_pyobject:
1011                 #print "NameNode.generate_assignment_code: to", self.name ###
1012                 #print "...from", rhs ###
1013                 #print "...LHS type", self.type, "ctype", self.ctype() ###
1014                 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1015                 rhs.make_owned_reference(code)
1016                 if entry.is_local and not Options.init_local_none:
1017                     initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1018                     if initalized is True:
1019                         code.put_decref(self.result_code, self.ctype())
1020                     elif initalized is None:
1021                         code.put_xdecref(self.result_code, self.ctype())
1022                 else:
1023                     code.put_decref(self.result_code, self.ctype())
1024             code.putln('%s = %s;' % (self.result_code, rhs.result_as(self.ctype())))
1025             if debug_disposal_code:
1026                 print("NameNode.generate_assignment_code:")
1027                 print("...generating post-assignment code for %s" % rhs)
1028             rhs.generate_post_assignment_code(code)
1029     
1030     def generate_deletion_code(self, code):
1031         if self.entry is None:
1032             return # There was an error earlier
1033         if not self.entry.is_pyglobal:
1034             error(self.pos, "Deletion of local or C global name not supported")
1035             return
1036         code.put_error_if_neg(self.pos, 
1037             'PyObject_DelAttrString(%s, "%s")' % (
1038                 Naming.module_cname,
1039                 self.entry.name))
1040                 
1041     def annotate(self, code):
1042         if hasattr(self, 'is_called') and self.is_called:
1043             pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1044             if self.type.is_pyobject:
1045                 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1046             else:
1047                 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1048             
1049
1050 class BackquoteNode(ExprNode):
1051     #  `expr`
1052     #
1053     #  arg    ExprNode
1054     
1055     subexprs = ['arg']
1056     
1057     def analyse_types(self, env):
1058         self.arg.analyse_types(env)
1059         self.arg = self.arg.coerce_to_pyobject(env)
1060         self.type = py_object_type
1061         self.is_temp = 1
1062     
1063     def generate_result_code(self, code):
1064         code.putln(
1065             "%s = PyObject_Repr(%s); %s" % (
1066                 self.result_code,
1067                 self.arg.py_result(),
1068                 code.error_goto_if_null(self.result_code, self.pos)))
1069
1070
1071 class ImportNode(ExprNode):
1072     #  Used as part of import statement implementation.
1073     #  Implements result = 
1074     #    __import__(module_name, globals(), None, name_list)
1075     #
1076     #  module_name   IdentifierStringNode     dotted name of module
1077     #  name_list     ListNode or None         list of names to be imported
1078     
1079     subexprs = ['module_name', 'name_list']
1080
1081     def analyse_types(self, env):
1082         self.module_name.analyse_types(env)
1083         self.module_name = self.module_name.coerce_to_pyobject(env)
1084         if self.name_list:
1085             self.name_list.analyse_types(env)
1086         self.type = py_object_type
1087         self.is_temp = 1
1088         env.use_utility_code(import_utility_code)
1089     
1090     def generate_result_code(self, code):
1091         if self.name_list:
1092             name_list_code = self.name_list.py_result()
1093         else:
1094             name_list_code = "0"
1095         code.putln(
1096             "%s = __Pyx_Import(%s, %s); %s" % (
1097                 self.result_code,
1098                 self.module_name.py_result(),
1099                 name_list_code,
1100                 code.error_goto_if_null(self.result_code, self.pos)))
1101
1102
1103 class IteratorNode(ExprNode):
1104     #  Used as part of for statement implementation.
1105     #  Implements result = iter(sequence)
1106     #
1107     #  sequence   ExprNode
1108     
1109     subexprs = ['sequence']
1110     
1111     def analyse_types(self, env):
1112         self.sequence.analyse_types(env)
1113         self.sequence = self.sequence.coerce_to_pyobject(env)
1114         self.type = py_object_type
1115         self.is_temp = 1
1116         
1117         self.counter = TempNode(self.pos, PyrexTypes.c_py_ssize_t_type, env)
1118         self.counter.allocate_temp(env)
1119         
1120     def release_temp(self, env):
1121         env.release_temp(self.result_code)
1122         self.counter.release_temp(env)
1123     
1124     def generate_result_code(self, code):
1125         code.putln(
1126             "if (PyList_CheckExact(%s)) { %s = 0; %s = %s; Py_INCREF(%s); }" % (
1127                 self.sequence.py_result(),
1128                 self.counter.result_code,
1129                 self.result_code,
1130                 self.sequence.py_result(),
1131                 self.result_code))
1132         code.putln("else { %s = PyObject_GetIter(%s); %s }" % (
1133                 self.result_code,
1134                 self.sequence.py_result(),
1135                 code.error_goto_if_null(self.result_code, self.pos)))
1136
1137
1138 class NextNode(AtomicExprNode):
1139     #  Used as part of for statement implementation.
1140     #  Implements result = iterator.next()
1141     #  Created during analyse_types phase.
1142     #  The iterator is not owned by this node.
1143     #
1144     #  iterator   ExprNode
1145     
1146     def __init__(self, iterator, env):
1147         self.pos = iterator.pos
1148         self.iterator = iterator
1149         self.type = py_object_type
1150         self.is_temp = 1
1151     
1152     def generate_result_code(self, code):
1153         code.putln(
1154             "if (PyList_CheckExact(%s)) { if (%s >= PyList_GET_SIZE(%s)) break; %s = PyList_GET_ITEM(%s, %s++); Py_INCREF(%s); }" % (
1155                 self.iterator.py_result(),
1156                 self.iterator.counter.result_code,
1157                 self.iterator.py_result(),
1158                 self.result_code,
1159                 self.iterator.py_result(),
1160                 self.iterator.counter.result_code,
1161                 self.result_code))
1162         code.putln("else {")
1163         code.putln(
1164             "%s = PyIter_Next(%s);" % (
1165                 self.result_code,
1166                 self.iterator.py_result()))
1167         code.putln(
1168             "if (!%s) {" %
1169                 self.result_code)
1170         code.error_goto_if_PyErr(self.pos)
1171         code.putln("break;")
1172         code.putln("}")
1173         code.putln("}")
1174
1175
1176 class ExcValueNode(AtomicExprNode):
1177     #  Node created during analyse_types phase
1178     #  of an ExceptClauseNode to fetch the current
1179     #  exception value.
1180     
1181     def __init__(self, pos, env, var):
1182         ExprNode.__init__(self, pos)
1183         self.type = py_object_type
1184         self.var = var
1185     
1186     def calculate_result_code(self):
1187         return self.var
1188
1189     def generate_result_code(self, code):
1190         pass
1191
1192
1193 class TempNode(AtomicExprNode):
1194     #  Node created during analyse_types phase
1195     #  of some nodes to hold a temporary value.
1196     
1197     def __init__(self, pos, type, env):
1198         ExprNode.__init__(self, pos)
1199         self.type = type
1200         if type.is_pyobject:
1201             self.result_ctype = py_object_type
1202         self.is_temp = 1
1203         
1204     def analyse_types(self, env):
1205         return self.type
1206     
1207     def generate_result_code(self, code):
1208         pass
1209
1210
1211 class PyTempNode(TempNode):
1212     #  TempNode holding a Python value.
1213     
1214     def __init__(self, pos, env):
1215         TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1216
1217
1218 #-------------------------------------------------------------------
1219 #
1220 #  Trailer nodes
1221 #
1222 #-------------------------------------------------------------------
1223
1224 class IndexNode(ExprNode):
1225     #  Sequence indexing.
1226     #
1227     #  base     ExprNode
1228     #  index    ExprNode
1229     
1230     subexprs = ['base', 'index', 'py_index']
1231     
1232     def compile_time_value(self, denv):
1233         base = self.base.compile_time_value(denv)
1234         index = self.index.compile_time_value(denv)
1235         try:
1236             return base[index]
1237         except Exception, e:
1238             self.compile_time_value_error(e)
1239     
1240     def is_ephemeral(self):
1241         return self.base.is_ephemeral()
1242     
1243     def analyse_target_declaration(self, env):
1244         pass
1245     
1246     def analyse_types(self, env):
1247         self.base.analyse_types(env)
1248         self.index.analyse_types(env)
1249         if self.base.type.is_pyobject:
1250             if self.index.type.is_int:
1251                 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1252                 self.py_index = CloneNode(self.index).coerce_to_pyobject(env)
1253             else:
1254                 self.index = self.index.coerce_to_pyobject(env)
1255                 self.py_index = CloneNode(self.index)
1256             self.type = py_object_type
1257             self.is_temp = 1
1258         else:
1259             self.py_index = CloneNode(self.index) # so that it exists for subexpr processing
1260             if self.base.type.is_ptr or self.base.type.is_array:
1261                 self.type = self.base.type.base_type
1262             else:
1263                 error(self.pos,
1264                     "Attempting to index non-array type '%s'" %
1265                         self.base.type)
1266                 self.type = PyrexTypes.error_type
1267             if self.index.type.is_pyobject:
1268                 self.index = self.index.coerce_to(
1269                     PyrexTypes.c_py_ssize_t_type, env)
1270             if not self.index.type.is_int:
1271                 error(self.pos,
1272                     "Invalid index type '%s'" %
1273                         self.index.type)
1274     
1275     def check_const_addr(self):
1276         self.base.check_const_addr()
1277         self.index.check_const()
1278     
1279     def is_lvalue(self):
1280         return 1
1281     
1282     def calculate_result_code(self):
1283         return "(%s[%s])" % (
1284             self.base.result_code, self.index.result_code)
1285
1286     def generate_subexpr_evaluation_code(self, code):
1287         # do not evaluate self.py_index in case we don't need it
1288         self.base.generate_evaluation_code(code)
1289         self.index.generate_evaluation_code(code)
1290         
1291     def generate_subexpr_disposal_code(self, code):
1292         # if we used self.py_index, it will be disposed of manually
1293         self.base.generate_disposal_code(code)
1294         self.index.generate_disposal_code(code)
1295
1296     def generate_result_code(self, code):
1297         if self.type.is_pyobject:
1298             if self.index.type.is_int:
1299                 code.putln("if (PyList_CheckExact(%s) && 0 <= %s && %s < PyList_GET_SIZE(%s)) {" % (
1300                         self.base.py_result(),
1301                         self.index.result_code,
1302                         self.index.result_code,
1303                         self.base.py_result()))
1304                 code.putln("%s = PyList_GET_ITEM(%s, %s); Py_INCREF(%s);" % (
1305                         self.result_code,
1306                         self.base.py_result(),
1307                         self.index.result_code,
1308                         self.result_code))
1309                 code.putln("} else if (PyTuple_CheckExact(%s) && 0 <= %s && %s < PyTuple_GET_SIZE(%s)) {" % (
1310                         self.base.py_result(),
1311                         self.index.result_code,
1312                         self.index.result_code,
1313                         self.base.py_result()))
1314                 code.putln("%s = PyTuple_GET_ITEM(%s, %s); Py_INCREF(%s);" % (
1315                         self.result_code,
1316                         self.base.py_result(),
1317                         self.index.result_code,
1318                         self.result_code))
1319                 code.putln("} else {")
1320                 self.generate_generic_code_result(code)
1321                 code.putln("}")
1322             else:
1323                 self.generate_generic_code_result(code)
1324
1325     def generate_generic_code_result(self, code):
1326         self.py_index.generate_result_code(code)
1327         code.putln(
1328             "%s = PyObject_GetItem(%s, %s); %s" % (
1329                 self.result_code,
1330                 self.base.py_result(),
1331                 self.py_index.py_result(),
1332                 code.error_goto_if_null(self.result_code, self.pos)))
1333         if self.is_temp:
1334             self.py_index.generate_disposal_code(code)
1335
1336     def generate_assignment_code(self, rhs, code):
1337         self.generate_subexpr_evaluation_code(code)
1338         if self.type.is_pyobject:
1339             if self.index.type.is_int:
1340                 code.putln("if (PyList_CheckExact(%s) && 0 <= %s && %s < PyList_GET_SIZE(%s)) {" % (
1341                         self.base.py_result(),
1342                         self.index.result_code,
1343                         self.index.result_code,
1344                         self.base.py_result()))
1345                 code.putln("Py_DECREF(PyList_GET_ITEM(%s, %s)); Py_INCREF(%s);" % (
1346                         self.base.py_result(),
1347                         self.index.result_code,
1348                         rhs.py_result()))
1349                 code.putln("PyList_SET_ITEM(%s, %s, %s);" % (
1350                         self.base.py_result(),
1351                         self.index.result_code,
1352                         rhs.py_result()))
1353                 code.putln("} else {")
1354                 self.generate_generic_assignment_code(rhs, code)
1355                 code.putln("}")
1356             else:
1357                 self.generate_generic_assignment_code(rhs, code)
1358         else:
1359             code.putln(
1360                 "%s = %s;" % (
1361                     self.result_code, rhs.result_code))
1362         self.generate_subexpr_disposal_code(code)
1363         rhs.generate_disposal_code(code)
1364     
1365     def generate_generic_assignment_code(self, rhs, code):
1366         self.py_index.generate_result_code(code)
1367         code.put_error_if_neg(self.pos, 
1368             "PyObject_SetItem(%s, %s, %s)" % (
1369                 self.base.py_result(),
1370                 self.py_index.py_result(),
1371                 rhs.py_result()))
1372         if self.is_temp:
1373             self.py_index.generate_disposal_code(code)
1374     
1375     def generate_deletion_code(self, code):
1376         self.generate_subexpr_evaluation_code(code)
1377         self.py_index.generate_evaluation_code(code)
1378         code.put_error_if_neg(self.pos, 
1379             "PyObject_DelItem(%s, %s)" % (
1380                 self.base.py_result(),
1381                 self.py_index.py_result()))
1382         self.generate_subexpr_disposal_code(code)
1383         self.py_index.generate_disposal_code(code)
1384
1385
1386 class SliceIndexNode(ExprNode):
1387     #  2-element slice indexing
1388     #
1389     #  base      ExprNode
1390     #  start     ExprNode or None
1391     #  stop      ExprNode or None
1392     
1393     subexprs = ['base', 'start', 'stop']
1394     
1395     def compile_time_value(self, denv):
1396         base = self.base.compile_time_value(denv)
1397         start = self.start.compile_time_value(denv)
1398         stop = self.stop.compile_time_value(denv)
1399         try:
1400             return base[start:stop]
1401         except Exception, e:
1402             self.compile_time_value_error(e)
1403     
1404     def analyse_target_declaration(self, env):
1405         pass
1406
1407     def analyse_types(self, env):
1408         self.base.analyse_types(env)
1409         if self.start:
1410             self.start.analyse_types(env)
1411         if self.stop:
1412             self.stop.analyse_types(env)
1413         self.base = self.base.coerce_to_pyobject(env)
1414         c_int = PyrexTypes.c_py_ssize_t_type
1415         if self.start:
1416             self.start = self.start.coerce_to(c_int, env)
1417         if self.stop:
1418             self.stop = self.stop.coerce_to(c_int, env)
1419         self.type = py_object_type
1420         self.is_temp = 1
1421     
1422     def generate_result_code(self, code):
1423         code.putln(
1424             "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1425                 self.result_code,
1426                 self.base.py_result(),
1427                 self.start_code(),
1428                 self.stop_code(),
1429                 code.error_goto_if_null(self.result_code, self.pos)))
1430     
1431     def generate_assignment_code(self, rhs, code):
1432         self.generate_subexpr_evaluation_code(code)
1433         code.put_error_if_neg(self.pos, 
1434             "PySequence_SetSlice(%s, %s, %s, %s)" % (
1435                 self.base.py_result(),
1436                 self.start_code(),
1437                 self.stop_code(),
1438                 rhs.result_code))
1439         self.generate_subexpr_disposal_code(code)
1440         rhs.generate_disposal_code(code)
1441
1442     def generate_deletion_code(self, code):
1443         self.generate_subexpr_evaluation_code(code)
1444         code.put_error_if_neg(self.pos,
1445             "PySequence_DelSlice(%s, %s, %s)" % (
1446                 self.base.py_result(),
1447                 self.start_code(),
1448                 self.stop_code()))
1449         self.generate_subexpr_disposal_code(code)
1450     
1451     def start_code(self):
1452         if self.start:
1453             return self.start.result_code
1454         else:
1455             return "0"
1456     
1457     def stop_code(self):
1458         if self.stop:
1459             return self.stop.result_code
1460         else:
1461             return "PY_SSIZE_T_MAX"
1462     
1463     def calculate_result_code(self):
1464         # self.result_code is not used, but this method must exist
1465         return "<unused>"
1466     
1467
1468 class SliceNode(ExprNode):
1469     #  start:stop:step in subscript list
1470     #
1471     #  start     ExprNode
1472     #  stop      ExprNode
1473     #  step      ExprNode
1474     
1475     def compile_time_value(self, denv):
1476         start = self.start.compile_time_value(denv)
1477         stop = self.stop.compile_time_value(denv)
1478         step = step.step.compile_time_value(denv)
1479         try:
1480             return slice(start, stop, step)
1481         except Exception, e:
1482             self.compile_time_value_error(e)
1483
1484     subexprs = ['start', 'stop', 'step']
1485     
1486     def analyse_types(self, env):
1487         self.start.analyse_types(env)
1488         self.stop.analyse_types(env)
1489         self.step.analyse_types(env)
1490         self.start = self.start.coerce_to_pyobject(env)
1491         self.stop = self.stop.coerce_to_pyobject(env)
1492         self.step = self.step.coerce_to_pyobject(env)
1493         self.type = py_object_type
1494         self.is_temp = 1
1495     
1496     def generate_result_code(self, code):
1497         code.putln(
1498             "%s = PySlice_New(%s, %s, %s); %s" % (
1499                 self.result_code,
1500                 self.start.py_result(), 
1501                 self.stop.py_result(), 
1502                 self.step.py_result(),
1503                 code.error_goto_if_null(self.result_code, self.pos)))
1504
1505 class SimpleCallNode(ExprNode):
1506     #  Function call without keyword, * or ** args.
1507     #
1508     #  function       ExprNode
1509     #  args           [ExprNode]
1510     #  arg_tuple      ExprNode or None     used internally
1511     #  self           ExprNode or None     used internally
1512     #  coerced_self   ExprNode or None     used internally
1513     #  wrapper_call   bool                 used internally
1514     
1515     subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
1516     
1517     self = None
1518     coerced_self = None
1519     arg_tuple = None
1520     wrapper_call = False
1521     
1522     def compile_time_value(self, denv):
1523         function = self.function.compile_time_value(denv)
1524         args = [arg.compile_time_value(denv) for arg in self.args]
1525         try:
1526             return function(*args)
1527         except Exception, e:
1528             self.compile_time_value_error(e)
1529
1530     def analyse_types(self, env):
1531         function = self.function
1532         function.is_called = 1
1533         self.function.analyse_types(env)
1534         if function.is_attribute and function.is_py_attr and \
1535            function.attribute == "append" and len(self.args) == 1:
1536             # L.append(x) is almost always applied to a list
1537             self.py_func = self.function
1538             self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
1539             self.function.analyse_types(env)
1540             self.self = self.py_func.obj
1541             function.obj = CloneNode(self.self)
1542             env.use_utility_code(append_utility_code)
1543         if function.is_attribute and function.entry and function.entry.is_cmethod:
1544             # Take ownership of the object from which the attribute
1545             # was obtained, because we need to pass it as 'self'.
1546             self.self = function.obj
1547             function.obj = CloneNode(self.self)
1548         func_type = self.function_type()
1549         if func_type.is_pyobject:
1550             self.arg_tuple = TupleNode(self.pos, args = self.args)
1551             self.arg_tuple.analyse_types(env)
1552             self.args = None
1553             self.type = py_object_type
1554             self.is_temp = 1
1555         else:
1556             for arg in self.args:
1557                 arg.analyse_types(env)
1558             if self.self and func_type.args:
1559                 # Coerce 'self' to the type expected by the method.
1560                 expected_type = func_type.args[0].type
1561                 self.coerced_self = CloneNode(self.self).coerce_to(
1562                     expected_type, env)
1563                 # Insert coerced 'self' argument into argument list.
1564                 self.args.insert(0, self.coerced_self)
1565             self.analyse_c_function_call(env)
1566     
1567     def function_type(self):
1568         # Return the type of the function being called, coercing a function
1569         # pointer to a function if necessary.
1570         func_type = self.function.type
1571         if func_type.is_ptr:
1572             func_type = func_type.base_type
1573         return func_type
1574     
1575     def analyse_c_function_call(self, env):
1576         func_type = self.function_type()
1577         # Check function type
1578         if not func_type.is_cfunction:
1579             if not func_type.is_error:
1580                 error(self.pos, "Calling non-function type '%s'" %
1581                     func_type)
1582             self.type = PyrexTypes.error_type
1583             self.result_code = "<error>"
1584             return
1585         # Check no. of args
1586         max_nargs = len(func_type.args)
1587         expected_nargs = max_nargs - func_type.optional_arg_count
1588         actual_nargs = len(self.args)
1589         if actual_nargs < expected_nargs \
1590             or (not func_type.has_varargs and actual_nargs > max_nargs):
1591                 expected_str = str(expected_nargs)
1592                 if func_type.has_varargs:
1593                     expected_str = "at least " + expected_str
1594                 elif func_type.optional_arg_count:
1595                     if actual_nargs < max_nargs:
1596                         expected_str = "at least " + expected_str
1597                     else:
1598                         expected_str = "at most " + str(max_nargs)
1599                 error(self.pos, 
1600                     "Call with wrong number of arguments (expected %s, got %s)"
1601                         % (expected_str, actual_nargs))
1602                 self.args = None
1603                 self.type = PyrexTypes.error_type
1604                 self.result_code = "<error>"
1605                 return
1606         # Coerce arguments
1607         for i in range(min(max_nargs, actual_nargs)):
1608             formal_type = func_type.args[i].type
1609             self.args[i] = self.args[i].coerce_to(formal_type, env)
1610         for i in range(max_nargs, actual_nargs):
1611             if self.args[i].type.is_pyobject:
1612                 error(self.args[i].pos, 
1613                     "Python object cannot be passed as a varargs parameter")
1614         # Calc result type and code fragment
1615         self.type = func_type.return_type
1616         if self.type.is_pyobject \
1617             or func_type.exception_value is not None \
1618             or func_type.exception_check:
1619                 self.is_temp = 1
1620                 if self.type.is_pyobject:
1621                     self.result_ctype = py_object_type
1622         # C++ exception handler
1623         if func_type.exception_check == '+':
1624             if func_type.exception_value is None:
1625                 env.use_utility_code(cpp_exception_utility_code)
1626
1627     def calculate_result_code(self):
1628         return self.c_call_code()
1629     
1630     def c_call_code(self):
1631         func_type = self.function_type()
1632         if self.args is None or not func_type.is_cfunction:
1633             return "<error>"
1634         formal_args = func_type.args
1635         arg_list_code = []
1636         args = zip(formal_args, self.args)
1637         max_nargs = len(func_type.args)
1638         expected_nargs = max_nargs - func_type.optional_arg_count
1639         actual_nargs = len(self.args)
1640         for formal_arg, actual_arg in args[:expected_nargs]:
1641                 arg_code = actual_arg.result_as(formal_arg.type)
1642                 arg_list_code.append(arg_code)
1643                 
1644         if func_type.optional_arg_count:
1645             if expected_nargs == actual_nargs:
1646                 optional_args = 'NULL'
1647             else:
1648                 optional_arg_code = [str(actual_nargs - expected_nargs)]
1649                 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
1650                     arg_code = actual_arg.result_as(formal_arg.type)
1651                     optional_arg_code.append(arg_code)
1652 #                for formal_arg in formal_args[actual_nargs:max_nargs]:
1653 #                    optional_arg_code.append(formal_arg.type.cast_code('0'))
1654                 optional_arg_struct = '{%s}' % ','.join(optional_arg_code)
1655                 optional_args = PyrexTypes.c_void_ptr_type.cast_code(
1656                     '&' + func_type.op_arg_struct.base_type.cast_code(optional_arg_struct))
1657             arg_list_code.append(optional_args)
1658             
1659         for actual_arg in self.args[len(formal_args):]:
1660             arg_list_code.append(actual_arg.result_code)
1661         result = "%s(%s)" % (self.function.result_code,
1662             join(arg_list_code, ", "))
1663         if self.wrapper_call or \
1664                 self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
1665             result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
1666         return result
1667     
1668     def generate_result_code(self, code):
1669         func_type = self.function_type()
1670         if func_type.is_pyobject:
1671             arg_code = self.arg_tuple.py_result()
1672             code.putln(
1673                 "%s = PyObject_Call(%s, %s, NULL); %s" % (
1674                     self.result_code,
1675                     self.function.py_result(),
1676                     arg_code,
1677                     code.error_goto_if_null(self.result_code, self.pos)))
1678         elif func_type.is_cfunction:
1679             exc_checks = []
1680             if self.type.is_pyobject:
1681                 exc_checks.append("!%s" % self.result_code)
1682             else:
1683                 exc_val = func_type.exception_value
1684                 exc_check = func_type.exception_check
1685                 if exc_val is not None:
1686                     exc_checks.append("%s == %s" % (self.result_code, exc_val))
1687                 if exc_check:
1688                     exc_checks.append("PyErr_Occurred()")
1689             if self.is_temp or exc_checks:
1690                 rhs = self.c_call_code()
1691                 if self.result_code:
1692                     lhs = "%s = " % self.result_code
1693                     if self.is_temp and self.type.is_pyobject:
1694                         #return_type = self.type # func_type.return_type
1695                         #print "SimpleCallNode.generate_result_code: casting", rhs, \
1696                         #       "from", return_type, "to pyobject" ###
1697                         rhs = typecast(py_object_type, self.type, rhs)
1698                 else:
1699                     lhs = ""
1700                 if func_type.exception_check == '+':
1701                     if func_type.exception_value is None:
1702                         raise_py_exception = "__Pyx_CppExn2PyErr()"
1703                     elif func_type.exception_value.type.is_pyobject:
1704                         raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
1705                     else:
1706                         raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
1707                     code.putln(
1708                     "try {%s%s;} catch(...) {%s; %s}" % (
1709                         lhs,
1710                         rhs,
1711                         raise_py_exception,
1712                         code.error_goto(self.pos)))
1713                     return
1714                 code.putln(
1715                     "%s%s; %s" % (
1716                         lhs,
1717                         rhs,
1718                         code.error_goto_if(" && ".join(exc_checks), self.pos)))    
1719
1720 class GeneralCallNode(ExprNode):
1721     #  General Python function call, including keyword,
1722     #  * and ** arguments.
1723     #
1724     #  function         ExprNode
1725     #  positional_args  ExprNode          Tuple of positional arguments
1726     #  keyword_args     ExprNode or None  Dict of keyword arguments
1727     #  starstar_arg     ExprNode or None  Dict of extra keyword args
1728     
1729     subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
1730
1731     def compile_time_value(self, denv):
1732         function = self.function.compile_time_value(denv)
1733         positional_args = self.positional_args.compile_time_value(denv)
1734         keyword_args = self.keyword_args.compile_time_value(denv)
1735         starstar_arg = self.starstar_arg.compile_time_value(denv)
1736         try:
1737             keyword_args.update(starstar_arg)
1738             return function(*positional_args, **keyword_args)
1739         except Exception, e:
1740             self.compile_time_value_error(e)
1741
1742     def analyse_types(self, env):
1743         self.function.analyse_types(env)
1744         self.positional_args.analyse_types(env)
1745         if self.keyword_args:
1746             self.keyword_args.analyse_types(env)
1747         if self.starstar_arg:
1748             self.starstar_arg.analyse_types(env)
1749         self.function = self.function.coerce_to_pyobject(env)
1750         self.positional_args = \
1751             self.positional_args.coerce_to_pyobject(env)
1752         if self.starstar_arg:
1753             self.starstar_arg = \
1754                 self.starstar_arg.coerce_to_pyobject(env)
1755         self.type = py_object_type
1756         self.is_temp = 1
1757         
1758     def generate_result_code(self, code):
1759         if self.keyword_args and self.starstar_arg:
1760             code.put_error_if_neg(self.pos, 
1761                 "PyDict_Update(%s, %s)" % (
1762                     self.keyword_args.py_result(), 
1763                     self.starstar_arg.py_result()))
1764             keyword_code = self.keyword_args.py_result()
1765         elif self.keyword_args:
1766             keyword_code = self.keyword_args.py_result()
1767         elif self.starstar_arg:
1768             keyword_code = self.starstar_arg.py_result()
1769         else:
1770             keyword_code = None
1771         if not keyword_code:
1772             call_code = "PyObject_Call(%s, %s, NULL)" % (
1773                 self.function.py_result(),
1774                 self.positional_args.py_result())
1775         else:
1776             call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
1777                 self.function.py_result(),
1778                 self.positional_args.py_result(),
1779                 keyword_code)
1780         code.putln(
1781             "%s = %s; %s" % (
1782                 self.result_code,
1783                 call_code,
1784                 code.error_goto_if_null(self.result_code, self.pos)))
1785
1786
1787 class AsTupleNode(ExprNode):
1788     #  Convert argument to tuple. Used for normalising
1789     #  the * argument of a function call.
1790     #
1791     #  arg    ExprNode
1792     
1793     subexprs = ['arg']
1794     
1795     def compile_time_value(self, denv):
1796         arg = self.arg.compile_time_value(denv)
1797         try:
1798             return tuple(arg)
1799         except Exception, e:
1800             self.compile_time_value_error(e)
1801
1802     def analyse_types(self, env):
1803         self.arg.analyse_types(env)
1804         self.arg = self.arg.coerce_to_pyobject(env)
1805         self.type = py_object_type
1806         self.is_temp = 1
1807     
1808     def generate_result_code(self, code):
1809         code.putln(
1810             "%s = PySequence_Tuple(%s); %s" % (
1811                 self.result_code,
1812                 self.arg.py_result(),
1813                 code.error_goto_if_null(self.result_code, self.pos)))
1814     
1815
1816 class AttributeNode(ExprNode):
1817     #  obj.attribute
1818     #
1819     #  obj          ExprNode
1820     #  attribute    string
1821     #
1822     #  Used internally:
1823     #
1824     #  is_py_attr           boolean   Is a Python getattr operation
1825     #  member               string    C name of struct member
1826     #  is_called            boolean   Function call is being done on result
1827     #  entry                Entry     Symbol table entry of attribute
1828     #  interned_attr_cname  string    C name of interned attribute name
1829     
1830     is_attribute = 1
1831     subexprs = ['obj']
1832     
1833     type = PyrexTypes.error_type
1834     result = "<error>"
1835     entry = None
1836     is_called = 0
1837
1838     def coerce_to(self, dst_type, env):
1839         #  If coercing to a generic pyobject and this is a cpdef function
1840         #  we can create the corresponding attribute
1841         if dst_type is py_object_type:
1842             entry = self.entry
1843             if entry and entry.is_cfunction and entry.as_variable:
1844                 # must be a cpdef function
1845                 self.is_temp = 1
1846                 self.entry = entry.as_variable
1847                 self.analyse_as_python_attribute(env) 
1848                 return self
1849         return ExprNode.coerce_to(self, dst_type, env)
1850     
1851     def compile_time_value(self, denv):
1852         attr = self.attribute
1853         if attr.beginswith("__") and attr.endswith("__"):
1854             self.error("Invalid attribute name '%s' in compile-time expression"
1855                 % attr)
1856             return None
1857         obj = self.arg.compile_time_value(denv)
1858         try:
1859             return getattr(obj, attr)
1860         except Exception, e:
1861             self.compile_time_value_error(e)
1862
1863     def analyse_target_declaration(self, env):
1864         pass
1865     
1866     def analyse_target_types(self, env):
1867         self.analyse_types(env, target = 1)
1868     
1869     def analyse_types(self, env, target = 0):
1870         if self.analyse_as_cimported_attribute(env, target):
1871             return
1872         if not target and self.analyse_as_unbound_cmethod(env):
1873             return
1874         self.analyse_as_ordinary_attribute(env, target)
1875     
1876     def analyse_as_cimported_attribute(self, env, target):
1877         # Try to interpret this as a reference to an imported
1878         # C const, type, var or function. If successful, mutates
1879         # this node into a NameNode and returns 1, otherwise
1880         # returns 0.
1881         module_scope = self.obj.analyse_as_module(env)
1882         if module_scope:
1883             entry = module_scope.lookup_here(self.attribute)
1884             if entry and (
1885                 entry.is_cglobal or entry.is_cfunction
1886                 or entry.is_type or entry.is_const):
1887                     self.mutate_into_name_node(env, entry, target)
1888                     return 1
1889         return 0
1890     
1891     def analyse_as_unbound_cmethod(self, env):
1892         # Try to interpret this as a reference to an unbound
1893         # C method of an extension type. If successful, mutates
1894         # this node into a NameNode and returns 1, otherwise
1895         # returns 0.
1896         type = self.obj.analyse_as_extension_type(env)
1897         if type:
1898             entry = type.scope.lookup_here(self.attribute)
1899             if entry and entry.is_cmethod:
1900                 # Create a temporary entry describing the C method
1901                 # as an ordinary function.
1902                 ubcm_entry = Symtab.Entry(entry.name,
1903                     "%s->%s" % (type.vtabptr_cname, entry.cname),
1904                     entry.type)
1905                 ubcm_entry.is_cfunction = 1
1906                 ubcm_entry.func_cname = entry.func_cname
1907                 ubcm_entry.is_unbound_cmethod = 1
1908                 self.mutate_into_name_node(env, ubcm_entry, None)
1909                 return 1
1910         return 0
1911     
1912     def analyse_as_extension_type(self, env):
1913         # Try to interpret this as a reference to an extension type
1914         # in a cimported module. Returns the extension type, or None.
1915         module_scope = self.obj.analyse_as_module(env)
1916         if module_scope:
1917             entry = module_scope.lookup_here(self.attribute)
1918             if entry and entry.is_type and entry.type.is_extension_type:
1919                 return entry.type
1920         return None
1921     
1922     def analyse_as_module(self, env):
1923         # Try to interpret this as a reference to a cimported module
1924         # in another cimported module. Returns the module scope, or None.
1925         module_scope = self.obj.analyse_as_module(env)
1926         if module_scope:
1927             entry = module_scope.lookup_here(self.attribute)
1928             if entry and entry.as_module:
1929                 return entry.as_module
1930         return None
1931                 
1932     def mutate_into_name_node(self, env, entry, target):
1933         # Mutate this node into a NameNode and complete the
1934         # analyse_types phase.
1935         self.__class__ = NameNode
1936         self.name = self.attribute
1937         self.entry = entry
1938         del self.obj
1939         del self.attribute
1940         if target:
1941             NameNode.analyse_target_types(self, env)
1942         else:
1943             NameNode.analyse_rvalue_entry(self, env)
1944     
1945     def analyse_as_ordinary_attribute(self, env, target):
1946         self.obj.analyse_types(env)
1947         self.analyse_attribute(env)
1948         if self.entry and self.entry.is_cmethod and not self.is_called:
1949 #            error(self.pos, "C method can only be called")
1950             pass
1951         ## Reference to C array turns into pointer to first element.
1952         #while self.type.is_array:
1953         #       self.type = self.type.element_ptr_type()
1954         if self.is_py_attr:
1955             if not target:
1956                 self.is_temp = 1
1957                 self.result_ctype = py_object_type
1958     
1959     def analyse_attribute(self, env):
1960         # Look up attribute and set self.type and self.member.
1961         self.is_py_attr = 0
1962         self.member = self.attribute
1963         if self.obj.type.is_string:
1964             self.obj = self.obj.coerce_to_pyobject(env)
1965         obj_type = self.obj.type
1966         if obj_type.is_ptr or obj_type.is_array:
1967             obj_type = obj_type.base_type
1968             self.op = "->"
1969         elif obj_type.is_extension_type:
1970             self.op = "->"
1971         else:
1972             self.op = "."
1973         if obj_type.has_attributes:
1974             entry = None
1975             if obj_type.attributes_known():
1976                 entry = obj_type.scope.lookup_here(self.attribute)
1977                 if entry and entry.is_member:
1978                     entry = None
1979             else:
1980                 error(self.pos, 
1981                     "Cannot select attribute of incomplete type '%s'" 
1982                     % obj_type)
1983                 obj_type = PyrexTypes.error_type
1984             self.entry = entry
1985             if entry:
1986                 if obj_type.is_extension_type and entry.name == "__weakref__":
1987                     error(self.pos, "Illegal use of special attribute __weakref__")
1988                 # methods need the normal attribute lookup
1989                 # because they do not have struct entries
1990                 if entry.is_variable or entry.is_cmethod:
1991                     self.type = entry.type
1992                     self.member = entry.cname
1993                     return
1994                 else:
1995                     # If it's not a variable or C method, it must be a Python
1996                     # method of an extension type, so we treat it like a Python
1997                     # attribute.
1998                     pass
1999         # If we get here, the base object is not a struct/union/extension 
2000         # type, or it is an extension type and the attribute is either not
2001         # declared or is declared as a Python method. Treat it as a Python
2002         # attribute reference.
2003         self.analyse_as_python_attribute(env)
2004                     
2005     def analyse_as_python_attribute(self, env):
2006         obj_type = self.obj.type
2007         self.member = self.attribute
2008         if obj_type.is_pyobject:
2009             self.type = py_object_type
2010             self.is_py_attr = 1
2011             self.interned_attr_cname = env.intern_identifier(self.attribute)
2012         else:
2013             if not obj_type.is_error:
2014                 error(self.pos, 
2015                     "Object of type '%s' has no attribute '%s'" %
2016                     (obj_type, self.attribute))
2017         
2018     def is_simple(self):
2019         if self.obj:
2020             return self.result_in_temp() or self.obj.is_simple()
2021         else:
2022             return NameNode.is_simple(self)
2023
2024     def is_lvalue(self):
2025         if self.obj:
2026             return 1
2027         else:
2028             return NameNode.is_lvalue(self)
2029     
2030     def is_ephemeral(self):
2031         if self.obj:
2032             return self.obj.is_ephemeral()
2033         else:
2034             return NameNode.is_ephemeral(self)
2035     
2036     def calculate_result_code(self):
2037         #print "AttributeNode.calculate_result_code:", self.member ###
2038         #print "...obj node =", self.obj, "code", self.obj.result_code ###
2039         #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2040         obj = self.obj
2041         obj_code = obj.result_as(obj.type)
2042         #print "...obj_code =", obj_code ###
2043         if self.entry and self.entry.is_cmethod:
2044             if obj.type.is_extension_type:
2045                 return "((struct %s *)%s%s%s)->%s" % (
2046                     obj.type.vtabstruct_cname, obj_code, self.op, 
2047                     obj.type.vtabslot_cname, self.member)
2048             else:
2049                 return self.member
2050         else:
2051             return "%s%s%s" % (obj_code, self.op, self.member)
2052     
2053     def generate_result_code(self, code):
2054         if self.is_py_attr:
2055             code.putln(
2056                 '%s = PyObject_GetAttr(%s, %s); %s' % (
2057                     self.result_code,
2058                     self.obj.py_result(),
2059                     self.interned_attr_cname,
2060                     code.error_goto_if_null(self.result_code, self.pos)))
2061     
2062     def generate_assignment_code(self, rhs, code):
2063         self.obj.generate_evaluation_code(code)
2064         if self.is_py_attr:
2065             code.put_error_if_neg(self.pos, 
2066                 'PyObject_SetAttr(%s, %s, %s)' % (
2067                     self.obj.py_result(),
2068                     self.interned_attr_cname,
2069                     rhs.py_result()))
2070             rhs.generate_disposal_code(code)
2071         else:
2072             select_code = self.result_code
2073             if self.type.is_pyobject:
2074                 rhs.make_owned_reference(code)
2075                 code.put_decref(select_code, self.ctype())
2076             code.putln(
2077                 "%s = %s;" % (
2078                     select_code,
2079                     rhs.result_as(self.ctype())))
2080                     #rhs.result_code))
2081             rhs.generate_post_assignment_code(code)
2082         self.obj.generate_disposal_code(code)
2083     
2084     def generate_deletion_code(self, code):
2085         self.obj.generate_evaluation_code(code)
2086         if self.is_py_attr:
2087             code.put_error_if_neg(self.pos,
2088                 'PyObject_DelAttr(%s, %s)' % (
2089                     self.obj.py_result(),
2090                     self.interned_attr_cname))
2091         else:
2092             error(self.pos, "Cannot delete C attribute of extension type")
2093         self.obj.generate_disposal_code(code)
2094         
2095     def annotate(self, code):
2096         if self.is_py_attr:
2097             code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2098         else:
2099             code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2100
2101 #-------------------------------------------------------------------
2102 #
2103 #  Constructor nodes
2104 #
2105 #-------------------------------------------------------------------
2106
2107 class SequenceNode(ExprNode):
2108     #  Base class for list and tuple constructor nodes.
2109     #  Contains common code for performing sequence unpacking.
2110     #
2111     #  args                    [ExprNode]
2112     #  iterator                ExprNode
2113     #  unpacked_items          [ExprNode] or None
2114     #  coerced_unpacked_items  [ExprNode] or None
2115     
2116     subexprs = ['args']
2117     
2118     is_sequence_constructor = 1
2119     unpacked_items = None
2120     
2121     def compile_time_value_list(self, denv):
2122         return [arg.compile_time_value(denv) for arg in self.args]
2123
2124     def analyse_target_declaration(self, env):
2125         for arg in self.args:
2126             arg.analyse_target_declaration(env)
2127
2128     def analyse_types(self, env):
2129         for i in range(len(self.args)):
2130             arg = self.args[i]
2131             arg.analyse_types(env)
2132             self.args[i] = arg.coerce_to_pyobject(env)
2133         self.type = py_object_type
2134         self.is_temp = 1
2135     
2136     def analyse_target_types(self, env):
2137         self.iterator = PyTempNode(self.pos, env)
2138         self.unpacked_items = []
2139         self.coerced_unpacked_items = []
2140         for arg in self.args:
2141             arg.analyse_target_types(env)
2142             unpacked_item = PyTempNode(self.pos, env)
2143             coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2144             self.unpacked_items.append(unpacked_item)
2145             self.coerced_unpacked_items.append(coerced_unpacked_item)
2146         self.type = py_object_type
2147         env.use_utility_code(unpacking_utility_code)
2148     
2149     def allocate_target_temps(self, env, rhs):
2150         self.iterator.allocate_temps(env)
2151         for arg, node in zip(self.args, self.coerced_unpacked_items):
2152             node.allocate_temps(env)
2153             arg.allocate_target_temps(env, node)
2154             #arg.release_target_temp(env)
2155             #node.release_temp(env)
2156         if rhs:
2157             rhs.release_temp(env)
2158         self.iterator.release_temp(env)
2159     
2160 #       def release_target_temp(self, env):
2161 #               #for arg in self.args:
2162 #               #       arg.release_target_temp(env)
2163 #               #for node in self.coerced_unpacked_items:
2164 #               #       node.release_temp(env)
2165 #               self.iterator.release_temp(env)
2166     
2167     def generate_result_code(self, code):
2168         self.generate_operation_code(code)
2169     
2170     def generate_assignment_code(self, rhs, code):
2171         code.putln(
2172             "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
2173                 rhs.py_result(), 
2174                 rhs.py_result(), 
2175                 len(self.args)))
2176         code.putln("PyObject* tuple = %s;" % rhs.py_result())
2177         for i in range(len(self.args)):
2178             item = self.unpacked_items[i]
2179             code.putln(
2180                 "%s = PyTuple_GET_ITEM(tuple, %s);" % (
2181                     item.result_code,
2182                     i))
2183             code.put_incref(item.result_code, item.ctype())
2184             value_node = self.coerced_unpacked_items[i]
2185             value_node.generate_evaluation_code(code)
2186             self.args[i].generate_assignment_code(value_node, code)
2187             
2188         rhs.generate_disposal_code(code)
2189         code.putln("}")
2190         code.putln("else {")
2191
2192         code.putln(
2193             "%s = PyObject_GetIter(%s); %s" % (
2194                 self.iterator.result_code,
2195                 rhs.py_result(),
2196                 code.error_goto_if_null(self.iterator.result_code, self.pos)))
2197         rhs.generate_disposal_code(code)
2198         for i in range(len(self.args)):
2199             item = self.unpacked_items[i]
2200             unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
2201                 self.iterator.py_result(), i)
2202             code.putln(
2203                 "%s = %s; %s" % (
2204                     item.result_code,
2205                     typecast(item.ctype(), py_object_type, unpack_code),
2206                     code.error_goto_if_null(item.result_code, self.pos)))
2207             value_node = self.coerced_unpacked_items[i]
2208             value_node.generate_evaluation_code(code)
2209             self.args[i].generate_assignment_code(value_node, code)
2210         code.put_error_if_neg(self.pos, 
2211             "__Pyx_EndUnpack(%s)" % (
2212                 self.iterator.py_result()))
2213         if debug_disposal_code:
2214             print("UnpackNode.generate_assignment_code:")
2215             print("...generating disposal code for %s" % self.iterator)
2216         self.iterator.generate_disposal_code(code)
2217
2218         code.putln("}")
2219         
2220     def annotate(self, code):
2221         for arg in self.args:
2222             arg.annotate(code)
2223         if self.unpacked_items:
2224             for arg in self.unpacked_items:
2225                 arg.annotate(code)
2226             for arg in self.coerced_unpacked_items:
2227                 arg.annotate(code)
2228
2229
2230 class TupleNode(SequenceNode):
2231     #  Tuple constructor.
2232     
2233     def analyse_types(self, env):
2234         if len(self.args) == 0:
2235             self.is_temp = 0
2236             self.is_literal = 1
2237         else:
2238             SequenceNode.analyse_types(self, env)
2239         self.type = tuple_type
2240             
2241     def calculate_result_code(self):
2242         if len(self.args) > 0:
2243             error(self.pos, "Positive length tuples must be constructed.")
2244         else:
2245             return Naming.empty_tuple
2246
2247     def compile_time_value(self, denv):
2248         values = self.compile_time_value_list(denv)
2249         try:
2250             return tuple(values)
2251         except Exception, e:
2252             self.compile_time_value_error(e)
2253     
2254     def generate_operation_code(self, code):
2255         if len(self.args) == 0:
2256             # result_code is Naming.empty_tuple
2257             return
2258         code.putln(
2259             "%s = PyTuple_New(%s); %s" % (
2260                 self.result_code,
2261                 len(self.args),
2262                 code.error_goto_if_null(self.result_code, self.pos)))
2263         for i in range(len(self.args)):
2264             arg = self.args[i]
2265             if not arg.result_in_temp():
2266                 code.put_incref(arg.result_code, arg.ctype())
2267             code.putln(
2268                 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2269                     self.result_code,
2270                     i,
2271                     arg.py_result()))
2272     
2273     def generate_subexpr_disposal_code(self, code):
2274         # We call generate_post_assignment_code here instead
2275         # of generate_disposal_code, because values were stored
2276         # in the tuple using a reference-stealing operation.
2277         for arg in self.args:
2278             arg.generate_post_assignment_code(code)             
2279
2280
2281 class ListNode(SequenceNode):
2282     #  List constructor.
2283     
2284     def analyse_types(self, env):
2285         SequenceNode.analyse_types(self, env)
2286         self.type = list_type
2287
2288     def compile_time_value(self, denv):
2289         return self.compile_time_value_list(denv)
2290
2291     def generate_operation_code(self, code):
2292         code.putln("%s = PyList_New(%s); %s" %
2293             (self.result_code,
2294             len(self.args),
2295             code.error_goto_if_null(self.result_code, self.pos)))
2296         for i in range(len(self.args)):
2297             arg = self.args[i]
2298             #if not arg.is_temp:
2299             if not arg.result_in_temp():
2300                 code.put_incref(arg.result_code, arg.ctype())
2301             code.putln("PyList_SET_ITEM(%s, %s, %s);" %
2302                 (self.result_code,
2303                 i,
2304                 arg.py_result()))
2305                 
2306     def generate_subexpr_disposal_code(self, code):
2307         # We call generate_post_assignment_code here instead
2308         # of generate_disposal_code, because values were stored
2309         # in the list using a reference-stealing operation.
2310         for arg in self.args:
2311             arg.generate_post_assignment_code(code)             
2312
2313             
2314 class ListComprehensionNode(SequenceNode):
2315
2316     subexprs = []
2317     is_sequence_constructor = 0 # not unpackable
2318
2319     def analyse_types(self, env): 
2320         self.type = list_type
2321         self.is_temp = 1
2322         self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
2323         
2324     def allocate_temps(self, env, result = None): 
2325         if debug_temp_alloc:
2326             print("%s Allocating temps" % self)
2327         self.allocate_temp(env, result)
2328         self.loop.analyse_declarations(env)
2329         self.loop.analyse_expressions(env)
2330         
2331     def generate_operation_code(self, code):
2332         code.putln("%s = PyList_New(%s); %s" %
2333             (self.result_code,
2334             0,
2335             code.error_goto_if_null(self.result_code, self.pos)))
2336         self.loop.generate_execution_code(code)
2337         
2338     def annotate(self, code):
2339         self.loop.annotate(code)
2340
2341
2342 class ListComprehensionAppendNode(ExprNode):
2343
2344     subexprs = ['expr']
2345     
2346     def analyse_types(self, env):
2347         self.expr.analyse_types(env)
2348         if self.expr.type != py_object_type:
2349             self.expr = self.expr.coerce_to_pyobject(env)
2350         self.type = PyrexTypes.c_int_type
2351         self.is_temp = 1
2352     
2353     def generate_result_code(self, code):
2354         code.putln("%s = PyList_Append(%s, %s); %s" %
2355             (self.result_code,
2356             self.target.result_code,
2357             self.expr.result_code,
2358             code.error_goto_if(self.result_code, self.pos)))
2359
2360
2361 class DictNode(ExprNode):
2362     #  Dictionary constructor.
2363     #
2364     #  key_value_pairs  [DictItemNode]
2365     
2366     subexprs = ['key_value_pairs']
2367     
2368     def compile_time_value(self, denv):
2369         pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
2370             for item in self.key_value_pairs]
2371         try:
2372             return dict(pairs)
2373         except Exception, e:
2374             self.compile_time_value_error(e)
2375     
2376     def analyse_types(self, env):
2377         for item in self.key_value_pairs:
2378             item.analyse_types(env)
2379         self.type = dict_type
2380         self.is_temp = 1
2381     
2382     def allocate_temps(self, env, result = None):
2383         #  Custom method used here because key-value
2384         #  pairs are evaluated and used one at a time.
2385         self.allocate_temp(env, result)
2386         for item in self.key_value_pairs:
2387             item.key.allocate_temps(env)
2388             item.value.allocate_temps(env)
2389             item.key.release_temp(env)
2390             item.value.release_temp(env)
2391     
2392     def generate_evaluation_code(self, code):
2393         #  Custom method used here because key-value
2394         #  pairs are evaluated and used one at a time.
2395         code.putln(
2396             "%s = PyDict_New(); %s" % (
2397                 self.result_code,
2398                 code.error_goto_if_null(self.result_code, self.pos)))
2399         for item in self.key_value_pairs:
2400             item.generate_evaluation_code(code)
2401             code.put_error_if_neg(self.pos, 
2402                 "PyDict_SetItem(%s, %s, %s)" % (
2403                     self.result_code,
2404                     item.key.py_result(),
2405                     item.value.py_result()))
2406             item.generate_disposal_code(code)
2407             
2408     def annotate(self, code):
2409         for item in self.key_value_pairs:
2410             item.annotate(code)
2411             
2412 class DictItemNode(ExprNode):
2413     # Represents a single item in a DictNode
2414     #
2415     # key          ExprNode
2416     # value        ExprNode
2417     subexprs = ['key', 'value']
2418             
2419     def analyse_types(self, env):
2420         self.key.analyse_types(env)
2421         self.value.analyse_types(env)
2422         self.key = self.key.coerce_to_pyobject(env)
2423         self.value = self.value.coerce_to_pyobject(env)
2424         
2425     def generate_evaluation_code(self, code):
2426         self.key.generate_evaluation_code(code)
2427         self.value.generate_evaluation_code(code)
2428         
2429     def generate_disposal_code(self, code):
2430         self.key.generate_disposal_code(code)
2431         self.value.generate_disposal_code(code)
2432
2433
2434 class ClassNode(ExprNode):
2435     #  Helper class used in the implementation of Python
2436     #  class definitions. Constructs a class object given
2437     #  a name, tuple of bases and class dictionary.
2438     #
2439     #  name         EncodedString      Name of the class
2440     #  cname        string             Class name as a Python string
2441     #  bases        ExprNode           Base class tuple
2442     #  dict         ExprNode           Class dict (not owned by this node)
2443     #  doc          ExprNode or None   Doc string
2444     #  module_name  string             Name of defining module
2445     
2446     subexprs = ['bases', 'doc']
2447
2448     def analyse_types(self, env):
2449         self.cname = env.intern_identifier(self.name)
2450         self.bases.analyse_types(env)
2451         if self.doc:
2452             self.doc.analyse_types(env)
2453             self.doc = self.doc.coerce_to_pyobject(env)
2454         self.module_name = env.global_scope().qualified_name
2455         self.type = py_object_type
2456         self.is_temp = 1
2457         env.use_utility_code(create_class_utility_code);
2458
2459     def generate_result_code(self, code):
2460         if self.doc:
2461             code.put_error_if_neg(self.pos, 
2462                 'PyDict_SetItemString(%s, "__doc__", %s)' % (
2463                     self.dict.py_result(),
2464                     self.doc.py_result()))
2465         code.putln(
2466             '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
2467                 self.result_code,
2468                 self.bases.py_result(),
2469                 self.dict.py_result(),
2470                 self.cname,
2471                 self.module_name,
2472                 code.error_goto_if_null(self.result_code, self.pos)))
2473
2474
2475 class UnboundMethodNode(ExprNode):
2476     #  Helper class used in the implementation of Python
2477     #  class definitions. Constructs an unbound method
2478     #  object from a class and a function.
2479     #
2480     #  class_cname   string     C var holding the class object
2481     #  function      ExprNode   Function object
2482     
2483     subexprs = ['function']
2484     
2485     def analyse_types(self, env):
2486         self.function.analyse_types(env)
2487         self.type = py_object_type
2488         self.is_temp = 1
2489     
2490     def generate_result_code(self, code):
2491         code.putln(
2492             "%s = PyMethod_New(%s, 0, %s); %s" % (
2493                 self.result_code,
2494                 self.function.py_result(),
2495                 self.class_cname,
2496                 code.error_goto_if_null(self.result_code, self.pos)))
2497
2498
2499 class PyCFunctionNode(AtomicExprNode):
2500     #  Helper class used in the implementation of Python
2501     #  class definitions. Constructs a PyCFunction object
2502     #  from a PyMethodDef struct.
2503     #
2504     #  pymethdef_cname   string   PyMethodDef structure
2505     
2506     def analyse_types(self, env):
2507         self.type = py_object_type
2508         self.is_temp = 1
2509     
2510     def generate_result_code(self, code):
2511         code.putln(
2512             "%s = PyCFunction_New(&%s, 0); %s" % (
2513                 self.result_code,
2514                 self.pymethdef_cname,
2515                 code.error_goto_if_null(self.result_code, self.pos)))
2516
2517 #-------------------------------------------------------------------
2518 #
2519 #  Unary operator nodes
2520 #
2521 #-------------------------------------------------------------------
2522
2523 compile_time_unary_operators = {
2524     'not': operator.not_,
2525     '~': operator.inv,
2526     '-': operator.neg,
2527     '+': operator.pos,
2528 }
2529
2530 class UnopNode(ExprNode):
2531     #  operator     string
2532     #  operand      ExprNode
2533     #
2534     #  Processing during analyse_expressions phase:
2535     #
2536     #    analyse_c_operation
2537     #      Called when the operand is not a pyobject.
2538     #      - Check operand type and coerce if needed.
2539     #      - Determine result type and result code fragment.
2540     #      - Allocate temporary for result if needed.
2541     
2542     subexprs = ['operand']
2543     
2544     def compile_time_value(self, denv):
2545         func = compile_time_unary_operators.get(self.operator)
2546         if not func:
2547             error(self.pos,
2548                 "Unary '%s' not supported in compile-time expression"
2549                     % self.operator)
2550         operand = self.operand.compile_time_value(denv)
2551         try:
2552             return func(operand)
2553         except Exception, e:
2554             self.compile_time_value_error(e)
2555
2556     def analyse_types(self, env):
2557         self.operand.analyse_types(env)
2558         if self.is_py_operation():
2559             self.coerce_operand_to_pyobject(env)
2560             self.type = py_object_type
2561             self.is_temp = 1
2562         else:
2563             self.analyse_c_operation(env)
2564     
2565     def check_const(self):
2566         self.operand.check_const()
2567     
2568     def is_py_operation(self):
2569         return self.operand.type.is_pyobject
2570     
2571     def coerce_operand_to_pyobject(self, env):
2572         self.operand = self.operand.coerce_to_pyobject(env)
2573     
2574     def generate_result_code(self, code):
2575         if self.operand.type.is_pyobject:
2576             self.generate_py_operation_code(code)
2577         else:
2578             if self.is_temp:
2579                 self.generate_c_operation_code(code)
2580     
2581     def generate_py_operation_code(self, code):
2582         function = self.py_operation_function()
2583         code.putln(
2584             "%s = %s(%s); %s" % (
2585                 self.result_code, 
2586                 function, 
2587                 self.operand.py_result(),
2588                 code.error_goto_if_null(self.result_code, self.pos)))
2589         
2590     def type_error(self):
2591         if not self.operand.type.is_error:
2592             error(self.pos, "Invalid operand type for '%s' (%s)" %
2593                 (self.operator, self.operand.type))
2594         self.type = PyrexTypes.error_type
2595
2596
2597 class NotNode(ExprNode):
2598     #  'not' operator
2599     #
2600     #  operand   ExprNode
2601     
2602     def compile_time_value(self, denv):
2603         operand = self.operand.compile_time_value(denv)
2604         try:
2605             return not operand
2606         except Exception, e:
2607             self.compile_time_value_error(e)
2608
2609     subexprs = ['operand']
2610     
2611     def analyse_types(self, env):
2612         self.operand.analyse_types(env)
2613         self.operand = self.operand.coerce_to_boolean(env)
2614         self.type = PyrexTypes.c_bint_type
2615     
2616     def calculate_result_code(self):
2617         return "(!%s)" % self.operand.result_code
2618     
2619     def generate_result_code(self, code):
2620         pass
2621
2622
2623 class UnaryPlusNode(UnopNode):
2624     #  unary '+' operator
2625     
2626     operator = '+'
2627     
2628     def analyse_c_operation(self, env):
2629         self.type = self.operand.type
2630     
2631     def py_operation_function(self):
2632         return "PyNumber_Positive"
2633     
2634     def calculate_result_code(self):
2635         return self.operand.result_code
2636
2637
2638 class UnaryMinusNode(UnopNode):
2639     #  unary '-' operator
2640     
2641     operator = '-'
2642     
2643     def analyse_c_operation(self, env):
2644         if self.operand.type.is_numeric:
2645             self.type = self.operand.type
2646         else:
2647             self.type_error()
2648     
2649     def py_operation_function(self):
2650         return "PyNumber_Negative"
2651     
2652     def calculate_result_code(self):
2653         return "(-%s)" % self.operand.result_code
2654
2655
2656 class TildeNode(UnopNode):
2657     #  unary '~' operator
2658
2659     def analyse_c_operation(self, env):
2660         if self.operand.type.is_int:
2661             self.type = self.operand.type
2662         else:
2663             self.type_error()
2664
2665     def py_operation_function(self):
2666         return "PyNumber_Invert"
2667     
2668     def calculate_result_code(self):
2669         return "(~%s)" % self.operand.result_code
2670
2671
2672 class AmpersandNode(ExprNode):
2673     #  The C address-of operator.
2674     #
2675     #  operand  ExprNode
2676     
2677     subexprs = ['operand']
2678
2679     def analyse_types(self, env):
2680         self.operand.analyse_types(env)
2681         argtype = self.operand.type
2682         if not (argtype.is_cfunction or self.operand.is_lvalue()):
2683             self.error("Taking address of non-lvalue")
2684             return
2685         if argtype.is_pyobject:
2686             self.error("Cannot take address of Python variable")
2687             return
2688         self.type = PyrexTypes.c_ptr_type(argtype)
2689     
2690     def check_const(self):
2691         self.operand.check_const_addr()
2692     
2693     def error(self, mess):
2694         error(self.pos, mess)
2695         self.type = PyrexTypes.error_type
2696         self.result_code = "<error>"
2697     
2698     def calculate_result_code(self):
2699         return "(&%s)" % self.operand.result_code
2700
2701     def generate_result_code(self, code):
2702         pass
2703     
2704
2705 unop_node_classes = {
2706     "+":  UnaryPlusNode,
2707     "-":  UnaryMinusNode,
2708     "~":  TildeNode,
2709 }
2710
2711 def unop_node(pos, operator, operand):
2712     # Construct unnop node of appropriate class for 
2713     # given operator.
2714     if isinstance(operand, IntNode) and operator == '-':
2715         return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
2716     elif isinstance(operand, UnopNode) and operand.operator == operator:
2717         warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
2718     return unop_node_classes[operator](pos, 
2719         operator = operator, 
2720         operand = operand)
2721
2722
2723 class TypecastNode(ExprNode):
2724     #  C type cast
2725     #
2726     #  base_type    CBaseTypeNode
2727     #  declarator   CDeclaratorNode
2728     #  operand      ExprNode
2729     
2730     subexprs = ['operand']
2731     
2732     def analyse_types(self, env):
2733         base_type = self.base_type.analyse(env)
2734         _, self.type = self.declarator.analyse(base_type, env)
2735         self.operand.analyse_types(env)
2736         to_py = self.type.is_pyobject
2737         from_py = self.operand.type.is_pyobject
2738         if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
2739             error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
2740         if to_py and not from_py:
2741             self.result_ctype = py_object_type
2742             self.is_temp = 1
2743             if self.operand.type.to_py_function:
2744                 self.operand = self.operand.coerce_to_pyobject(env)
2745             else:
2746                 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
2747         elif from_py and not to_py:
2748             if self.type.from_py_function:
2749                 self.operand = self.operand.coerce_to(self.type, env)
2750             else:
2751                 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
2752         elif from_py and to_py:
2753             if self.typecheck and self.type.is_extension_type:
2754                 self.operand = PyTypeTestNode(self.operand, self.type, env)
2755     
2756     def check_const(self):
2757         self.operand.check_const()
2758     
2759     def calculate_result_code(self):
2760         opnd = self.operand
2761         result_code = self.type.cast_code(opnd.result_code)
2762         return result_code
2763     
2764     def result_as(self, type):
2765         if self.type.is_pyobject and not self.is_temp:
2766             #  Optimise away some unnecessary casting
2767             return self.operand.result_as(type)
2768         else:
2769             return ExprNode.result_as(self, type)
2770
2771     def generate_result_code(self, code):
2772         if self.is_temp:
2773             code.putln(
2774                 "%s = (PyObject *)%s;" % (
2775                     self.result_code,
2776                     self.operand.result_code))
2777             code.put_incref(self.result_code, self.ctype())
2778
2779
2780 class SizeofNode(ExprNode):
2781     #  Abstract base class for sizeof(x) expression nodes.
2782
2783     def check_const(self):
2784         pass
2785
2786     def generate_result_code(self, code):
2787         pass
2788
2789
2790 class SizeofTypeNode(SizeofNode):
2791     #  C sizeof function applied to a type
2792     #
2793     #  base_type   CBaseTypeNode
2794     #  declarator  CDeclaratorNode
2795     
2796     subexprs = []
2797     
2798     def analyse_types(self, env):
2799         base_type = self.base_type.analyse(env)
2800         _, arg_type = self.declarator.analyse(base_type, env)
2801         self.arg_type = arg_type
2802         if arg_type.is_pyobject and not arg_type.is_extension_type:
2803             error(self.pos, "Cannot take sizeof Python object")
2804         elif arg_type.is_void:
2805             error(self.pos, "Cannot take sizeof void")
2806         elif not arg_type.is_complete():
2807             error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
2808         self.type = PyrexTypes.c_int_type
2809         
2810     def calculate_result_code(self):
2811         if self.arg_type.is_extension_type:
2812             # the size of the pointer is boring
2813             # we want the size of the actual struct
2814             arg_code = self.arg_type.declaration_code("", deref=1)
2815         else:
2816             arg_code = self.arg_type.declaration_code("")
2817         return "(sizeof(%s))" % arg_code
2818     
2819
2820 class SizeofVarNode(SizeofNode):
2821     #  C sizeof function applied to a variable
2822     #
2823     #  operand   ExprNode
2824     
2825     subexprs = ['operand']
2826     
2827     def analyse_types(self, env):
2828         self.operand.analyse_types(env)
2829         self.type = PyrexTypes.c_int_type
2830     
2831     def calculate_result_code(self):
2832         return "(sizeof(%s))" % self.operand.result_code
2833     
2834     def generate_result_code(self, code):
2835         pass
2836
2837
2838 #-------------------------------------------------------------------
2839 #
2840 #  Binary operator nodes
2841 #
2842 #-------------------------------------------------------------------
2843
2844 def _not_in(x, seq):
2845     return x not in seq
2846
2847 compile_time_binary_operators = {
2848     '<': operator.lt,
2849     '<=': operator.le,
2850     '==': operator.eq,
2851     '!=': operator.ne,
2852     '>=': operator.ge,
2853     '>': operator.gt,
2854     'is': operator.is_,
2855     'is_not': operator.is_not,
2856     '+': operator.add,
2857     '&': operator.and_,
2858     '/': operator.div,
2859     '//': operator.floordiv,
2860     '<<': operator.lshift,
2861     '%': operator.mod,
2862     '*': operator.mul,
2863     '|': operator.or_,
2864     '**': operator.pow,
2865     '>>': operator.rshift,
2866     '-': operator.sub,
2867     #'/': operator.truediv,
2868     '^': operator.xor,
2869     'in': operator.contains,
2870     'not_in': _not_in,
2871 }
2872
2873 def get_compile_time_binop(node):
2874     func = compile_time_binary_operators.get(node.operator)
2875     if not func:
2876         error(node.pos,
2877             "Binary '%s' not supported in compile-time expression"
2878                 % node.operator)
2879     return func
2880
2881 class BinopNode(ExprNode):
2882     #  operator     string
2883     #  operand1     ExprNode
2884     #  operand2     ExprNode
2885     #
2886     #  Processing during analyse_expressions phase:
2887     #
2888     #    analyse_c_operation
2889     #      Called when neither operand is a pyobject.
2890     #      - Check operand types and coerce if needed.
2891     #      - Determine result type and result code fragment.
2892     #      - Allocate temporary for result if needed.
2893     
2894     subexprs = ['operand1', 'operand2']
2895     
2896     def compile_time_value(self, denv):
2897         func = get_compile_time_binop(self)
2898         operand1 = self.operand1.compile_time_value(denv)
2899         operand2 = self.operand2.compile_time_value(denv)
2900         try:
2901             return func(operand1, operand2)
2902         except Exception, e:
2903             self.compile_time_value_error(e)
2904
2905     def analyse_types(self, env):
2906         self.operand1.analyse_types(env)
2907         self.operand2.analyse_types(env)
2908         if self.is_py_operation():
2909             self.coerce_operands_to_pyobjects(env)
2910             self.type = py_object_type
2911             self.is_temp = 1
2912             if Options.incref_local_binop and self.operand1.type.is_pyobject:
2913                 self.operand1 = self.operand1.coerce_to_temp(env)
2914         else:
2915             self.analyse_c_operation(env)
2916     
2917     def is_py_operation(self):
2918         return (self.operand1.type.is_pyobject 
2919             or self.operand2.type.is_pyobject)
2920     
2921     def coerce_operands_to_pyobjects(self, env):
2922         self.operand1 = self.operand1.coerce_to_pyobject(env)
2923         self.operand2 = self.operand2.coerce_to_pyobject(env)
2924     
2925     def check_const(self):
2926         self.operand1.check_const()
2927         self.operand2.check_const()
2928     
2929     def generate_result_code(self, code):
2930         #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
2931         if self.operand1.type.is_pyobject:
2932             function = self.py_operation_function()
2933             if function == "PyNumber_Power":
2934                 extra_args = ", Py_None"
2935             else:
2936                 extra_args = ""
2937             code.putln(
2938                 "%s = %s(%s, %s%s); %s" % (
2939                     self.result_code, 
2940                     function, 
2941                     self.operand1.py_result(),
2942                     self.operand2.py_result(),
2943                     extra_args,
2944                     code.error_goto_if_null(self.result_code, self.pos)))
2945         else:
2946             if self.is_temp:
2947                 self.generate_c_operation_code(code)
2948     
2949     def type_error(self):
2950         if not (self.operand1.type.is_error
2951                 or self.operand2.type.is_error):
2952             error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
2953                 (self.operator, self.operand1.type, 
2954                     self.operand2.type))
2955         self.type = PyrexTypes.error_type
2956
2957
2958 class NumBinopNode(BinopNode):
2959     #  Binary operation taking numeric arguments.
2960     
2961     def analyse_c_operation(self, env):
2962         type1 = self.operand1.type
2963         type2 = self.operand2.type
2964         if self.operator == "**" and type1.is_int and type2.is_int:
2965             error(self.pos, "** with two C int types is ambiguous")
2966             self.type = error_type
2967             return
2968         self.type = self.compute_c_result_type(type1, type2)
2969         if not self.type:
2970             self.type_error()
2971     
2972     def compute_c_result_type(self, type1, type2):
2973         if self.c_types_okay(type1, type2):
2974             return PyrexTypes.widest_numeric_type(type1, type2)
2975         else:
2976             return None
2977     
2978     def c_types_okay(self, type1, type2):
2979         #print "NumBinopNode.c_types_okay:", type1, type2 ###
2980         return (type1.is_numeric  or type1.is_enum) \
2981             and (type2.is_numeric  or type2.is_enum)
2982
2983     def calculate_result_code(self):
2984         return "(%s %s %s)" % (
2985             self.operand1.result_code, 
2986             self.operator, 
2987             self.operand2.result_code)
2988     
2989     def py_operation_function(self):
2990         return self.py_functions[self.operator]
2991
2992     py_functions = {
2993         "|":            "PyNumber_Or",
2994         "^":            "PyNumber_Xor",
2995         "&":            "PyNumber_And",
2996         "<<":           "PyNumber_Lshift",
2997         ">>":           "PyNumber_Rshift",
2998         "+":            "PyNumber_Add",
2999         "-":            "PyNumber_Subtract",
3000         "*":            "PyNumber_Multiply",
3001         "/":            "PyNumber_Divide",
3002         "//":           "PyNumber_FloorDivide",
3003         "%":            "PyNumber_Remainder",
3004         "**":       "PyNumber_Power"
3005     }
3006
3007
3008 class IntBinopNode(NumBinopNode):
3009     #  Binary operation taking integer arguments.
3010     
3011     def c_types_okay(self, type1, type2):
3012         #print "IntBinopNode.c_types_okay:", type1, type2 ###
3013         return (type1.is_int or type1.is_enum) \
3014             and (type2.is_int or type2.is_enum)
3015
3016     
3017 class AddNode(NumBinopNode):
3018     #  '+' operator.
3019     
3020     def is_py_operation(self):
3021         if self.operand1.type.is_string \
3022             and self.operand2.type.is_string:
3023                 return 1
3024         else:
3025             return NumBinopNode.is_py_operation(self)
3026
3027     def compute_c_result_type(self, type1, type2):
3028         #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
3029         if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3030             return type1
3031         elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
3032             return type2
3033         else:
3034             return NumBinopNode.compute_c_result_type(
3035                 self, type1, type2)
3036
3037
3038 class SubNode(NumBinopNode):
3039     #  '-' operator.
3040     
3041     def compute_c_result_type(self, type1, type2):
3042         if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3043             return type1
3044         elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
3045             return PyrexTypes.c_int_type
3046         else:
3047             return NumBinopNode.compute_c_result_type(
3048                 self, type1, type2)
3049
3050
3051 class MulNode(NumBinopNode):
3052     #  '*' operator.
3053     
3054     def is_py_operation(self):
3055         type1 = self.operand1.type
3056         type2 = self.operand2.type
3057         if (type1.is_string and type2.is_int) \
3058             or (type2.is_string and type1.is_int):
3059                 return 1
3060         else:
3061             return NumBinopNode.is_py_operation(self)
3062
3063
3064 class FloorDivNode(NumBinopNode):
3065     #  '//' operator.
3066     
3067     def calculate_result_code(self):
3068         return "(%s %s %s)" % (
3069             self.operand1.result_code, 
3070             "/",  # c division is by default floor-div 
3071             self.operand2.result_code)
3072
3073
3074 class ModNode(IntBinopNode):
3075     #  '%' operator.
3076     
3077     def is_py_operation(self):
3078         return (self.operand1.type.is_string
3079             or self.operand2.type.is_string
3080             or IntBinopNode.is_py_operation(self))
3081
3082
3083 class PowNode(NumBinopNode):
3084     #  '**' operator.
3085
3086     def analyse_types(self, env):
3087         env.pow_function_used = 1
3088         NumBinopNode.analyse_types(self, env)
3089
3090     def compute_c_result_type(self, type1, type2):
3091         if self.c_types_okay(type1, type2):
3092             return PyrexTypes.c_double_type
3093         else:
3094             return None
3095
3096     def c_types_okay(self, type1, type2):
3097         return type1.is_float or type2.is_float
3098
3099     def type_error(self):
3100         if not (self.operand1.type.is_error or self.operand2.type.is_error):
3101             if self.operand1.type.is_int and self.operand2.type.is_int:
3102                 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
3103                     (self.operator, self.operand1.type, self.operand2.type))
3104             else:
3105                 NumBinopNode.type_error(self)
3106         self.type = PyrexTypes.error_type
3107
3108     def calculate_result_code(self):
3109         return "pow(%s, %s)" % (
3110             self.operand1.result_code, self.operand2.result_code)
3111
3112
3113 class BoolBinopNode(ExprNode):
3114     #  Short-circuiting boolean operation.
3115     #
3116     #  operator     string
3117     #  operand1     ExprNode
3118     #  operand2     ExprNode
3119     #  temp_bool    ExprNode     used internally
3120     
3121     temp_bool = None
3122     
3123     subexprs = ['operand1', 'operand2', 'temp_bool']
3124     
3125     def compile_time_value(self, denv):
3126         if self.operator == 'and':
3127             return self.operand1.compile_time_value(denv) \
3128                 and self.operand2.compile_time_value(denv)
3129         else:
3130             return self.operand1.compile_time_value(denv) \
3131                 or self.operand2.compile_time_value(denv)
3132
3133     def analyse_types(self, env):
3134         self.operand1.analyse_types(env)
3135         self.operand2.analyse_types(env)
3136         if self.operand1.type.is_pyobject or \
3137                 self.operand2.type.is_pyobject:
3138             self.operand1 = self.operand1.coerce_to_pyobject(env)
3139             self.operand2 = self.operand2.coerce_to_pyobject(env)
3140             self.temp_bool = TempNode(self.pos, PyrexTypes.c_bint_type, env)
3141             self.type = py_object_type
3142         else:
3143             self.operand1 = self.operand1.coerce_to_boolean(env)
3144             self.operand2 = self.operand2.coerce_to_boolean(env)
3145             self.type = PyrexTypes.c_bint_type
3146         # For what we're about to do, it's vital that
3147         # both operands be temp nodes.
3148         self.operand1 = self.operand1.coerce_to_temp(env) #CTT
3149         self.operand2 = self.operand2.coerce_to_temp(env)
3150         # coerce_to_simple does not seem to be sufficient
3151         #self.operand1 = self.operand1.coerce_to_simple(env)
3152         #self.operand2 = self.operand2.coerce_to_simple(env)
3153         self.is_temp = 1
3154     
3155     def allocate_temps(self, env, result_code = None):
3156         #  We don't need both operands at the same time, and
3157         #  one of the operands will also be our result. So we
3158         #  use an allocation strategy here which results in
3159         #  this node and both its operands sharing the same
3160         #  result variable. This allows us to avoid some 
3161         #  assignments and increfs/decrefs that would otherwise
3162         #  be necessary.
3163         self.allocate_temp(env, result_code)
3164         self.operand1.allocate_temps(env, self.result_code)
3165         if self.temp_bool:
3166             self.temp_bool.allocate_temp(env)
3167             self.temp_bool.release_temp(env)
3168         self.operand2.allocate_temps(env, self.result_code)
3169         #  We haven't called release_temp on either operand,
3170         #  because although they are temp nodes, they don't own 
3171         #  their result variable. And because they are temp
3172         #  nodes, any temps in their subnodes will have been
3173         #  released before their allocate_temps returned.
3174         #  Therefore, they contain no temp vars that need to
3175         #  be released.
3176
3177     def check_const(self):
3178         self.operand1.check_const()
3179         self.operand2.check_const()
3180     
3181     def calculate_result_code(self):
3182         return "(%s %s %s)" % (
3183             self.operand1.result_code,
3184             self.py_to_c_op[self.operator],
3185             self.operand2.result_code)
3186     
3187     py_to_c_op = {'and': "&&", 'or': "||"}
3188
3189     def generate_evaluation_code(self, code):
3190         self.operand1.generate_evaluation_code(code)
3191         test_result = self.generate_operand1_test(code)
3192         if self.operator == 'and':
3193             sense = ""
3194         else:
3195             sense = "!"
3196         code.putln(
3197             "if (%s%s) {" % (
3198                 sense,
3199                 test_result))
3200         self.operand1.generate_disposal_code(code)
3201         self.operand2.generate_evaluation_code(code)
3202         code.putln(
3203             "}")
3204     
3205     def generate_operand1_test(self, code):
3206         #  Generate code to test the truth of the first operand.
3207         if self.type.is_pyobject:
3208             test_result = self.temp_bool.result_code
3209             code.putln(
3210                 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3211                     test_result,
3212                     self.operand1.py_result(),
3213                     code.error_goto_if_neg(test_result, self.pos)))
3214         else:
3215             test_result = self.operand1.result_code
3216         return test_result
3217
3218
3219 class CondExprNode(ExprNode):
3220     #  Short-circuiting conditional expression.
3221     #
3222     #  test        ExprNode
3223     #  true_val    ExprNode
3224     #  false_val   ExprNode
3225     
3226     temp_bool = None
3227     
3228     subexprs = ['test', 'true_val', 'false_val']
3229     
3230     def analyse_types(self, env):
3231         self.test.analyse_types(env)
3232         self.test = self.test.coerce_to_boolean(env)
3233         self.true_val.analyse_types(env)
3234         self.false_val.analyse_types(env)
3235         self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
3236         if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
3237             self.true_val = self.true_val.coerce_to(self.type, env)
3238             self.false_val = self.false_val.coerce_to(self.type, env)
3239         # must be tmp variables so they can share a result
3240         self.true_val = self.true_val.coerce_to_temp(env)
3241         self.false_val = self.false_val.coerce_to_temp(env)
3242         self.is_temp = 1
3243         if self.type == PyrexTypes.error_type:
3244             self.type_error()
3245     
3246     def allocate_temps(self, env, result_code = None):
3247         #  We only ever evaluate one side, and this is 
3248         #  after evaluating the truth value, so we may
3249         #  use an allocation strategy here which results in
3250         #  this node and both its operands sharing the same
3251         #  result variable. This allows us to avoid some 
3252         #  assignments and increfs/decrefs that would otherwise
3253         #  be necessary.
3254         self.allocate_temp(env, result_code)
3255         self.test.allocate_temps(env, result_code)
3256         self.true_val.allocate_temps(env, self.result_code)
3257         self.false_val.allocate_temps(env, self.result_code)
3258         #  We haven't called release_temp on either value,
3259         #  because although they are temp nodes, they don't own 
3260         #  their result variable. And because they are temp
3261         #  nodes, any temps in their subnodes will have been
3262         #  released before their allocate_temps returned.
3263         #  Therefore, they contain no temp vars that need to
3264         #  be released.
3265         
3266     def compute_result_type(self, type1, type2):
3267         if type1 == type2:
3268             return type1
3269         elif type1.is_numeric and type2.is_numeric:
3270             return PyrexTypes.widest_numeric_type(type1, type2)
3271         elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
3272             return type2
3273         elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
3274             return type1
3275         elif type1.is_pyobject or type2.is_pyobject:
3276             return py_object_type
3277         elif type1.assignable_from(type2):
3278             return type1
3279         elif type2.assignable_from(type1):
3280             return type2
3281         else:
3282             return PyrexTypes.error_type
3283         
3284     def type_error(self):
3285         if not (self.true_val.type.is_error or self.false_val.type.is_error):
3286             error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
3287                 (self.true_val.type, self.false_val.type))
3288         self.type = PyrexTypes.error_type
3289     
3290     def check_const(self):
3291         self.test.check_const()
3292         self.true_val.check_const()
3293         self.false_val.check_const()
3294     
3295     def generate_evaluation_code(self, code):
3296         self.test.generate_evaluation_code(code)
3297         code.putln("if (%s) {" % self.test.result_code )
3298         self.true_val.generate_evaluation_code(code)
3299         code.putln("} else {")
3300         self.false_val.generate_evaluation_code(code)
3301         code.putln("}")
3302         self.test.generate_disposal_code(code)
3303
3304 richcmp_constants = {
3305     "<" : "Py_LT",
3306     "<=": "Py_LE",
3307     "==": "Py_EQ",
3308     "!=": "Py_NE",
3309     "<>": "Py_NE",
3310     ">" : "Py_GT",
3311     ">=": "Py_GE",
3312 }
3313
3314 class CmpNode:
3315     #  Mixin class containing code common to PrimaryCmpNodes
3316     #  and CascadedCmpNodes.
3317     
3318     def cascaded_compile_time_value(self, operand1, denv):
3319         func = get_compile_time_binop(self)
3320         operand2 = self.operand2.compile_time_value(denv)
3321         try:
3322             result = func(operand1, operand2)
3323         except Exception, e:
3324             self.compile_time_value_error(e)
3325             result = None
3326         if result:
3327             cascade = self.cascade
3328             if cascade:
3329                 result = result and cascade.compile_time_value(operand2, denv)
3330         return result
3331
3332     def is_python_comparison(self):
3333         return (self.has_python_operands()
3334             or (self.cascade and self.cascade.is_python_comparison())
3335             or self.operator in ('in', 'not_in'))
3336
3337     def is_python_result(self):
3338         return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
3339             or (self.cascade and self.cascade.is_python_result()))
3340
3341     def check_types(self, env, operand1, op, operand2):
3342         if not self.types_okay(operand1, op, operand2):
3343             error(self.pos, "Invalid types for '%s' (%s, %s)" %
3344                 (self.operator, operand1.type, operand2.type))
3345     
3346     def types_okay(self, operand1, op, operand2):
3347         type1 = operand1.type
3348         type2 = operand2.type
3349         if type1.is_error or type2.is_error:
3350             return 1
3351         if type1.is_pyobject: # type2 will be, too
3352             return 1
3353         elif type1.is_ptr or type1.is_array:
3354             return type1.is_null_ptr or type2.is_null_ptr \
3355                 or ((type2.is_ptr or type2.is_array)
3356                     and type1.base_type.same_as(type2.base_type))
3357         elif ((type1.is_numeric and type2.is_numeric
3358                     or type1.is_enum and (type1 is type2 or type2.is_int)
3359                     or type1.is_int and type2.is_enum)
3360                 and op not in ('is', 'is_not')):
3361             return 1
3362         else:
3363             return type1.is_cfunction and type1.is_cfunction and type1 == type2
3364
3365     def generate_operation_code(self, code, result_code, 
3366             operand1, op , operand2):
3367         if self.type is PyrexTypes.py_object_type:
3368             coerce_result = "__Pyx_PyBool_FromLong"
3369         else:
3370             coerce_result = ""
3371         if 'not' in op: negation = "!"
3372         else: negation = ""
3373         if op == 'in' or op == 'not_in':
3374             code.putln(
3375                 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
3376                     result_code, 
3377                     coerce_result, 
3378                     negation,
3379                     operand2.py_result(), 
3380                     operand1.py_result(), 
3381                     code.error_goto_if_neg(result_code, self.pos)))
3382         elif (operand1.type.is_pyobject
3383             and op not in ('is', 'is_not')):
3384                 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
3385                         result_code, 
3386                         operand1.py_result(), 
3387                         operand2.py_result(), 
3388                         richcmp_constants[op],
3389                         code.error_goto_if_null(result_code, self.pos)))
3390         else:
3391             type1 = operand1.type
3392             type2 = operand2.type
3393             if (type1.is_extension_type or type2.is_extension_type) \
3394                     and not type1.same_as(type2):
3395                 common_type = py_object_type
3396             elif type1.is_numeric:
3397                 common_type = PyrexTypes.widest_numeric_type(type1, type2)
3398             else:
3399                 common_type = type1
3400             code1 = operand1.result_as(common_type)
3401             code2 = operand2.result_as(common_type)
3402             code.putln("%s = %s(%s %s %s);" % (
3403                 result_code, 
3404                 coerce_result, 
3405                 code1, 
3406                 self.c_operator(op), 
3407                 code2))
3408
3409     def c_operator(self, op):
3410         if op == 'is':
3411             return "=="
3412         elif op == 'is_not':
3413             return "!="
3414         else:
3415             return op
3416     
3417
3418 class PrimaryCmpNode(ExprNode, CmpNode):
3419     #  Non-cascaded comparison or first comparison of
3420     #  a cascaded sequence.
3421     #
3422     #  operator      string
3423     #  operand1      ExprNode
3424     #  operand2      ExprNode
3425     #  cascade       CascadedCmpNode
3426     
3427     #  We don't use the subexprs mechanism, because
3428     #  things here are too complicated for it to handle.
3429     #  Instead, we override all the framework methods
3430     #  which use it.
3431     
3432     child_attrs = ['operand1', 'operand2', 'cascade']
3433     
3434     cascade = None
3435     
3436     def compile_time_value(self, denv):
3437         operand1 = self.operand1.compile_time_value(denv)
3438         return self.cascaded_compile_time_value(operand1, denv)
3439
3440     def analyse_types(self, env):
3441         self.operand1.analyse_types(env)
3442         self.operand2.analyse_types(env)
3443         if self.cascade:
3444             self.cascade.analyse_types(env, self.operand2)
3445         self.is_pycmp = self.is_python_comparison()
3446         if self.is_pycmp:
3447             self.coerce_operands_to_pyobjects(env)
3448         if self.has_int_operands():
3449             self.coerce_chars_to_ints(env)
3450         if self.cascade:
3451             #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
3452             self.operand2 = self.operand2.coerce_to_simple(env)
3453             self.cascade.coerce_cascaded_operands_to_temp(env)
3454         self.check_operand_types(env)
3455         if self.is_python_result():
3456             self.type = PyrexTypes.py_object_type
3457         else:
3458             self.type = PyrexTypes.c_bint_type
3459         cdr = self.cascade
3460         while cdr:
3461             cdr.type = self.type
3462             cdr = cdr.cascade
3463         if self.is_pycmp or self.cascade:
3464             self.is_temp = 1
3465     
3466     def check_operand_types(self, env):
3467         self.check_types(env, 
3468             self.operand1, self.operator, self.operand2)
3469         if self.cascade:
3470             self.cascade.check_operand_types(env, self.operand2)
3471     
3472     def has_python_operands(self):
3473         return (self.operand1.type.is_pyobject
3474             or self.operand2.type.is_pyobject)
3475             
3476     def coerce_operands_to_pyobjects(self, env):
3477         self.operand1 = self.operand1.coerce_to_pyobject(env)
3478         self.operand2 = self.operand2.coerce_to_pyobject(env)
3479         if self.cascade:
3480             self.cascade.coerce_operands_to_pyobjects(env)
3481         
3482     def has_int_operands(self):
3483         return (self.operand1.type.is_int or self.operand2.type.is_int) \
3484            or (self.cascade and self.cascade.has_int_operands())
3485     
3486     def coerce_chars_to_ints(self, env):
3487         if self.operand1.type.is_string:
3488             self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
3489         if self.operand2.type.is_string:
3490             self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3491         if self.cascade:
3492             self.cascade.coerce_chars_to_ints(env)
3493     
3494     def allocate_subexpr_temps(self, env):
3495         self.operand1.allocate_temps(env)
3496         self.operand2.allocate_temps(env)
3497         if self.cascade:
3498             self.cascade.allocate_subexpr_temps(env)
3499     
3500     def release_subexpr_temps(self, env):
3501         self.operand1.release_temp(env)
3502         self.operand2.release_temp(env)
3503         if self.cascade:
3504             self.cascade.release_subexpr_temps(env)
3505     
3506     def check_const(self):
3507         self.operand1.check_const()
3508         self.operand2.check_const()
3509         if self.cascade:
3510             self.not_const()
3511
3512     def calculate_result_code(self):
3513         return "(%s %s %s)" % (
3514             self.operand1.result_code,
3515             self.c_operator(self.operator),
3516             self.operand2.result_code)
3517     
3518     def generate_evaluation_code(self, code):
3519         self.operand1.generate_evaluation_code(code)
3520         self.operand2.generate_evaluation_code(code)
3521         if self.is_temp:
3522             self.generate_operation_code(code, self.result_code, 
3523                 self.operand1, self.operator, self.operand2)
3524             if self.cascade:
3525                 self.cascade.generate_evaluation_code(code,
3526                     self.result_code, self.operand2)
3527             self.operand1.generate_disposal_code(code)
3528             self.operand2.generate_disposal_code(code)
3529     
3530     def generate_subexpr_disposal_code(self, code):
3531         #  If this is called, it is a non-cascaded cmp,
3532         #  so only need to dispose of the two main operands.
3533         self.operand1.generate_disposal_code(code)
3534         self.operand2.generate_disposal_code(code)
3535         
3536     def annotate(self, code):
3537         self.operand1.annotate(code)
3538         self.operand2.annotate(code)
3539         if self.cascade:
3540             self.cascade.annotate(code)
3541
3542
3543 class CascadedCmpNode(Node, CmpNode):
3544     #  A CascadedCmpNode is not a complete expression node. It 
3545     #  hangs off the side of another comparison node, shares 
3546     #  its left operand with that node, and shares its result 
3547     #  with the PrimaryCmpNode at the head of the chain.
3548     #
3549     #  operator      string
3550     #  operand2      ExprNode
3551     #  cascade       CascadedCmpNode
3552
3553     child_attrs = ['operand2', 'cascade']
3554
3555     cascade = None
3556     
3557     def analyse_types(self, env, operand1):
3558         self.operand2.analyse_types(env)
3559         if self.cascade:
3560             self.cascade.analyse_types(env, self.operand2)
3561     
3562     def check_operand_types(self, env, operand1):
3563         self.check_types(env, 
3564             operand1, self.operator, self.operand2)
3565         if self.cascade:
3566             self.cascade.check_operand_types(env, self.operand2)
3567     
3568     def has_python_operands(self):
3569         return self.operand2.type.is_pyobject
3570         
3571     def coerce_operands_to_pyobjects(self, env):
3572         self.operand2 = self.operand2.coerce_to_pyobject(env)
3573         if self.cascade:
3574             self.cascade.coerce_operands_to_pyobjects(env)
3575
3576     def has_int_operands(self):
3577         return self.operand2.type.is_int
3578         
3579     def coerce_chars_to_ints(self, env):
3580         if self.operand2.type.is_string:
3581             self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3582
3583     def coerce_cascaded_operands_to_temp(self, env):
3584         if self.cascade:
3585             #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
3586             self.operand2 = self.operand2.coerce_to_simple(env)
3587             self.cascade.coerce_cascaded_operands_to_temp(env)
3588     
3589     def allocate_subexpr_temps(self, env):
3590         self.operand2.allocate_temps(env)
3591         if self.cascade:
3592             self.cascade.allocate_subexpr_temps(env)
3593     
3594     def release_subexpr_temps(self, env):
3595         self.operand2.release_temp(env)
3596         if self.cascade:
3597             self.cascade.release_subexpr_temps(env)
3598     
3599     def generate_evaluation_code(self, code, result, operand1):
3600         if self.type.is_pyobject:
3601             code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
3602         else:
3603             code.putln("if (%s) {" % result)
3604         self.operand2.generate_evaluation_code(code)
3605         self.generate_operation_code(code, result, 
3606             operand1, self.operator, self.operand2)
3607         if self.cascade:
3608             self.cascade.generate_evaluation_code(
3609                 code, result, self.operand2)
3610         # Cascaded cmp result is always temp
3611         self.operand2.generate_disposal_code(code)
3612         code.putln("}")
3613
3614     def annotate(self, code):
3615         self.operand2.annotate(code)
3616         if self.cascade:
3617             self.cascade.annotate(code)
3618
3619
3620 binop_node_classes = {
3621     "or":               BoolBinopNode,
3622     "and":      BoolBinopNode,
3623     "|":                IntBinopNode,
3624     "^":                IntBinopNode,
3625     "&":                IntBinopNode,
3626     "<<":               IntBinopNode,
3627     ">>":               IntBinopNode,
3628     "+":                AddNode,
3629     "-":                SubNode,
3630     "*":                MulNode,
3631     "/":                NumBinopNode,
3632     "//":               FloorDivNode,
3633     "%":                ModNode,
3634     "**":               PowNode
3635 }
3636
3637 def binop_node(pos, operator, operand1, operand2):
3638     # Construct binop node of appropriate class for 
3639     # given operator.
3640     return binop_node_classes[operator](pos, 
3641         operator = operator, 
3642         operand1 = operand1, 
3643         operand2 = operand2)
3644
3645 #-------------------------------------------------------------------
3646 #
3647 #  Coercion nodes
3648 #
3649 #  Coercion nodes are special in that they are created during
3650 #  the analyse_types phase of parse tree processing.
3651 #  Their __init__ methods consequently incorporate some aspects
3652 #  of that phase.
3653 #
3654 #-------------------------------------------------------------------
3655
3656 class CoercionNode(ExprNode):
3657     #  Abstract base class for coercion nodes.
3658     #
3659     #  arg       ExprNode       node being coerced
3660     
3661     subexprs = ['arg']
3662     
3663     def __init__(self, arg):
3664         self.pos = arg.pos
3665         self.arg = arg
3666         if debug_coercion:
3667             print("%s Coercing %s" % (self, self.arg))
3668             
3669     def annotate(self, code):
3670         self.arg.annotate(code)
3671         if self.arg.type != self.type:
3672             file, line, col = self.pos
3673             code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
3674
3675
3676 class CastNode(CoercionNode):
3677     #  Wrap a node in a C type cast.
3678     
3679     def __init__(self, arg, new_type):
3680         CoercionNode.__init__(self, arg)
3681         self.type = new_type
3682     
3683     def calculate_result_code(self):
3684         return self.arg.result_as(self.type)
3685
3686     def generate_result_code(self, code):
3687         self.arg.generate_result_code(code)
3688
3689
3690 class PyTypeTestNode(CoercionNode):
3691     #  This node is used to check that a generic Python
3692     #  object is an instance of a particular extension type.
3693     #  This node borrows the result of its argument node.
3694
3695     def __init__(self, arg, dst_type, env):
3696         #  The arg is know to be a Python object, and
3697         #  the dst_type is known to be an extension type.
3698         assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
3699         CoercionNode.__init__(self, arg)
3700         self.type = dst_type
3701         self.result_ctype = arg.ctype()
3702         env.use_utility_code(type_test_utility_code)
3703     
3704     def analyse_types(self, env):
3705         pass
3706     
3707     def result_in_temp(self):
3708         return self.arg.result_in_temp()
3709     
3710     def is_ephemeral(self):
3711         return self.arg.is_ephemeral()
3712     
3713     def calculate_result_code(self):
3714         return self.arg.result_code
3715     
3716     def generate_result_code(self, code):
3717         if self.type.typeobj_is_available():
3718             code.putln(
3719                 "if (!(%s)) %s" % (
3720                     self.type.type_test_code(self.arg.py_result()),
3721                     code.error_goto(self.pos)))
3722         else:
3723             error(self.pos, "Cannot test type of extern C class "
3724                 "without type object name specification")
3725                 
3726     def generate_post_assignment_code(self, code):
3727         self.arg.generate_post_assignment_code(code)
3728                 
3729                 
3730 class CoerceToPyTypeNode(CoercionNode):
3731     #  This node is used to convert a C data type
3732     #  to a Python object.
3733
3734     def __init__(self, arg, env):
3735         CoercionNode.__init__(self, arg)
3736         self.type = py_object_type
3737         self.is_temp = 1
3738         if not arg.type.to_py_function:
3739             error(arg.pos,
3740                 "Cannot convert '%s' to Python object" % arg.type)
3741     
3742     def generate_result_code(self, code):
3743         function = self.arg.type.to_py_function
3744         code.putln('%s = %s(%s); %s' % (
3745             self.result_code, 
3746             function, 
3747             self.arg.result_code, 
3748             code.error_goto_if_null(self.result_code, self.pos)))
3749
3750
3751 class CoerceFromPyTypeNode(CoercionNode):
3752     #  This node is used to convert a Python object
3753     #  to a C data type.
3754
3755     def __init__(self, result_type, arg, env):
3756         CoercionNode.__init__(self, arg)
3757         self.type = result_type
3758         self.is_temp = 1
3759         if not result_type.from_py_function:
3760             error(arg.pos,
3761                 "Cannot convert Python object to '%s'" % result_type)
3762         if self.type.is_string and self.arg.is_ephemeral():
3763             error(arg.pos,
3764                 "Obtaining char * from temporary Python value")
3765     
3766     def generate_result_code(self, code):
3767         function = self.type.from_py_function
3768         operand = self.arg.py_result()
3769         rhs = "%s(%s)" % (function, operand)
3770         if self.type.is_enum:
3771             rhs = typecast(self.type, c_long_type, rhs)
3772         code.putln('%s = %s; %s' % (
3773             self.result_code, 
3774             rhs,
3775             code.error_goto_if(self.type.error_condition(self.result_code), self.pos)))
3776
3777
3778 class CoerceToBooleanNode(CoercionNode):
3779     #  This node is used when a result needs to be used
3780     #  in a boolean context.
3781     
3782     def __init__(self, arg, env):
3783         CoercionNode.__init__(self, arg)
3784         self.type = PyrexTypes.c_bint_type
3785         if arg.type.is_pyobject:
3786             self.is_temp = 1
3787     
3788     def check_const(self):
3789         if self.is_temp:
3790             self.not_const()
3791         self.arg.check_const()
3792     
3793     def calculate_result_code(self):
3794         return "(%s != 0)" % self.arg.result_code
3795
3796     def generate_result_code(self, code):
3797         if self.arg.type.is_pyobject:
3798             code.putln(
3799                 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3800                     self.result_code, 
3801                     self.arg.py_result(), 
3802                     code.error_goto_if_neg(self.result_code, self.pos)))
3803
3804
3805 class CoerceToTempNode(CoercionNode):
3806     #  This node is used to force the result of another node
3807     #  to be stored in a temporary. It is only used if the
3808     #  argument node's result is not already in a temporary.
3809
3810     def __init__(self, arg, env):
3811         CoercionNode.__init__(self, arg)
3812         self.type = self.arg.type
3813         self.is_temp = 1
3814         if self.type.is_pyobject:
3815             self.result_ctype = py_object_type
3816     
3817     def generate_result_code(self, code):
3818         #self.arg.generate_evaluation_code(code) # Already done
3819         # by generic generate_subexpr_evaluation_code!
3820         code.putln("%s = %s;" % (
3821             self.result_code, self.arg.result_as(self.ctype())))
3822         if self.type.is_pyobject:
3823             code.put_incref(self.result_code, self.ctype())
3824
3825
3826 class CloneNode(CoercionNode):
3827     #  This node is employed when the result of another node needs
3828     #  to be used multiple times. The argument node's result must
3829     #  be in a temporary. This node "borrows" the result from the
3830     #  argument node, and does not generate any evaluation or
3831     #  disposal code for it. The original owner of the argument 
3832     #  node is responsible for doing those things.
3833     
3834     subexprs = [] # Arg is not considered a subexpr
3835     
3836     def __init__(self, arg):
3837         CoercionNode.__init__(self, arg)
3838         if hasattr(arg, 'type'):
3839             self.type = arg.type
3840             self.result_ctype = arg.result_ctype
3841         if hasattr(arg, 'entry'):
3842             self.entry = arg.entry
3843     
3844     def calculate_result_code(self):
3845         return self.arg.result_code
3846         
3847     def analyse_types(self, env):
3848         self.type = self.arg.type
3849         self.result_ctype = self.arg.result_ctype
3850         self.is_temp = 1
3851         if hasattr(self.arg, 'entry'):
3852             self.entry = self.arg.entry
3853     
3854     #def result_as_extension_type(self):
3855     #   return self.arg.result_as_extension_type()
3856     
3857     def generate_evaluation_code(self, code):
3858         pass
3859
3860     def generate_result_code(self, code):
3861         pass
3862         
3863     def generate_disposal_code(self, code):
3864         pass
3865                 
3866     def allocate_temps(self, env):
3867         self.result_code = self.calculate_result_code()
3868         
3869     def release_temp(self, env):
3870         pass
3871     
3872 #------------------------------------------------------------------------------------
3873 #
3874 #  Runtime support code
3875 #
3876 #------------------------------------------------------------------------------------
3877
3878 get_name_interned_utility_code = [
3879 """
3880 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
3881 ""","""
3882 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
3883     PyObject *result;
3884     result = PyObject_GetAttr(dict, name);
3885     if (!result)
3886         PyErr_SetObject(PyExc_NameError, name);
3887     return result;
3888 }
3889 """]
3890
3891 #------------------------------------------------------------------------------------
3892
3893 import_utility_code = [
3894 """
3895 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
3896 ""","""
3897 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
3898     PyObject *__import__ = 0;
3899     PyObject *empty_list = 0;
3900     PyObject *module = 0;
3901     PyObject *global_dict = 0;
3902     PyObject *empty_dict = 0;
3903     PyObject *list;
3904     __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
3905     if (!__import__)
3906         goto bad;
3907     if (from_list)
3908         list = from_list;
3909     else {
3910         empty_list = PyList_New(0);
3911         if (!empty_list)
3912             goto bad;
3913         list = empty_list;
3914     }
3915     global_dict = PyModule_GetDict(%(GLOBALS)s);
3916     if (!global_dict)
3917         goto bad;
3918     empty_dict = PyDict_New();
3919     if (!empty_dict)
3920         goto bad;
3921     module = PyObject_CallFunction(__import__, "OOOO",
3922         name, global_dict, empty_dict, list);
3923 bad:
3924     Py_XDECREF(empty_list);
3925     Py_XDECREF(__import__);
3926     Py_XDECREF(empty_dict);
3927     return module;
3928 }
3929 """ % {
3930     "BUILTINS": Naming.builtins_cname,
3931     "GLOBALS":  Naming.module_cname,
3932 }]
3933
3934 #------------------------------------------------------------------------------------
3935
3936 get_exception_utility_code = [
3937 """
3938 static PyObject *__Pyx_GetExcValue(void); /*proto*/
3939 ""","""
3940 static PyObject *__Pyx_GetExcValue(void) {
3941     PyObject *type = 0, *value = 0, *tb = 0;
3942     PyObject *tmp_type, *tmp_value, *tmp_tb;
3943     PyObject *result = 0;
3944     PyThreadState *tstate = PyThreadState_Get();
3945     PyErr_Fetch(&type, &value, &tb);
3946     PyErr_NormalizeException(&type, &value, &tb);
3947     if (PyErr_Occurred())
3948         goto bad;
3949     if (!value) {
3950         value = Py_None;
3951         Py_INCREF(value);
3952     }
3953     tmp_type = tstate->exc_type;
3954     tmp_value = tstate->exc_value;
3955     tmp_tb = tstate->exc_traceback;
3956     tstate->exc_type = type;
3957     tstate->exc_value = value;
3958     tstate->exc_traceback = tb;
3959     /* Make sure tstate is in a consistent state when we XDECREF
3960     these objects (XDECREF may run arbitrary code). */
3961     Py_XDECREF(tmp_type);
3962     Py_XDECREF(tmp_value);
3963     Py_XDECREF(tmp_tb);
3964     result = value;
3965     Py_XINCREF(result);
3966     type = 0;
3967     value = 0;
3968     tb = 0;
3969 bad:
3970     Py_XDECREF(type);
3971     Py_XDECREF(value);
3972     Py_XDECREF(tb);
3973     return result;
3974 }
3975 """]
3976
3977 #------------------------------------------------------------------------------------
3978
3979 unpacking_utility_code = [
3980 """
3981 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
3982 static int __Pyx_EndUnpack(PyObject *); /*proto*/
3983 ""","""
3984 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
3985     PyObject *item;
3986     if (!(item = PyIter_Next(iter))) {
3987         if (!PyErr_Occurred()) {
3988             PyErr_Format(PyExc_ValueError,
3989                 #if PY_VERSION_HEX < 0x02050000
3990                     "need more than %d values to unpack", (int)index);
3991                 #else
3992                     "need more than %zd values to unpack", index);
3993                 #endif
3994         }
3995     }
3996     return item;
3997 }
3998
3999 static int __Pyx_EndUnpack(PyObject *iter) {
4000     PyObject *item;
4001     if ((item = PyIter_Next(iter))) {
4002         Py_DECREF(item);
4003         PyErr_SetString(PyExc_ValueError, "too many values to unpack");
4004         return -1;
4005     }
4006     else if (!PyErr_Occurred())
4007         return 0;
4008     else
4009         return -1;
4010 }
4011 """]
4012
4013 #------------------------------------------------------------------------------------
4014
4015 type_test_utility_code = [
4016 """
4017 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
4018 ""","""
4019 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
4020     if (!type) {
4021         PyErr_Format(PyExc_SystemError, "Missing type object");
4022         return 0;
4023     }
4024     if (obj == Py_None || PyObject_TypeCheck(obj, type))
4025         return 1;
4026     PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
4027         Py_TYPE(obj)->tp_name, type->tp_name);
4028     return 0;
4029 }
4030 """]
4031
4032 #------------------------------------------------------------------------------------
4033
4034 create_class_utility_code = [
4035 """
4036 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
4037 ""","""
4038 static PyObject *__Pyx_CreateClass(
4039     PyObject *bases, PyObject *dict, PyObject *name, char *modname)
4040 {
4041     PyObject *py_modname;
4042     PyObject *result = 0;
4043
4044     #if PY_MAJOR_VERSION < 3
4045     py_modname = PyString_FromString(modname);
4046     #else
4047     py_modname = PyUnicode_FromString(modname);
4048     #endif
4049     if (!py_modname)
4050         goto bad;
4051     if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
4052         goto bad;
4053     #if PY_MAJOR_VERSION < 3
4054     result = PyClass_New(bases, dict, name);
4055     #else
4056     result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
4057     #endif
4058 bad:
4059     Py_XDECREF(py_modname);
4060     return result;
4061 }
4062 """]
4063
4064 #------------------------------------------------------------------------------------
4065
4066 cpp_exception_utility_code = [
4067 """
4068 #ifndef __Pyx_CppExn2PyErr
4069 static void __Pyx_CppExn2PyErr() {
4070   try {
4071     if (PyErr_Occurred())
4072       ; // let the latest Python exn pass through and ignore the current one
4073     else
4074       throw;
4075   } catch (const std::out_of_range& exn) {
4076     // catch out_of_range explicitly so the proper Python exn may be raised
4077     PyErr_SetString(PyExc_IndexError, exn.what());
4078   } catch (const std::exception& exn) {
4079     PyErr_SetString(PyExc_RuntimeError, exn.what());
4080   }
4081   catch (...)
4082   {
4083     PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
4084   }
4085 }
4086 #endif
4087 """,""]
4088
4089 #------------------------------------------------------------------------------------
4090
4091 append_utility_code = [
4092 """
4093 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
4094     if (likely(PyList_CheckExact(L))) {
4095         if (PyList_Append(L, x) < 0) return NULL;
4096         Py_INCREF(Py_None);
4097         return Py_None; // this is just to have an accurate signature
4098     }
4099     else {
4100         return PyObject_CallMethod(L, "append", "(O)", x);
4101     }
4102 }
4103 """,""
4104 ]