Fixing up flawed fix for #303
[cython.git] / Cython / Compiler / Nodes.py
1 #
2 #   Pyrex - Parse tree nodes
3 #
4
5 import sys, os, time, copy
6
7 import Code
8 import Builtin
9 from Errors import error, warning, InternalError
10 import Naming
11 import PyrexTypes
12 import TypeSlots
13 from PyrexTypes import py_object_type, error_type, CTypedefType, CFuncType
14 from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \
15     StructOrUnionScope, PyClassScope, CClassScope
16 from Cython.Utils import open_new_file, replace_suffix, UtilityCode
17 from StringEncoding import EncodedString, escape_byte_string, split_docstring
18 import Options
19 import ControlFlow
20 import DebugFlags
21
22 absolute_path_length = 0
23
24 def relative_position(pos):
25     """
26     We embed the relative filename in the generated C file, since we
27     don't want to have to regnerate and compile all the source code
28     whenever the Python install directory moves (which could happen,
29     e.g,. when distributing binaries.)
30     
31     INPUT:
32         a position tuple -- (absolute filename, line number column position)
33
34     OUTPUT:
35         relative filename
36         line number
37
38     AUTHOR: William Stein
39     """
40     global absolute_path_length
41     if absolute_path_length==0:
42         absolute_path_length = len(os.path.abspath(os.getcwd())) 
43     return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
44
45 def embed_position(pos, docstring):
46     if not Options.embed_pos_in_docstring:
47         return docstring
48     pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
49     if docstring is None:
50         # unicode string
51         return EncodedString(pos_line)
52
53     # make sure we can encode the filename in the docstring encoding
54     # otherwise make the docstring a unicode string
55     encoding = docstring.encoding
56     if encoding is not None:
57         try:
58             encoded_bytes = pos_line.encode(encoding)
59         except UnicodeEncodeError:
60             encoding = None
61
62     if not docstring:
63         # reuse the string encoding of the original docstring
64         doc = EncodedString(pos_line)
65     else:
66         doc = EncodedString(pos_line + u'\n' + docstring)
67     doc.encoding = encoding
68     return doc
69
70
71 from Code import CCodeWriter
72 from types import FunctionType
73
74 def write_func_call(func):
75     def f(*args, **kwds):
76         if len(args) > 1 and isinstance(args[1], CCodeWriter):
77             # here we annotate the code with this function call
78             # but only if new code is generated
79             node, code = args[:2]
80             marker = '                    /* %s -> %s.%s %s */' % (
81                     ' ' * code.call_level,
82                     node.__class__.__name__, 
83                     func.__name__, 
84                     node.pos[1:])
85             pristine = code.buffer.stream.tell()
86             code.putln(marker)
87             start = code.buffer.stream.tell()
88             code.call_level += 4
89             res = func(*args, **kwds)
90             code.call_level -= 4
91             if start == code.buffer.stream.tell():
92                 code.buffer.stream.seek(pristine)
93             else:
94                 marker = marker.replace('->', '<-')
95                 code.putln(marker)
96             return res
97         else:
98             return func(*args, **kwds)
99     return f
100
101 class VerboseCodeWriter(type):
102     # Set this as a metaclass to trace function calls in code.
103     # This slows down code generation and makes much larger files. 
104     def __new__(cls, name, bases, attrs):
105         attrs = dict(attrs)
106         for mname, m in attrs.items():
107             if isinstance(m, FunctionType):
108                 attrs[mname] = write_func_call(m)
109         return super(VerboseCodeWriter, cls).__new__(cls, name, bases, attrs)
110
111
112 class Node(object):
113     #  pos         (string, int, int)   Source file position
114     #  is_name     boolean              Is a NameNode
115     #  is_literal  boolean              Is a ConstNode
116
117     if DebugFlags.debug_trace_code_generation:
118         __metaclass__ = VerboseCodeWriter
119     
120     is_name = 0
121     is_literal = 0
122     temps = None
123
124     # All descandants should set child_attrs to a list of the attributes
125     # containing nodes considered "children" in the tree. Each such attribute
126     # can either contain a single node or a list of nodes. See Visitor.py.
127     child_attrs = None
128     
129     def __init__(self, pos, **kw):
130         self.pos = pos
131         self.__dict__.update(kw)
132     
133     gil_message = "Operation"
134
135     def gil_check(self, env):
136         if env.nogil:
137             self.gil_error()
138
139     def gil_error(self):
140         error(self.pos, "%s not allowed without gil" % self.gil_message)
141
142     def clone_node(self):
143         """Clone the node. This is defined as a shallow copy, except for member lists
144            amongst the child attributes (from get_child_accessors) which are also
145            copied. Lists containing child nodes are thus seen as a way for the node
146            to hold multiple children directly; the list is not treated as a seperate
147            level in the tree."""
148         result = copy.copy(self)
149         for attrname in result.child_attrs:
150             value = getattr(result, attrname)
151             if isinstance(value, list):
152                 setattr(result, attrname, [x for x in value])
153         return result
154     
155     
156     #
157     #  There are 4 phases of parse tree processing, applied in order to
158     #  all the statements in a given scope-block:
159     #
160     #  (0) analyse_control_flow
161     #        Create the control flow tree into which state can be asserted and
162     #        queried.
163     #
164     #  (1) analyse_declarations
165     #        Make symbol table entries for all declarations at the current
166     #        level, both explicit (def, cdef, etc.) and implicit (assignment
167     #        to an otherwise undeclared name).
168     #
169     #  (2) analyse_expressions
170     #         Determine the result types of expressions and fill in the
171     #         'type' attribute of each ExprNode. Insert coercion nodes into the
172     #         tree where needed to convert to and from Python objects. 
173     #         Allocate temporary locals for intermediate results. Fill
174     #         in the 'result_code' attribute of each ExprNode with a C code
175     #         fragment.
176     #
177     #  (3) generate_code
178     #         Emit C code for all declarations, statements and expressions.
179     #         Recursively applies the 3 processing phases to the bodies of
180     #         functions.
181     #
182     
183     def analyse_control_flow(self, env):
184         pass
185     
186     def analyse_declarations(self, env):
187         pass
188     
189     def analyse_expressions(self, env):
190         raise InternalError("analyse_expressions not implemented for %s" % \
191             self.__class__.__name__)
192     
193     def generate_code(self, code):
194         raise InternalError("generate_code not implemented for %s" % \
195             self.__class__.__name__)
196             
197     def annotate(self, code):
198         # mro does the wrong thing
199         if isinstance(self, BlockNode):
200             self.body.annotate(code)
201             
202     def end_pos(self):
203         try:
204             return self._end_pos
205         except AttributeError:
206             pos = self.pos
207             if not self.child_attrs:
208                 self._end_pos = pos
209                 return pos
210             for attr in self.child_attrs:
211                 child = getattr(self, attr)
212                 # Sometimes lists, sometimes nodes
213                 if child is None:
214                     pass
215                 elif isinstance(child, list):
216                     for c in child:
217                         pos = max(pos, c.end_pos())
218                 else:
219                     pos = max(pos, child.end_pos())
220             self._end_pos = pos
221             return pos
222
223     def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
224         if cutoff == 0:
225             return "<...nesting level cutoff...>"
226         if encountered is None:
227             encountered = set()
228         if id(self) in encountered:
229             return "<%s (%d) -- already output>" % (self.__class__.__name__, id(self))
230         encountered.add(id(self))
231         
232         def dump_child(x, level):
233             if isinstance(x, Node):
234                 return x.dump(level, filter_out, cutoff-1, encountered)
235             elif isinstance(x, list):
236                 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
237             else:
238                 return repr(x)
239             
240         
241         attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
242         if len(attrs) == 0:
243             return "<%s (%d)>" % (self.__class__.__name__, id(self))
244         else:
245             indent = "  " * level
246             res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
247             for key, value in attrs:
248                 res += "%s  %s: %s\n" % (indent, key, dump_child(value, level + 1))
249             res += "%s>" % indent
250             return res
251
252 class CompilerDirectivesNode(Node):
253     """
254     Sets compiler directives for the children nodes
255     """
256     #  directives     {string:value}  A dictionary holding the right value for
257     #                                 *all* possible directives.
258     #  body           Node
259     child_attrs = ["body"]
260
261     def analyse_control_flow(self, env):
262         old = env.directives
263         env.directives = self.directives
264         self.body.analyse_control_flow(env)
265         env.directives = old
266
267     def analyse_declarations(self, env):
268         old = env.directives
269         env.directives = self.directives
270         self.body.analyse_declarations(env)
271         env.directives = old
272     
273     def analyse_expressions(self, env):
274         old = env.directives
275         env.directives = self.directives
276         self.body.analyse_expressions(env)
277         env.directives = old
278
279     def generate_function_definitions(self, env, code):
280         env_old = env.directives
281         code_old = code.globalstate.directives
282         code.globalstate.directives = self.directives
283         self.body.generate_function_definitions(env, code)
284         env.directives = env_old
285         code.globalstate.directives = code_old
286             
287     def generate_execution_code(self, code):
288         old = code.globalstate.directives
289         code.globalstate.directives = self.directives
290         self.body.generate_execution_code(code)
291         code.globalstate.directives = old
292             
293     def annotate(self, code):
294         old = code.globalstate.directives
295         code.globalstate.directives = self.directives
296         self.body.annotate(code)
297         code.globalstate.directives = old
298         
299 class BlockNode(object):
300     #  Mixin class for nodes representing a declaration block.
301
302     def generate_const_definitions(self, env, code):
303         if env.const_entries:
304             for entry in env.const_entries:
305                 if not entry.is_interned:
306                     code.globalstate.add_const_definition(entry)
307
308     def generate_interned_string_decls(self, env, code):
309         entries = env.global_scope().new_interned_string_entries
310         if entries:
311             for entry in entries:
312                 code.globalstate.add_interned_string_decl(entry)
313             del entries[:]
314
315     def generate_py_string_decls(self, env, code):
316         if env is None:
317             return # earlier error
318         entries = env.pystring_entries
319         if entries:
320             for entry in entries:
321                 if not entry.is_interned:
322                     code.globalstate.add_py_string_decl(entry)
323
324     def generate_interned_num_decls(self, env, code):
325         #  Flush accumulated interned nums from the global scope
326         #  and generate declarations for them.
327         genv = env.global_scope()
328         entries = genv.interned_nums
329         if entries:
330             for entry in entries:
331                 code.globalstate.add_interned_num_decl(entry)
332             del entries[:]
333
334     def generate_cached_builtins_decls(self, env, code):
335         entries = env.global_scope().undeclared_cached_builtins
336         for entry in entries:
337             code.globalstate.add_cached_builtin_decl(entry)
338         del entries[:]
339         
340
341 class StatListNode(Node):
342     # stats     a list of StatNode
343     
344     child_attrs = ["stats"]
345
346     def create_analysed(pos, env, *args, **kw):
347         node = StatListNode(pos, *args, **kw)
348         return node # No node-specific analysis necesarry
349     create_analysed = staticmethod(create_analysed)
350     
351     def analyse_control_flow(self, env):
352         for stat in self.stats:
353             stat.analyse_control_flow(env)
354
355     def analyse_declarations(self, env):
356         #print "StatListNode.analyse_declarations" ###
357         for stat in self.stats:
358             stat.analyse_declarations(env)
359     
360     def analyse_expressions(self, env):
361         #print "StatListNode.analyse_expressions" ###
362         for stat in self.stats:
363             stat.analyse_expressions(env)
364     
365     def generate_function_definitions(self, env, code):
366         #print "StatListNode.generate_function_definitions" ###
367         for stat in self.stats:
368             stat.generate_function_definitions(env, code)
369             
370     def generate_execution_code(self, code):
371         #print "StatListNode.generate_execution_code" ###
372         for stat in self.stats:
373             code.mark_pos(stat.pos)
374             stat.generate_execution_code(code)
375             
376     def annotate(self, code):
377         for stat in self.stats:
378             stat.annotate(code)
379     
380
381 class StatNode(Node):
382     #
383     #  Code generation for statements is split into the following subphases:
384     #
385     #  (1) generate_function_definitions
386     #        Emit C code for the definitions of any structs,
387     #        unions, enums and functions defined in the current
388     #        scope-block.
389     #
390     #  (2) generate_execution_code
391     #        Emit C code for executable statements.
392     #
393     
394     def generate_function_definitions(self, env, code):
395         pass
396     
397     def generate_execution_code(self, code):
398         raise InternalError("generate_execution_code not implemented for %s" % \
399             self.__class__.__name__)
400
401
402 class CDefExternNode(StatNode):
403     #  include_file   string or None
404     #  body           StatNode
405     
406     child_attrs = ["body"]
407     
408     def analyse_declarations(self, env):
409         if self.include_file:
410             env.add_include_file(self.include_file)
411         old_cinclude_flag = env.in_cinclude
412         env.in_cinclude = 1
413         self.body.analyse_declarations(env)
414         env.in_cinclude = old_cinclude_flag
415     
416     def analyse_expressions(self, env):
417         pass
418     
419     def generate_execution_code(self, code):
420         pass
421
422     def annotate(self, code):
423         self.body.annotate(code)
424         
425
426 class CDeclaratorNode(Node):
427     # Part of a C declaration.
428     #
429     # Processing during analyse_declarations phase:
430     #
431     #   analyse
432     #      Returns (name, type) pair where name is the
433     #      CNameDeclaratorNode of the name being declared 
434     #      and type is the type it is being declared as.
435     #
436     #  calling_convention  string   Calling convention of CFuncDeclaratorNode
437     #                               for which this is a base 
438
439     child_attrs = []
440
441     calling_convention = ""
442
443
444 class CNameDeclaratorNode(CDeclaratorNode):
445     #  name    string             The Pyrex name being declared
446     #  cname   string or None     C name, if specified
447     #  default ExprNode or None   the value assigned on declaration
448     
449     child_attrs = ['default']
450     
451     default = None
452     
453     def analyse(self, base_type, env, nonempty = 0):
454         if nonempty and self.name == '':
455             # May have mistaken the name for the type. 
456             if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
457                 error(self.pos, "Missing argument name")
458             elif base_type.is_void:
459                 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
460             else:
461                 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
462                 base_type = py_object_type
463         self.type = base_type
464         return self, base_type
465         
466 class CPtrDeclaratorNode(CDeclaratorNode):
467     # base     CDeclaratorNode
468     
469     child_attrs = ["base"]
470
471     def analyse(self, base_type, env, nonempty = 0):
472         if base_type.is_pyobject:
473             error(self.pos,
474                 "Pointer base type cannot be a Python object")
475         ptr_type = PyrexTypes.c_ptr_type(base_type)
476         return self.base.analyse(ptr_type, env, nonempty = nonempty)
477         
478 class CArrayDeclaratorNode(CDeclaratorNode):
479     # base        CDeclaratorNode
480     # dimension   ExprNode
481
482     child_attrs = ["base", "dimension"]
483     
484     def analyse(self, base_type, env, nonempty = 0):
485         if self.dimension:
486             self.dimension.analyse_const_expression(env)
487             if not self.dimension.type.is_int:
488                 error(self.dimension.pos, "Array dimension not integer")
489             size = self.dimension.result()
490             try:
491                 size = int(size)
492             except ValueError:
493                 # runtime constant?
494                 pass
495         else:
496             size = None
497         if not base_type.is_complete():
498             error(self.pos,
499                 "Array element type '%s' is incomplete" % base_type)
500         if base_type.is_pyobject:
501             error(self.pos,
502                 "Array element cannot be a Python object")
503         if base_type.is_cfunction:
504             error(self.pos,
505                 "Array element cannot be a function")
506         array_type = PyrexTypes.c_array_type(base_type, size)
507         return self.base.analyse(array_type, env, nonempty = nonempty)
508
509
510 class CFuncDeclaratorNode(CDeclaratorNode):
511     # base             CDeclaratorNode
512     # args             [CArgDeclNode]
513     # has_varargs      boolean
514     # exception_value  ConstNode
515     # exception_check  boolean    True if PyErr_Occurred check needed
516     # nogil            boolean    Can be called without gil
517     # with_gil         boolean    Acquire gil around function body
518     
519     child_attrs = ["base", "args", "exception_value"]
520
521     overridable = 0
522     optional_arg_count = 0
523
524     def analyse(self, return_type, env, nonempty = 0):
525         if nonempty:
526             nonempty -= 1
527         func_type_args = []
528         for arg_node in self.args:
529             name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
530             name = name_declarator.name
531             if name_declarator.cname:
532                 error(self.pos, 
533                     "Function argument cannot have C name specification")
534             # Turn *[] argument into **
535             if type.is_array:
536                 type = PyrexTypes.c_ptr_type(type.base_type)
537             # Catch attempted C-style func(void) decl
538             if type.is_void:
539                 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
540 #            if type.is_pyobject and self.nogil:
541 #                error(self.pos,
542 #                    "Function with Python argument cannot be declared nogil")
543             func_type_args.append(
544                 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
545             if arg_node.default:
546                 self.optional_arg_count += 1
547             elif self.optional_arg_count:
548                 error(self.pos, "Non-default argument follows default argument")
549         
550         if self.optional_arg_count:
551             scope = StructOrUnionScope()
552             arg_count_member = '%sn' % Naming.pyrex_prefix
553             scope.declare_var(arg_count_member, PyrexTypes.c_int_type, self.pos)
554             for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
555                 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
556             struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
557             self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
558                                         kind = 'struct',
559                                         scope = scope,
560                                         typedef_flag = 0,
561                                         pos = self.pos,
562                                         cname = struct_cname)
563             self.op_args_struct.defined_in_pxd = 1
564             self.op_args_struct.used = 1
565         
566         exc_val = None
567         exc_check = 0
568         if self.exception_check == '+':
569             env.add_include_file('stdexcept')
570         if return_type.is_pyobject \
571             and (self.exception_value or self.exception_check) \
572             and self.exception_check != '+':
573                 error(self.pos,
574                     "Exception clause not allowed for function returning Python object")
575         else:
576             if self.exception_value:
577                 self.exception_value.analyse_const_expression(env)
578                 if self.exception_check == '+':
579                     exc_val_type = self.exception_value.type
580                     if not exc_val_type.is_error and \
581                           not exc_val_type.is_pyobject and \
582                           not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
583                         error(self.exception_value.pos,
584                             "Exception value must be a Python exception or cdef function with no arguments.")
585                     exc_val = self.exception_value
586                 else:
587                     exc_val = self.exception_value.result()
588                     if not return_type.assignable_from(self.exception_value.type):
589                         error(self.exception_value.pos,
590                             "Exception value incompatible with function return type")
591             exc_check = self.exception_check
592         if return_type.is_array:
593             error(self.pos,
594                 "Function cannot return an array")
595         if return_type.is_cfunction:
596             error(self.pos,
597                 "Function cannot return a function")
598         func_type = PyrexTypes.CFuncType(
599             return_type, func_type_args, self.has_varargs, 
600             optional_arg_count = self.optional_arg_count,
601             exception_value = exc_val, exception_check = exc_check,
602             calling_convention = self.base.calling_convention,
603             nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
604         if self.optional_arg_count:
605             func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
606         return self.base.analyse(func_type, env)
607
608
609 class CArgDeclNode(Node):
610     # Item in a function declaration argument list.
611     #
612     # base_type      CBaseTypeNode
613     # declarator     CDeclaratorNode
614     # not_none       boolean            Tagged with 'not None'
615     # default        ExprNode or None
616     # default_entry  Symtab.Entry       Entry for the variable holding the default value
617     # default_result_code string        cname or code fragment for default value
618     # is_self_arg    boolean            Is the "self" arg of an extension type method
619     # is_kw_only     boolean            Is a keyword-only argument
620
621     child_attrs = ["base_type", "declarator", "default"]
622
623     is_self_arg = 0
624     is_generic = 1
625     type = None
626     name_declarator = None
627
628     def analyse(self, env, nonempty = 0):
629         #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
630         if self.type is None:
631             # The parser may missinterpret names as types...
632             # We fix that here.
633             if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
634                 if nonempty:
635                     self.declarator.name = self.base_type.name
636                     self.base_type.name = None
637                     self.base_type.is_basic_c_type = False
638                 could_be_name = True
639             else:
640                 could_be_name = False
641             base_type = self.base_type.analyse(env, could_be_name = could_be_name)
642             if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
643                 self.declarator.name = self.base_type.arg_name
644             return self.declarator.analyse(base_type, env, nonempty = nonempty)
645         else:
646             return self.name_declarator, self.type
647
648     def annotate(self, code):
649         if self.default:
650             self.default.annotate(code)
651
652
653 class CBaseTypeNode(Node):
654     # Abstract base class for C base type nodes.
655     #
656     # Processing during analyse_declarations phase:
657     #
658     #   analyse
659     #     Returns the type.
660     
661     pass
662     
663 class CAnalysedBaseTypeNode(Node):
664     # type            type
665     
666     child_attrs = []
667     
668     def analyse(self, env, could_be_name = False):
669         return self.type
670
671 class CSimpleBaseTypeNode(CBaseTypeNode):
672     # name             string
673     # module_path      [string]     Qualifying name components
674     # is_basic_c_type  boolean
675     # signed           boolean
676     # longness         integer
677     # complex          boolean
678     # is_self_arg      boolean      Is self argument of C method
679
680     child_attrs = []
681     arg_name = None   # in case the argument name was interpreted as a type
682     
683     def analyse(self, env, could_be_name = False):
684         # Return type descriptor.
685         #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
686         type = None
687         if self.is_basic_c_type:
688             type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
689             if not type:
690                 error(self.pos, "Unrecognised type modifier combination")
691         elif self.name == "object" and not self.module_path:
692             type = py_object_type
693         elif self.name is None:
694             if self.is_self_arg and env.is_c_class_scope:
695                 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
696                 type = env.parent_type
697             else:
698                 type = py_object_type
699         else:
700             if self.module_path:
701                 scope = env.find_imported_module(self.module_path, self.pos)
702             else:
703                 scope = env
704             if scope:
705                 if scope.is_c_class_scope:
706                     scope = scope.global_scope()
707                 entry = scope.lookup(self.name)
708                 if entry and entry.is_type:
709                     type = entry.type
710                 elif could_be_name:
711                     if self.is_self_arg and env.is_c_class_scope:
712                         type = env.parent_type
713                     else:
714                         type = py_object_type
715                     self.arg_name = self.name
716                 else:
717                     error(self.pos, "'%s' is not a type identifier" % self.name)
718         if self.complex:
719             if not type.is_numeric or type.is_complex:
720                 error(self.pos, "can only complexify c numeric types")
721             type = PyrexTypes.CComplexType(type)
722             type.create_declaration_utility_code(env)
723         if type:
724             return type
725         else:
726             return PyrexTypes.error_type
727
728 class CBufferAccessTypeNode(CBaseTypeNode):
729     #  After parsing:
730     #  positional_args  [ExprNode]        List of positional arguments
731     #  keyword_args     DictNode          Keyword arguments
732     #  base_type_node   CBaseTypeNode
733
734     #  After analysis:
735     #  type             PyrexType.BufferType   ...containing the right options
736
737
738     child_attrs = ["base_type_node", "positional_args",
739                    "keyword_args", "dtype_node"]
740
741     dtype_node = None
742
743     name = None
744     
745     def analyse(self, env, could_be_name = False):
746         base_type = self.base_type_node.analyse(env)
747         if base_type.is_error: return base_type
748         import Buffer
749
750         options = Buffer.analyse_buffer_options(
751             self.pos,
752             env,
753             self.positional_args,
754             self.keyword_args,
755             base_type.buffer_defaults)
756         
757         self.type = PyrexTypes.BufferType(base_type, **options)
758         return self.type
759
760 class CComplexBaseTypeNode(CBaseTypeNode):
761     # base_type   CBaseTypeNode
762     # declarator  CDeclaratorNode
763     
764     child_attrs = ["base_type", "declarator"]
765
766     def analyse(self, env, could_be_name = False):
767         base = self.base_type.analyse(env, could_be_name)
768         _, type = self.declarator.analyse(base, env)
769         return type
770
771
772 class CVarDefNode(StatNode):
773     #  C variable definition or forward/extern function declaration.
774     #
775     #  visibility    'private' or 'public' or 'extern'
776     #  base_type     CBaseTypeNode
777     #  declarators   [CDeclaratorNode]
778     #  in_pxd        boolean
779     #  api           boolean
780     #  need_properties [entry]
781
782     #  decorators    [cython.locals(...)] or None 
783     #  directive_locals { string : NameNode } locals defined by cython.locals(...)
784
785     child_attrs = ["base_type", "declarators"]
786     need_properties = ()
787     
788     decorators = None
789     directive_locals = {}
790     
791     def analyse_declarations(self, env, dest_scope = None):
792         if not dest_scope:
793             dest_scope = env
794         self.dest_scope = dest_scope
795         base_type = self.base_type.analyse(env)
796
797         need_property = False
798         if (dest_scope.is_c_class_scope
799               and self.visibility == 'public'
800               and base_type.is_pyobject
801               and (base_type.is_builtin_type or base_type.is_extension_type)):
802             # If the field is settable and extension type, then the CPython mechanism does
803             # not do enough type-checking for us.
804             need_property = True
805         elif (base_type.is_typedef and base_type.typedef_is_external
806               and (self.visibility in ('public', 'readonly'))):
807             # If the field is an external typedef, we cannot be sure about the type,
808             # so do conversion ourself rather than rely on the CPython mechanism (through
809             # a property; made in AnalyseDeclarationsTransform).
810             need_property = True
811
812         if need_property:
813             visibility = 'private'
814             self.need_properties = []
815         else:
816             visibility = self.visibility
817             
818         for declarator in self.declarators:
819             name_declarator, type = declarator.analyse(base_type, env)
820             if not type.is_complete():
821                 if not (self.visibility == 'extern' and type.is_array):
822                     error(declarator.pos,
823                         "Variable type '%s' is incomplete" % type)
824             if self.visibility == 'extern' and type.is_pyobject:
825                 error(declarator.pos,
826                     "Python object cannot be declared extern")
827             name = name_declarator.name
828             cname = name_declarator.cname
829             if name == '':
830                 error(declarator.pos, "Missing name in declaration.")
831                 return
832             if type.is_cfunction:
833                 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
834                     cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
835                     api = self.api)
836                 if entry is not None:
837                     entry.directive_locals = self.directive_locals
838             else:
839                 if self.directive_locals:
840                     s.error("Decorators can only be followed by functions")
841                 if self.in_pxd and self.visibility != 'extern':
842                     error(self.pos, 
843                         "Only 'extern' C variable declaration allowed in .pxd file")
844                 entry = dest_scope.declare_var(name, type, declarator.pos,
845                             cname = cname, visibility = visibility, is_cdef = 1)
846                 if need_property:
847                     self.need_properties.append(entry)
848                     entry.needs_property = 1
849     
850
851 class CStructOrUnionDefNode(StatNode):
852     #  name          string
853     #  cname         string or None
854     #  kind          "struct" or "union"
855     #  typedef_flag  boolean
856     #  visibility    "public" or "private"
857     #  in_pxd        boolean
858     #  attributes    [CVarDefNode] or None
859     #  entry         Entry
860     #  packed        boolean
861     
862     child_attrs = ["attributes"]
863
864     def analyse_declarations(self, env):
865         scope = None
866         if self.visibility == 'extern' and self.packed:
867             error(self.pos, "Cannot declare extern struct as 'packed'")
868         if self.attributes is not None:
869             scope = StructOrUnionScope(self.name)
870         self.entry = env.declare_struct_or_union(
871             self.name, self.kind, scope, self.typedef_flag, self.pos,
872             self.cname, visibility = self.visibility, packed = self.packed)
873         if self.attributes is not None:
874             if self.in_pxd and not env.in_cinclude:
875                 self.entry.defined_in_pxd = 1
876             for attr in self.attributes:
877                 attr.analyse_declarations(env, scope)
878             if self.visibility != 'extern':
879                 need_typedef_indirection = False
880                 for attr in scope.var_entries:
881                     type = attr.type
882                     while type.is_array:
883                         type = type.base_type
884                     if type == self.entry.type:
885                         error(attr.pos, "Struct cannot contain itself as a member.")
886                     if self.typedef_flag:
887                         while type.is_ptr:
888                             type = type.base_type
889                         if type == self.entry.type:
890                             need_typedef_indirection = True
891                 if need_typedef_indirection:
892                     # C can't handle typedef structs that refer to themselves. 
893                     struct_entry = self.entry
894                     cname = env.new_const_cname()
895                     self.entry = env.declare_typedef(self.name, struct_entry.type, self.pos, cname = self.cname, visibility='ignore')
896                     struct_entry.type.typedef_flag = False
897                     struct_entry.cname = struct_entry.type.cname = env.new_const_cname()
898     
899     def analyse_expressions(self, env):
900         pass
901     
902     def generate_execution_code(self, code):
903         pass
904
905
906 class CEnumDefNode(StatNode):
907     #  name           string or None
908     #  cname          string or None
909     #  items          [CEnumDefItemNode]
910     #  typedef_flag   boolean
911     #  visibility     "public" or "private"
912     #  in_pxd         boolean
913     #  entry          Entry
914     
915     child_attrs = ["items"]
916     
917     def analyse_declarations(self, env):
918         self.entry = env.declare_enum(self.name, self.pos,
919             cname = self.cname, typedef_flag = self.typedef_flag,
920             visibility = self.visibility)
921         if self.items is not None:
922             if self.in_pxd and not env.in_cinclude:
923                 self.entry.defined_in_pxd = 1
924             for item in self.items:
925                 item.analyse_declarations(env, self.entry)
926
927     def analyse_expressions(self, env):
928         if self.visibility == 'public':
929             self.temp = env.allocate_temp_pyobject()
930             env.release_temp(self.temp)
931     
932     def generate_execution_code(self, code):
933         if self.visibility == 'public':
934             for item in self.entry.enum_values:
935                 code.putln("%s = PyInt_FromLong(%s); %s" % (
936                         self.temp,
937                         item.cname,
938                         code.error_goto_if_null(self.temp, item.pos)))
939                 code.put_gotref(self.temp)
940                 code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
941                         Naming.module_cname, 
942                         item.name, 
943                         self.temp,
944                         code.error_goto(item.pos)))
945                 code.put_decref_clear(self.temp, PyrexTypes.py_object_type)
946
947
948 class CEnumDefItemNode(StatNode):
949     #  name     string
950     #  cname    string or None
951     #  value    ExprNode or None
952     
953     child_attrs = ["value"]
954
955     def analyse_declarations(self, env, enum_entry):
956         if self.value:
957             self.value.analyse_const_expression(env)
958             if not self.value.type.is_int:
959                 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
960                 self.value.analyse_const_expression(env)
961             value = self.value.result()
962         else:
963             value = self.name
964         entry = env.declare_const(self.name, enum_entry.type, 
965             value, self.pos, cname = self.cname, visibility = enum_entry.visibility)
966         enum_entry.enum_values.append(entry)
967
968
969 class CTypeDefNode(StatNode):
970     #  base_type    CBaseTypeNode
971     #  declarator   CDeclaratorNode
972     #  visibility   "public" or "private"
973     #  in_pxd       boolean
974
975     child_attrs = ["base_type", "declarator"]
976     
977     def analyse_declarations(self, env):
978         base = self.base_type.analyse(env)
979         name_declarator, type = self.declarator.analyse(base, env)
980         name = name_declarator.name
981         cname = name_declarator.cname
982         entry = env.declare_typedef(name, type, self.pos,
983             cname = cname, visibility = self.visibility)
984         if self.in_pxd and not env.in_cinclude:
985             entry.defined_in_pxd = 1
986     
987     def analyse_expressions(self, env):
988         pass
989     def generate_execution_code(self, code):
990         pass
991
992
993 class FuncDefNode(StatNode, BlockNode):
994     #  Base class for function definition nodes.
995     #
996     #  return_type     PyrexType
997     #  #filename        string        C name of filename string const
998     #  entry           Symtab.Entry
999     #  needs_closure   boolean        Whether or not this function has inner functions/classes/yield
1000     #  directive_locals { string : NameNode } locals defined by cython.locals(...)
1001     
1002     py_func = None
1003     assmt = None
1004     needs_closure = False
1005     
1006     def analyse_default_values(self, env):
1007         genv = env.global_scope()
1008         for arg in self.args:
1009             if arg.default:
1010                 if arg.is_generic:
1011                     if not hasattr(arg, 'default_entry'):
1012                         arg.default.analyse_types(env)
1013                         arg.default = arg.default.coerce_to(arg.type, genv)
1014                         if arg.default.is_literal:
1015                             arg.default_entry = arg.default
1016                             arg.default_result_code = arg.default.calculate_result_code()
1017                             if arg.default.type != arg.type and not arg.type.is_int:
1018                                 arg.default_result_code = arg.type.cast_code(arg.default_result_code)
1019                         else:
1020                             arg.default.allocate_temps(genv)
1021                             arg.default_entry = genv.add_default_value(arg.type)
1022                             if arg.type.is_pyobject:
1023                                 arg.default_entry.init = 0
1024                             arg.default_entry.used = 1
1025                             arg.default_result_code = arg.default_entry.cname
1026                 else:
1027                     error(arg.pos,
1028                         "This argument cannot have a default value")
1029                     arg.default = None
1030     
1031     def need_gil_acquisition(self, lenv):
1032         return 0
1033         
1034     def create_local_scope(self, env):
1035         genv = env
1036         while env.is_py_class_scope or env.is_c_class_scope:
1037             env = env.outer_scope
1038         if self.needs_closure:
1039             lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
1040         else:
1041             lenv = LocalScope(name = self.entry.name, outer_scope = genv)
1042         lenv.return_type = self.return_type
1043         type = self.entry.type
1044         if type.is_cfunction:
1045             lenv.nogil = type.nogil and not type.with_gil
1046         self.local_scope = lenv
1047         lenv.directives = env.directives
1048         return lenv
1049                 
1050     def generate_function_definitions(self, env, code):
1051         import Buffer
1052
1053         lenv = self.local_scope
1054
1055         is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
1056                              self.entry.scope.is_c_class_scope)
1057
1058         # Generate C code for header and body of function
1059         code.enter_cfunc_scope()
1060         code.return_from_error_cleanup_label = code.new_label()
1061             
1062         # ----- Top-level constants used by this function
1063         code.mark_pos(self.pos)
1064         self.generate_interned_num_decls(lenv, code)
1065         self.generate_interned_string_decls(lenv, code)
1066         self.generate_py_string_decls(lenv, code)
1067         self.generate_cached_builtins_decls(lenv, code)
1068         #code.putln("")
1069         #code.put_var_declarations(lenv.const_entries, static = 1)
1070         self.generate_const_definitions(lenv, code)
1071         # ----- Function header
1072         code.putln("")
1073         if self.py_func:
1074             self.py_func.generate_function_header(code, 
1075                 with_pymethdef = env.is_py_class_scope,
1076                 proto_only=True)
1077         self.generate_function_header(code,
1078             with_pymethdef = env.is_py_class_scope)
1079         # ----- Local variable declarations
1080         lenv.mangle_closure_cnames(Naming.cur_scope_cname)
1081         self.generate_argument_declarations(lenv, code)
1082         if self.needs_closure:
1083             code.putln("/* TODO: declare and create scope object */")
1084         code.put_var_declarations(lenv.var_entries)
1085         init = ""
1086         if not self.return_type.is_void:
1087             if self.return_type.is_pyobject:
1088                 init = " = NULL"
1089             code.putln(
1090                 "%s%s;" % 
1091                     (self.return_type.declaration_code(
1092                         Naming.retval_cname),
1093                     init))
1094         tempvardecl_code = code.insertion_point()
1095         self.generate_keyword_list(code)
1096         # ----- Extern library function declarations
1097         lenv.generate_library_function_declarations(code)
1098         # ----- GIL acquisition
1099         acquire_gil = self.need_gil_acquisition(lenv)
1100         if acquire_gil:
1101             env.use_utility_code(force_init_threads_utility_code)
1102             code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1103         # ----- Automatic lead-ins for certain special functions
1104         if not lenv.nogil:
1105             code.put_setup_refcount_context(self.entry.name)
1106         if is_getbuffer_slot:
1107             self.getbuffer_init(code)
1108         # ----- Fetch arguments
1109         self.generate_argument_parsing_code(env, code)
1110         # If an argument is assigned to in the body, we must 
1111         # incref it to properly keep track of refcounts.
1112         for entry in lenv.arg_entries:
1113             if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1114                 code.put_var_incref(entry)
1115         # ----- Initialise local variables 
1116         for entry in lenv.var_entries:
1117             if entry.type.is_pyobject and entry.init_to_none and entry.used:
1118                 code.put_init_var_to_py_none(entry)
1119         # ----- Initialise local buffer auxiliary variables
1120         for entry in lenv.var_entries + lenv.arg_entries:
1121             if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1122                 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1123         # ----- Check and convert arguments
1124         self.generate_argument_type_tests(code)
1125         # ----- Acquire buffer arguments
1126         for entry in lenv.arg_entries:
1127             if entry.type.is_buffer:
1128                 Buffer.put_acquire_arg_buffer(entry, code, self.pos)        
1129         # ----- Function body
1130         self.body.generate_execution_code(code)
1131         # ----- Default return value
1132         code.putln("")
1133         if self.return_type.is_pyobject:
1134             #if self.return_type.is_extension_type:
1135             #    lhs = "(PyObject *)%s" % Naming.retval_cname
1136             #else:
1137             lhs = Naming.retval_cname
1138             code.put_init_to_py_none(lhs, self.return_type)
1139         else:
1140             val = self.return_type.default_value
1141             if val:
1142                 code.putln("%s = %s;" % (Naming.retval_cname, val))
1143         # ----- Error cleanup
1144         if code.error_label in code.labels_used:
1145             code.put_goto(code.return_label)
1146             code.put_label(code.error_label)
1147             # cleanup temps the old way
1148             code.put_var_xdecrefs(lenv.temp_entries)
1149             # cleanup temps the new way
1150             for cname, type in code.funcstate.all_managed_temps():
1151                 code.put_xdecref(cname, type)
1152
1153             # Clean up buffers -- this calls a Python function
1154             # so need to save and restore error state
1155             buffers_present = len(lenv.buffer_entries) > 0
1156             if buffers_present:
1157                 code.globalstate.use_utility_code(restore_exception_utility_code)
1158                 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1159                 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1160                 for entry in lenv.buffer_entries:
1161                     code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1162                     #code.putln("%s = 0;" % entry.cname)
1163                 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1164
1165             err_val = self.error_value()
1166             exc_check = self.caller_will_check_exceptions()
1167             if err_val is not None or exc_check:
1168                 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1169             else:
1170                 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1171                             % self.entry.qualified_name, 0)
1172                 code.putln(
1173                     '__Pyx_WriteUnraisable("%s");' % 
1174                         self.entry.qualified_name)
1175                 env.use_utility_code(unraisable_exception_utility_code)
1176                 env.use_utility_code(restore_exception_utility_code)
1177             default_retval = self.return_type.default_value
1178             if err_val is None and default_retval:
1179                 err_val = default_retval
1180             if err_val is not None:
1181                 code.putln(
1182                     "%s = %s;" % (
1183                         Naming.retval_cname, 
1184                         err_val))
1185
1186             if is_getbuffer_slot:
1187                 self.getbuffer_error_cleanup(code)
1188
1189             # If we are using the non-error cleanup section we should
1190             # jump past it if we have an error. The if-test below determine
1191             # whether this section is used.
1192             if buffers_present or is_getbuffer_slot:
1193                 code.put_goto(code.return_from_error_cleanup_label)
1194
1195
1196         # ----- Non-error return cleanup
1197         # If you add anything here, remember to add a condition to the
1198         # if-test above in the error block (so that it can jump past this
1199         # block).
1200         code.put_label(code.return_label)
1201         for entry in lenv.buffer_entries:
1202             if entry.used:
1203                 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1204         if is_getbuffer_slot:
1205             self.getbuffer_normal_cleanup(code)
1206         # ----- Return cleanup for both error and no-error return
1207         code.put_label(code.return_from_error_cleanup_label)
1208         if not Options.init_local_none:
1209             for entry in lenv.var_entries:
1210                 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1211                     entry.xdecref_cleanup = 1
1212         code.put_var_decrefs(lenv.var_entries, used_only = 1)
1213         # Decref any increfed args
1214         for entry in lenv.arg_entries:
1215             if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1216                 code.put_var_decref(entry)
1217
1218         # code.putln("/* TODO: decref scope object */")
1219         # ----- Return
1220         # This code is duplicated in ModuleNode.generate_module_init_func
1221         if not lenv.nogil:
1222             default_retval = self.return_type.default_value
1223             err_val = self.error_value()
1224             if err_val is None and default_retval:
1225                 err_val = default_retval
1226             if self.return_type.is_pyobject:
1227                 code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1228
1229             code.put_finish_refcount_context()
1230
1231         if acquire_gil:
1232             code.putln("PyGILState_Release(_save);")
1233
1234         if not self.return_type.is_void:
1235             code.putln("return %s;" % Naming.retval_cname)
1236             
1237         code.putln("}")
1238         # ----- Go back and insert temp variable declarations
1239         tempvardecl_code.put_var_declarations(lenv.temp_entries)
1240         tempvardecl_code.put_temp_declarations(code.funcstate)
1241         # ----- Python version
1242         code.exit_cfunc_scope()
1243         if self.py_func:
1244             self.py_func.generate_function_definitions(env, code)
1245         self.generate_wrapper_functions(code)
1246
1247     def declare_argument(self, env, arg):
1248         if arg.type.is_void:
1249             error(arg.pos, "Invalid use of 'void'")
1250         elif not arg.type.is_complete() and not arg.type.is_array:
1251             error(arg.pos,
1252                 "Argument type '%s' is incomplete" % arg.type)
1253         return env.declare_arg(arg.name, arg.type, arg.pos)
1254         
1255     def generate_wrapper_functions(self, code):
1256         pass
1257
1258     def generate_execution_code(self, code):
1259         # Evaluate and store argument default values
1260         for arg in self.args:
1261             default = arg.default
1262             if default:
1263                 if not default.is_literal:
1264                     default.generate_evaluation_code(code)
1265                     default.make_owned_reference(code)
1266                     code.putln(
1267                         "%s = %s;" % (
1268                             arg.default_entry.cname,
1269                             default.result_as(arg.default_entry.type)))
1270                     if default.is_temp and default.type.is_pyobject:
1271                         code.putln("%s = 0;" % default.result())
1272                     default.free_temps(code)
1273                     code.put_var_giveref(arg.default_entry)
1274         # For Python class methods, create and store function object
1275         if self.assmt:
1276             self.assmt.generate_execution_code(code)
1277
1278     #
1279     # Special code for the __getbuffer__ function
1280     #
1281     def getbuffer_init(self, code):
1282         info = self.local_scope.arg_entries[1].cname
1283         # Python 3.0 betas have a bug in memoryview which makes it call
1284         # getbuffer with a NULL parameter. For now we work around this;
1285         # the following line should be removed when this bug is fixed.
1286         code.putln("if (%s == NULL) return 0;" % info) 
1287         code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1288         code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1289
1290     def getbuffer_error_cleanup(self, code):
1291         info = self.local_scope.arg_entries[1].cname
1292         code.put_gotref("%s->obj" % info)
1293         code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1294                    (info, info))
1295
1296     def getbuffer_normal_cleanup(self, code):
1297         info = self.local_scope.arg_entries[1].cname
1298         code.putln("if (%s->obj == Py_None) {" % info)
1299         code.put_gotref("Py_None")
1300         code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
1301         code.putln("}")
1302
1303 class CFuncDefNode(FuncDefNode):
1304     #  C function definition.
1305     #
1306     #  modifiers     ['inline']
1307     #  visibility    'private' or 'public' or 'extern'
1308     #  base_type     CBaseTypeNode
1309     #  declarator    CDeclaratorNode
1310     #  body          StatListNode
1311     #  api           boolean
1312     #  decorators    [DecoratorNode]        list of decorators
1313     #
1314     #  with_gil      boolean    Acquire GIL around body
1315     #  type          CFuncType
1316     #  py_func       wrapper for calling from Python
1317     #  overridable   whether or not this is a cpdef function
1318     #  inline_in_pxd whether this is an inline function in a pxd file
1319     
1320     child_attrs = ["base_type", "declarator", "body", "py_func"]
1321
1322     inline_in_pxd = False
1323     decorators = None
1324     directive_locals = {}
1325
1326     def unqualified_name(self):
1327         return self.entry.name
1328         
1329     def analyse_declarations(self, env):
1330         directive_locals = self.directive_locals = env.directives['locals']
1331         base_type = self.base_type.analyse(env)
1332         # The 2 here is because we need both function and argument names. 
1333         name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1334         if not type.is_cfunction:
1335             error(self.pos, 
1336                 "Suite attached to non-function declaration")
1337         # Remember the actual type according to the function header
1338         # written here, because the type in the symbol table entry
1339         # may be different if we're overriding a C method inherited
1340         # from the base type of an extension type.
1341         self.type = type
1342         type.is_overridable = self.overridable
1343         declarator = self.declarator
1344         while not hasattr(declarator, 'args'):
1345             declarator = declarator.base
1346         self.args = declarator.args
1347         for formal_arg, type_arg in zip(self.args, type.args):
1348             formal_arg.type = type_arg.type
1349             formal_arg.name = type_arg.name
1350             formal_arg.cname = type_arg.cname
1351         name = name_declarator.name
1352         cname = name_declarator.cname
1353         self.entry = env.declare_cfunction(
1354             name, type, self.pos, 
1355             cname = cname, visibility = self.visibility,
1356             defining = self.body is not None,
1357             api = self.api, modifiers = self.modifiers)
1358         self.entry.inline_func_in_pxd = self.inline_in_pxd
1359         self.return_type = type.return_type
1360         
1361         if self.overridable and not env.is_module_scope:
1362             if len(self.args) < 1 or not self.args[0].type.is_pyobject:
1363                 # An error will be produced in the cdef function
1364                 self.overridable = False
1365             
1366         if self.overridable:
1367             import ExprNodes
1368             py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1369             self.py_func = DefNode(pos = self.pos, 
1370                                    name = self.entry.name,
1371                                    args = self.args,
1372                                    star_arg = None,
1373                                    starstar_arg = None,
1374                                    doc = self.doc,
1375                                    body = py_func_body,
1376                                    is_wrapper = 1)
1377             self.py_func.is_module_scope = env.is_module_scope
1378             self.py_func.analyse_declarations(env)
1379             self.entry.as_variable = self.py_func.entry
1380             # Reset scope entry the above cfunction
1381             env.entries[name] = self.entry
1382             self.py_func.interned_attr_cname = env.intern_identifier(
1383                 self.py_func.entry.name)
1384             if not env.is_module_scope or Options.lookup_module_cpdef:
1385                 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1386                 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1387     
1388     def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1389         import ExprNodes
1390         args = self.type.args
1391         if omit_optional_args:
1392             args = args[:len(args) - self.type.optional_arg_count]
1393         arg_names = [arg.name for arg in args]
1394         if is_module_scope:
1395             cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1396         else:
1397             self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1398             cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1399         skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1400         c_call = ExprNodes.SimpleCallNode(self.pos, function=cfunc, args=[ExprNodes.NameNode(self.pos, name=n) for n in arg_names[1-is_module_scope:]], wrapper_call=skip_dispatch)
1401         return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1402     
1403     def declare_arguments(self, env):
1404         for arg in self.type.args:
1405             if not arg.name:
1406                 error(arg.pos, "Missing argument name")
1407             self.declare_argument(env, arg)
1408             
1409     def need_gil_acquisition(self, lenv):
1410         type = self.type
1411         with_gil = self.type.with_gil
1412         if type.nogil and not with_gil:
1413             if type.return_type.is_pyobject:
1414                 error(self.pos,
1415                       "Function with Python return type cannot be declared nogil")
1416             for entry in lenv.var_entries + lenv.temp_entries:
1417                 if entry.type.is_pyobject:
1418                     error(self.pos, "Function declared nogil has Python locals or temporaries")
1419         return with_gil
1420
1421     def analyse_expressions(self, env):
1422         self.local_scope.directives = env.directives
1423         self.analyse_default_values(env)
1424         if self.py_func is not None:
1425             self.py_func.analyse_expressions(env)
1426
1427     def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1428         arg_decls = []
1429         type = self.type
1430         visibility = self.entry.visibility
1431         for arg in type.args[:len(type.args)-type.optional_arg_count]:
1432             arg_decls.append(arg.declaration_code())
1433         if with_dispatch and self.overridable:
1434             arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1435         if type.optional_arg_count and with_opt_args:
1436             arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1437         if type.has_varargs:
1438             arg_decls.append("...")
1439         if not arg_decls:
1440             arg_decls = ["void"]
1441         if cname is None:
1442             cname = self.entry.func_cname
1443         entity = type.function_header_code(cname, ', '.join(arg_decls))
1444         if visibility == 'public':
1445             dll_linkage = "DL_EXPORT"
1446         else:
1447             dll_linkage = None
1448         header = self.return_type.declaration_code(entity,
1449             dll_linkage = dll_linkage)
1450         if visibility == 'extern':
1451             storage_class = "%s " % Naming.extern_c_macro
1452         elif visibility == 'public':
1453             storage_class = ""
1454         else:
1455             storage_class = "static "
1456         code.putln("%s%s %s {" % (
1457             storage_class,
1458             ' '.join(self.modifiers).upper(), # macro forms 
1459             header))
1460
1461     def generate_argument_declarations(self, env, code):
1462         for arg in self.args:
1463             if arg.default:
1464                     code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1465
1466     def generate_keyword_list(self, code):
1467         pass
1468         
1469     def generate_argument_parsing_code(self, env, code):
1470         i = 0
1471         if self.type.optional_arg_count:
1472             code.putln('if (%s) {' % Naming.optional_args_cname)
1473             for arg in self.args:
1474                 if arg.default:
1475                     # FIXME: simple name prefixing doesn't work when
1476                     # argument name mangling is in place
1477                     code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1478                     declarator = arg.declarator
1479                     while not hasattr(declarator, 'name'):
1480                         declarator = declarator.base
1481                     code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1482                     i += 1
1483             for _ in range(self.type.optional_arg_count):
1484                 code.putln('}')
1485             code.putln('}')
1486     
1487     def generate_argument_conversion_code(self, code):
1488         pass
1489     
1490     def generate_argument_type_tests(self, code):
1491         # Generate type tests for args whose type in a parent
1492         # class is a supertype of the declared type.
1493         for arg in self.type.args:
1494             if arg.needs_type_test:
1495                 self.generate_arg_type_test(arg, code)
1496     
1497     def generate_arg_type_test(self, arg, code):
1498         # Generate type test for one argument.
1499         if arg.type.typeobj_is_available():
1500             typeptr_cname = arg.type.typeptr_cname
1501             arg_code = "((PyObject *)%s)" % arg.cname
1502             code.putln(
1503                 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1504                     arg_code, 
1505                     typeptr_cname,
1506                     not arg.not_none,
1507                     arg.name,
1508                     type.is_builtin_type,
1509                     code.error_goto(arg.pos)))
1510         else:
1511             error(arg.pos, "Cannot test type of extern C class "
1512                 "without type object name specification")
1513
1514     def error_value(self):
1515         if self.return_type.is_pyobject:
1516             return "0"
1517         else:
1518             #return None
1519             return self.entry.type.exception_value
1520             
1521     def caller_will_check_exceptions(self):
1522         return self.entry.type.exception_check
1523         
1524     def generate_wrapper_functions(self, code):
1525         # If the C signature of a function has changed, we need to generate
1526         # wrappers to put in the slots here. 
1527         k = 0
1528         entry = self.entry
1529         func_type = entry.type
1530         while entry.prev_entry is not None:
1531             k += 1
1532             entry = entry.prev_entry
1533             entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1534             code.putln()
1535             self.generate_function_header(code, 
1536                                           0,
1537                                           with_dispatch = entry.type.is_overridable, 
1538                                           with_opt_args = entry.type.optional_arg_count, 
1539                                           cname = entry.func_cname)
1540             if not self.return_type.is_void:
1541                 code.put('return ')
1542             args = self.type.args
1543             arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1544             if entry.type.is_overridable:
1545                 arglist.append(Naming.skip_dispatch_cname)
1546             elif func_type.is_overridable:
1547                 arglist.append('0')
1548             if entry.type.optional_arg_count:
1549                 arglist.append(Naming.optional_args_cname)
1550             elif func_type.optional_arg_count:
1551                 arglist.append('NULL')
1552             code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1553             code.putln('}')
1554         
1555
1556 class PyArgDeclNode(Node):
1557     # Argument which must be a Python object (used
1558     # for * and ** arguments).
1559     #
1560     # name   string
1561     # entry  Symtab.Entry
1562     child_attrs = []
1563     
1564
1565 class DecoratorNode(Node):
1566     # A decorator
1567     #
1568     # decorator    NameNode or CallNode
1569     child_attrs = ['decorator']
1570
1571
1572 class DefNode(FuncDefNode):
1573     # A Python function definition.
1574     #
1575     # name          string                 the Python name of the function
1576     # decorators    [DecoratorNode]        list of decorators
1577     # args          [CArgDeclNode]         formal arguments
1578     # star_arg      PyArgDeclNode or None  * argument
1579     # starstar_arg  PyArgDeclNode or None  ** argument
1580     # doc           EncodedString or None
1581     # body          StatListNode
1582     #
1583     #  The following subnode is constructed internally
1584     #  when the def statement is inside a Python class definition.
1585     #
1586     #  assmt   AssignmentNode   Function construction/assignment
1587     
1588     child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1589
1590     assmt = None
1591     num_kwonly_args = 0
1592     num_required_kw_args = 0
1593     reqd_kw_flags_cname = "0"
1594     is_wrapper = 0
1595     decorators = None
1596     entry = None
1597     
1598
1599     def __init__(self, pos, **kwds):
1600         FuncDefNode.__init__(self, pos, **kwds)
1601         k = rk = r = 0
1602         for arg in self.args:
1603             if arg.kw_only:
1604                 k += 1
1605                 if not arg.default:
1606                     rk += 1
1607             if not arg.default:
1608                 r += 1
1609         self.num_kwonly_args = k
1610         self.num_required_kw_args = rk
1611         self.num_required_args = r
1612         
1613     def as_cfunction(self, cfunc=None, scope=None):
1614         if self.star_arg:
1615             error(self.star_arg.pos, "cdef function cannot have star argument")
1616         if self.starstar_arg:
1617             error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1618         if cfunc is None:
1619             cfunc_args = []
1620             for formal_arg in self.args:
1621                 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1622                 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1623                                                           cname = None,
1624                                                           type = py_object_type,
1625                                                           pos = formal_arg.pos))
1626             cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1627                                               args = cfunc_args,
1628                                               has_varargs = False,
1629                                               exception_value = None,
1630                                               exception_check = False,
1631                                               nogil = False,
1632                                               with_gil = False,
1633                                               is_overridable = True)
1634             cfunc = CVarDefNode(self.pos, type=cfunc_type)
1635         else:
1636             cfunc_type = cfunc.type
1637             if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1638                 error(self.pos, "wrong number of arguments")
1639                 error(declarator.pos, "previous declaration here")
1640             for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1641                 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1642                 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1643                     formal_arg.type = type_arg.type
1644                     formal_arg.name_declarator = name_declarator
1645         import ExprNodes
1646         if cfunc_type.exception_value is None:
1647             exception_value = None
1648         else:
1649             exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1650         declarator = CFuncDeclaratorNode(self.pos, 
1651                                          base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1652                                          args = self.args,
1653                                          has_varargs = False,
1654                                          exception_check = cfunc_type.exception_check,
1655                                          exception_value = exception_value,
1656                                          with_gil = cfunc_type.with_gil,
1657                                          nogil = cfunc_type.nogil)
1658         return CFuncDefNode(self.pos, 
1659                             modifiers = [],
1660                             base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1661                             declarator = declarator,
1662                             body = self.body,
1663                             doc = self.doc,
1664                             overridable = cfunc_type.is_overridable,
1665                             type = cfunc_type,
1666                             with_gil = cfunc_type.with_gil,
1667                             nogil = cfunc_type.nogil,
1668                             visibility = 'private',
1669                             api = False,
1670                             directive_locals = getattr(cfunc, 'directive_locals', {}))
1671     
1672     def analyse_declarations(self, env):
1673         directive_locals = self.directive_locals = env.directives['locals']
1674         for arg in self.args:
1675             if hasattr(arg, 'name'):
1676                 type = arg.type
1677                 name_declarator = None
1678             else:
1679                 base_type = arg.base_type.analyse(env)
1680                 name_declarator, type = \
1681                     arg.declarator.analyse(base_type, env)
1682                 arg.name = name_declarator.name
1683             if arg.name in directive_locals:
1684                 type_node = directive_locals[arg.name]
1685                 other_type = type_node.analyse_as_type(env)
1686                 if other_type is None:
1687                     error(type_node.pos, "Not a type")
1688                 elif (type is not PyrexTypes.py_object_type 
1689                         and not type.same_as(other_type)):
1690                     error(arg.base_type.pos, "Signature does not agree with previous declaration")
1691                     error(type_node.pos, "Previous declaration here")
1692                 else:
1693                     type = other_type
1694             if name_declarator and name_declarator.cname:
1695                 error(self.pos,
1696                     "Python function argument cannot have C name specification")
1697             arg.type = type.as_argument_type()
1698             arg.hdr_type = None
1699             arg.needs_conversion = 0
1700             arg.needs_type_test = 0
1701             arg.is_generic = 1
1702             if arg.not_none and not arg.type.is_extension_type:
1703                 error(self.pos,
1704                     "Only extension type arguments can have 'not None'")
1705         self.declare_pyfunction(env)
1706         self.analyse_signature(env)
1707         self.return_type = self.entry.signature.return_type()
1708
1709     def analyse_signature(self, env):
1710         any_type_tests_needed = 0
1711         if self.entry.is_special:
1712             self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1713         elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
1714             # Use the simpler calling signature for zero- and one-argument functions.
1715             if self.entry.signature is TypeSlots.pyfunction_signature:
1716                 if len(self.args) == 0:
1717                     self.entry.signature = TypeSlots.pyfunction_noargs
1718                 elif len(self.args) == 1:
1719                     if self.args[0].default is None and not self.args[0].kw_only:
1720                         self.entry.signature = TypeSlots.pyfunction_onearg
1721             elif self.entry.signature is TypeSlots.pymethod_signature:
1722                 if len(self.args) == 1:
1723                     self.entry.signature = TypeSlots.unaryfunc
1724                 elif len(self.args) == 2:
1725                     if self.args[1].default is None and not self.args[1].kw_only:
1726                         self.entry.signature = TypeSlots.ibinaryfunc
1727         sig = self.entry.signature
1728         nfixed = sig.num_fixed_args()
1729         for i in range(nfixed):
1730             if i < len(self.args):
1731                 arg = self.args[i]
1732                 arg.is_generic = 0
1733                 if sig.is_self_arg(i):
1734                     arg.is_self_arg = 1
1735                     arg.hdr_type = arg.type = env.parent_type
1736                     arg.needs_conversion = 0
1737                 else:
1738                     arg.hdr_type = sig.fixed_arg_type(i)
1739                     if not arg.type.same_as(arg.hdr_type):
1740                         if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1741                             arg.needs_type_test = 1
1742                             any_type_tests_needed = 1
1743                         else:
1744                             arg.needs_conversion = 1
1745                 if arg.needs_conversion:
1746                     arg.hdr_cname = Naming.arg_prefix + arg.name
1747                 else:
1748                     arg.hdr_cname = Naming.var_prefix + arg.name
1749             else:
1750                 self.bad_signature()
1751                 return
1752         if nfixed < len(self.args):
1753             if not sig.has_generic_args:
1754                 self.bad_signature()
1755             for arg in self.args:
1756                 if arg.is_generic and \
1757                         (arg.type.is_extension_type or arg.type.is_builtin_type):
1758                     arg.needs_type_test = 1
1759                     any_type_tests_needed = 1
1760         if any_type_tests_needed:
1761             env.use_utility_code(arg_type_test_utility_code)
1762     
1763     def bad_signature(self):
1764         sig = self.entry.signature
1765         expected_str = "%d" % sig.num_fixed_args()
1766         if sig.has_generic_args:
1767             expected_str = expected_str + " or more"
1768         name = self.name
1769         if name.startswith("__") and name.endswith("__"):
1770             desc = "Special method"
1771         else:
1772             desc = "Method"
1773         error(self.pos,
1774             "%s %s has wrong number of arguments "
1775             "(%d declared, %s expected)" % (
1776                 desc, self.name, len(self.args), expected_str))
1777
1778     def signature_has_nongeneric_args(self):
1779         argcount = len(self.args)
1780         if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1781             return 0
1782         return 1
1783
1784     def signature_has_generic_args(self):
1785         return self.entry.signature.has_generic_args
1786     
1787     def declare_pyfunction(self, env):
1788         #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1789         name = self.name
1790         entry = env.lookup_here(self.name)
1791         if entry and entry.type.is_cfunction and not self.is_wrapper:
1792             warning(self.pos, "Overriding cdef method with def method.", 5)
1793         entry = env.declare_pyfunction(self.name, self.pos)
1794         self.entry = entry
1795         prefix = env.scope_prefix
1796         entry.func_cname = \
1797             Naming.pyfunc_prefix + prefix + name
1798         entry.pymethdef_cname = \
1799             Naming.pymethdef_prefix + prefix + name
1800         if Options.docstrings:
1801             entry.doc = embed_position(self.pos, self.doc)
1802             entry.doc_cname = \
1803                 Naming.funcdoc_prefix + prefix + name
1804         else:
1805             entry.doc = None
1806
1807     def declare_arguments(self, env):
1808         for arg in self.args:
1809             if not arg.name:
1810                 error(arg.pos, "Missing argument name")
1811             if arg.needs_conversion:
1812                 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1813                 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1814                 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1815                 if arg.type.is_pyobject:
1816                     arg.entry.init = "0"
1817                 arg.entry.init_to_none = 0
1818             else:
1819                 arg.entry = self.declare_argument(env, arg)
1820             arg.entry.used = 1
1821             arg.entry.is_self_arg = arg.is_self_arg
1822             if not arg.is_self_arg:
1823                 arg.name_entry = env.get_string_const(
1824                     arg.name, identifier = True)
1825                 env.add_py_string(arg.name_entry, identifier = True)
1826             if arg.hdr_type:
1827                 if arg.is_self_arg or \
1828                     (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1829                         arg.entry.is_declared_generic = 1
1830         self.declare_python_arg(env, self.star_arg)
1831         self.declare_python_arg(env, self.starstar_arg)
1832
1833     def declare_python_arg(self, env, arg):
1834         if arg:
1835             entry = env.declare_var(arg.name, 
1836                 PyrexTypes.py_object_type, arg.pos)
1837             entry.used = 1
1838             entry.init = "0"
1839             entry.init_to_none = 0
1840             entry.xdecref_cleanup = 1
1841             arg.entry = entry
1842             env.control_flow.set_state((), (arg.name, 'initalized'), True)
1843             
1844     def analyse_expressions(self, env):
1845         self.local_scope.directives = env.directives
1846         self.analyse_default_values(env)
1847         if env.is_py_class_scope:
1848             self.synthesize_assignment_node(env)
1849     
1850     def synthesize_assignment_node(self, env):
1851         import ExprNodes
1852         self.assmt = SingleAssignmentNode(self.pos,
1853             lhs = ExprNodes.NameNode(self.pos, name = self.name),
1854             rhs = ExprNodes.UnboundMethodNode(self.pos, 
1855                 class_cname = env.class_obj_cname,
1856                 function = ExprNodes.PyCFunctionNode(self.pos,
1857                     pymethdef_cname = self.entry.pymethdef_cname)))
1858         self.assmt.analyse_declarations(env)
1859         self.assmt.analyse_expressions(env)
1860             
1861     def generate_function_header(self, code, with_pymethdef, proto_only=0):
1862         arg_code_list = []
1863         sig = self.entry.signature
1864         if sig.has_dummy_arg:
1865             arg_code_list.append(
1866                 "PyObject *%s" % Naming.self_cname)
1867         for arg in self.args:
1868             if not arg.is_generic:
1869                 if arg.is_self_arg:
1870                     arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1871                 else:
1872                     arg_code_list.append(
1873                         arg.hdr_type.declaration_code(arg.hdr_cname))
1874         if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1875             arg_code_list.append("PyObject *unused")
1876         if sig.has_generic_args:
1877             arg_code_list.append(
1878                 "PyObject *%s, PyObject *%s"
1879                     % (Naming.args_cname, Naming.kwds_cname))
1880         arg_code = ", ".join(arg_code_list)
1881         dc = self.return_type.declaration_code(self.entry.func_cname)
1882         header = "static %s(%s)" % (dc, arg_code)
1883         code.putln("%s; /*proto*/" % header)
1884         if proto_only:
1885             return
1886         if self.entry.doc and Options.docstrings:
1887             docstr = self.entry.doc
1888             if not isinstance(docstr, str):
1889                 docstr = docstr.utf8encode()
1890             code.putln(
1891                 'static char %s[] = "%s";' % (
1892                     self.entry.doc_cname,
1893                     split_docstring(escape_byte_string(docstr))))
1894         if with_pymethdef:
1895             code.put(
1896                 "static PyMethodDef %s = " % 
1897                     self.entry.pymethdef_cname)
1898             code.put_pymethoddef(self.entry, ";")
1899         code.putln("%s {" % header)
1900
1901     def generate_argument_declarations(self, env, code):
1902         for arg in self.args:
1903             if arg.is_generic: # or arg.needs_conversion:
1904                 if arg.needs_conversion:
1905                     code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1906                 else:
1907                     code.put_var_declaration(arg.entry)
1908     
1909     def generate_keyword_list(self, code):
1910         if self.signature_has_generic_args() and \
1911                 self.signature_has_nongeneric_args():
1912             code.put(
1913                 "static PyObject **%s[] = {" %
1914                     Naming.pykwdlist_cname)
1915             for arg in self.args:
1916                 if arg.is_generic:
1917                     code.put('&%s,' % arg.name_entry.pystring_cname)
1918             code.putln("0};")
1919
1920     def generate_argument_parsing_code(self, env, code):
1921         # Generate PyArg_ParseTuple call for generic
1922         # arguments, if any.
1923         if self.entry.signature.has_dummy_arg:
1924             # get rid of unused argument warning
1925             code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1926
1927         old_error_label = code.new_error_label()
1928         our_error_label = code.error_label
1929         end_label = code.new_label("argument_unpacking_done")
1930
1931         has_kwonly_args = self.num_kwonly_args > 0
1932         has_star_or_kw_args = self.star_arg is not None \
1933             or self.starstar_arg is not None or has_kwonly_args
1934
1935         for arg in self.args:
1936             if not arg.type.is_pyobject and arg.type.from_py_function is None:
1937                 arg.type.create_from_py_utility_code(env)
1938
1939         if not self.signature_has_generic_args():
1940             if has_star_or_kw_args:
1941                 error(self.pos, "This method cannot have * or keyword arguments")
1942             self.generate_argument_conversion_code(code)
1943
1944         elif not self.signature_has_nongeneric_args():
1945             # func(*args) or func(**kw) or func(*args, **kw)
1946             self.generate_stararg_copy_code(code)
1947
1948         else:
1949             positional_args = []
1950             kw_only_args = []
1951             default_seen = 0
1952             for arg in self.args:
1953                 arg_entry = arg.entry
1954                 if arg.is_generic:
1955                     if arg.default:
1956                         default_seen = 1
1957                         if not arg.is_self_arg:
1958                             if arg.kw_only:
1959                                 kw_only_args.append(arg)
1960                             else:
1961                                 positional_args.append(arg)
1962                     elif arg.kw_only:
1963                         kw_only_args.append(arg)
1964                         default_seen = 1
1965                     elif default_seen:
1966                         error(arg.pos, "Non-default argument following default argument")
1967                     elif not arg.is_self_arg:
1968                         positional_args.append(arg)
1969
1970             self.generate_tuple_and_keyword_parsing_code(
1971                 positional_args, kw_only_args, end_label, code)
1972
1973         code.error_label = old_error_label
1974         if code.label_used(our_error_label):
1975             if not code.label_used(end_label):
1976                 code.put_goto(end_label)
1977             code.put_label(our_error_label)
1978             if has_star_or_kw_args:
1979                 self.generate_arg_decref(self.star_arg, code)
1980                 if self.starstar_arg:
1981                     if self.starstar_arg.entry.xdecref_cleanup:
1982                         code.put_var_xdecref(self.starstar_arg.entry)
1983                     else:
1984                         code.put_var_decref(self.starstar_arg.entry)
1985             code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1986             code.putln("return %s;" % self.error_value())
1987         if code.label_used(end_label):
1988             code.put_label(end_label)
1989
1990     def generate_arg_assignment(self, arg, item, code):
1991         if arg.type.is_pyobject:
1992             if arg.is_generic:
1993                 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1994             code.putln("%s = %s;" % (arg.entry.cname, item))
1995         else:
1996             func = arg.type.from_py_function
1997             if func:
1998                 code.putln("%s = %s(%s); %s" % (
1999                     arg.entry.cname,
2000                     func,
2001                     item,
2002                     code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
2003             else:
2004                 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
2005     
2006     def generate_arg_xdecref(self, arg, code):
2007         if arg:
2008             code.put_var_xdecref(arg.entry)
2009     
2010     def generate_arg_decref(self, arg, code):
2011         if arg:
2012             code.put_var_decref(arg.entry)
2013
2014     def generate_stararg_copy_code(self, code):
2015         if not self.star_arg:
2016             code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2017             code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
2018                        Naming.args_cname)
2019             code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
2020                     self.name.utf8encode(), Naming.args_cname, self.error_value()))
2021             code.putln("}")
2022
2023         code.globalstate.use_utility_code(keyword_string_check_utility_code)
2024
2025         if self.starstar_arg:
2026             if self.star_arg:
2027                 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
2028             else:
2029                 kwarg_check = "%s" % Naming.kwds_cname
2030         else:
2031             kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2032                 Naming.kwds_cname, Naming.kwds_cname)
2033         code.putln(
2034             "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2035                 kwarg_check, Naming.kwds_cname, self.name,
2036                 bool(self.starstar_arg), self.error_value()))
2037
2038         if self.starstar_arg:
2039             code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2040                     self.starstar_arg.entry.cname,
2041                     Naming.kwds_cname,
2042                     Naming.kwds_cname))
2043             code.putln("if (unlikely(!%s)) return %s;" % (
2044                     self.starstar_arg.entry.cname, self.error_value()))
2045             self.starstar_arg.entry.xdecref_cleanup = 0
2046             code.put_gotref(self.starstar_arg.entry.cname)
2047             
2048
2049         if self.star_arg:
2050             code.put_incref(Naming.args_cname, py_object_type)
2051             code.putln("%s = %s;" % (
2052                     self.star_arg.entry.cname,
2053                     Naming.args_cname))
2054             self.star_arg.entry.xdecref_cleanup = 0
2055
2056     def generate_tuple_and_keyword_parsing_code(self, positional_args,
2057                                                 kw_only_args, success_label, code):
2058         argtuple_error_label = code.new_label("argtuple_error")
2059
2060         min_positional_args = self.num_required_args - self.num_required_kw_args
2061         if len(self.args) > 0 and self.args[0].is_self_arg:
2062             min_positional_args -= 1
2063         max_positional_args = len(positional_args)
2064         has_fixed_positional_count = not self.star_arg and \
2065             min_positional_args == max_positional_args
2066
2067         code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2068         code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2069         if self.num_required_kw_args:
2070             code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2071
2072         if self.starstar_arg or self.star_arg:
2073             self.generate_stararg_init_code(max_positional_args, code)
2074
2075         # --- optimised code when we receive keyword arguments
2076         if self.num_required_kw_args:
2077             likely_hint = "likely"
2078         else:
2079             likely_hint = "unlikely"
2080         code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2081         self.generate_keyword_unpacking_code(
2082             min_positional_args, max_positional_args,
2083             has_fixed_positional_count,
2084             positional_args, kw_only_args, argtuple_error_label, code)
2085
2086         # --- optimised code when we do not receive any keyword arguments
2087         if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2088             # Python raises arg tuple related errors first, so we must
2089             # check the length here
2090             if min_positional_args == max_positional_args and not self.star_arg:
2091                 compare = '!='
2092             else:
2093                 compare = '<'
2094             code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2095                     Naming.args_cname, compare, min_positional_args))
2096             code.put_goto(argtuple_error_label)
2097
2098         if self.num_required_kw_args:
2099             # pure error case: keywords required but not passed
2100             if max_positional_args > min_positional_args and not self.star_arg:
2101                 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2102                         Naming.args_cname, max_positional_args))
2103                 code.put_goto(argtuple_error_label)
2104             code.putln('} else {')
2105             for i, arg in enumerate(kw_only_args):
2106                 if not arg.default:
2107                     # required keyword-only argument missing
2108                     code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2109                             self.name.utf8encode(),
2110                             arg.name_entry.pystring_cname))
2111                     code.putln(code.error_goto(self.pos))
2112                     break
2113
2114         elif min_positional_args == max_positional_args:
2115             # parse the exact number of positional arguments from the
2116             # args tuple
2117             code.putln('} else {')
2118             for i, arg in enumerate(positional_args):
2119                 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2120                 self.generate_arg_assignment(arg, item, code)
2121             self.generate_arg_default_assignments(code)
2122
2123         else:
2124             # parse the positional arguments from the variable length
2125             # args tuple
2126             code.putln('} else {')
2127             self.generate_arg_default_assignments(code)
2128             code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2129             if self.star_arg:
2130                 code.putln('default:')
2131             reversed_args = list(enumerate(positional_args))[::-1]
2132             for i, arg in reversed_args:
2133                 if i >= min_positional_args-1:
2134                     if min_positional_args > 1:
2135                         code.putln('case %2d:' % (i+1)) # pure code beautification
2136                     else:
2137                         code.put('case %2d: ' % (i+1))
2138                 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2139                 self.generate_arg_assignment(arg, item, code)
2140             if min_positional_args == 0:
2141                 code.put('case  0: ')
2142             code.putln('break;')
2143             if self.star_arg:
2144                 if min_positional_args:
2145                     for i in range(min_positional_args-1, -1, -1):
2146                         code.putln('case %2d:' % i)
2147                     code.put_goto(argtuple_error_label)
2148             else:
2149                 code.put('default: ')
2150                 code.put_goto(argtuple_error_label)
2151             code.putln('}')
2152
2153         code.putln('}')
2154
2155         if code.label_used(argtuple_error_label):
2156             code.put_goto(success_label)
2157             code.put_label(argtuple_error_label)
2158             code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2159                     self.name.utf8encode(), has_fixed_positional_count,
2160                     min_positional_args, max_positional_args,
2161                     Naming.args_cname))
2162             code.putln(code.error_goto(self.pos))
2163
2164     def generate_arg_default_assignments(self, code):
2165         for arg in self.args:
2166             if arg.is_generic and arg.default:
2167                 code.putln(
2168                     "%s = %s;" % (
2169                         arg.entry.cname,
2170                         arg.default_result_code))
2171
2172     def generate_stararg_init_code(self, max_positional_args, code):
2173         if self.starstar_arg:
2174             self.starstar_arg.entry.xdecref_cleanup = 0
2175             code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2176                     self.starstar_arg.entry.cname,
2177                     self.starstar_arg.entry.cname,
2178                     self.error_value()))
2179             code.put_gotref(self.starstar_arg.entry.cname)
2180         if self.star_arg:
2181             self.star_arg.entry.xdecref_cleanup = 0
2182             code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2183                     Naming.args_cname,
2184                     max_positional_args))
2185             code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2186                     self.star_arg.entry.cname, Naming.args_cname,
2187                     max_positional_args, Naming.args_cname))
2188             code.put_gotref(self.star_arg.entry.cname)
2189             if self.starstar_arg:
2190                 code.putln("")
2191                 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2192                 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2193                 code.putln('return %s;' % self.error_value())
2194                 code.putln('}')
2195             else:
2196                 code.putln("if (unlikely(!%s)) return %s;" % (
2197                         self.star_arg.entry.cname, self.error_value()))
2198             code.putln('} else {')
2199             code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2200             code.put_incref(Naming.empty_tuple, py_object_type)
2201             code.putln('}')
2202
2203     def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2204                                         has_fixed_positional_count, positional_args,
2205                                         kw_only_args, argtuple_error_label, code):
2206         all_args = tuple(positional_args) + tuple(kw_only_args)
2207         max_args = len(all_args)
2208
2209         default_args = []
2210         for i, arg in enumerate(all_args):
2211             if arg.default and arg.type.is_pyobject:
2212                 default_value = arg.default_result_code
2213                 if arg.type is not PyrexTypes.py_object_type:
2214                     default_value = "(PyObject*)"+default_value
2215                 default_args.append((i, default_value))
2216
2217         code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2218                    Naming.kwds_cname)
2219         # it looks funny to separate the init-to-0 from setting the
2220         # default value, but C89 needs this
2221         code.putln("PyObject* values[%d] = {%s};" % (
2222             max_args, ','.join(['0']*max_args)))
2223         for i, default_value in default_args:
2224             code.putln('values[%d] = %s;' % (i, default_value))
2225
2226         # parse the tuple and check that it's not too long
2227         code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2228         if self.star_arg:
2229             code.putln('default:')
2230         for i in range(max_positional_args-1, -1, -1):
2231             code.put('case %2d: ' % (i+1))
2232             code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2233                     i, Naming.args_cname, i))
2234         code.putln('case  0: break;')
2235         if not self.star_arg:
2236             code.put('default: ') # more arguments than allowed
2237             code.put_goto(argtuple_error_label)
2238         code.putln('}')
2239
2240         # now fill up the positional/required arguments with values
2241         # from the kw dict
2242         if self.num_required_args or max_positional_args > 0:
2243             last_required_arg = -1
2244             for i, arg in enumerate(all_args):
2245                 if not arg.default:
2246                     last_required_arg = i
2247             if last_required_arg < max_positional_args:
2248                 last_required_arg = max_positional_args-1
2249             num_required_args = self.num_required_args
2250             if max_positional_args > 0:
2251                 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2252             for i, arg in enumerate(all_args[:last_required_arg+1]):
2253                 if max_positional_args > 0 and i <= max_positional_args:
2254                     if self.star_arg and i == max_positional_args:
2255                         code.putln('default:')
2256                     else:
2257                         code.putln('case %2d:' % i)
2258                 if arg.default:
2259                     if arg.kw_only:
2260                         # handled separately below
2261                         continue
2262                     code.putln('if (kw_args > %d) {' % num_required_args)
2263                     code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2264                         Naming.kwds_cname, arg.name_entry.pystring_cname))
2265                     code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2266                     code.putln('}')
2267                 else:
2268                     num_required_args -= 1
2269                     code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2270                         i, Naming.kwds_cname, arg.name_entry.pystring_cname))
2271                     code.putln('if (likely(values[%d])) kw_args--;' % i);
2272                     if i < min_positional_args:
2273                         if i == 0:
2274                             # special case: we know arg 0 is missing
2275                             code.put('else ')
2276                             code.put_goto(argtuple_error_label)
2277                         else:
2278                             # print the correct number of values (args or
2279                             # kwargs) that were passed into positional
2280                             # arguments up to this point
2281                             code.putln('else {')
2282                             code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2283                                     self.name.utf8encode(), has_fixed_positional_count,
2284                                     min_positional_args, max_positional_args, i))
2285                             code.putln(code.error_goto(self.pos))
2286                             code.putln('}')
2287                     elif arg.kw_only:
2288                         code.putln('else {')
2289                         code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2290                                 self.name.utf8encode(), arg.name_entry.pystring_cname))
2291                         code.putln(code.error_goto(self.pos))
2292                         code.putln('}')
2293             if max_positional_args > 0:
2294                 code.putln('}')
2295
2296         if kw_only_args and not self.starstar_arg:
2297             # unpack optional keyword-only arguments
2298             # checking for interned strings in a dict is faster than iterating
2299             # but it's too likely that we must iterate if we expect **kwargs
2300             optional_args = []
2301             for i, arg in enumerate(all_args[max_positional_args:]):
2302                 if not arg.kw_only or not arg.default:
2303                     continue
2304                 optional_args.append((i+max_positional_args, arg))
2305             if optional_args:
2306                 # this mimics an unrolled loop so that we can "break" out of it
2307                 code.putln('while (kw_args > 0) {')
2308                 code.putln('PyObject* value;')
2309                 for i, arg in optional_args:
2310                     code.putln(
2311                         'value = PyDict_GetItem(%s, %s);' % (
2312                         Naming.kwds_cname, arg.name_entry.pystring_cname))
2313                     code.putln(
2314                         'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2315                 code.putln('break;')
2316                 code.putln('}')
2317
2318         code.putln('if (unlikely(kw_args > 0)) {')
2319         # non-positional/-required kw args left in dict: default args,
2320         # kw-only args, **kwargs or error
2321         #
2322         # This is sort of a catch-all: except for checking required
2323         # arguments, this will always do the right thing for unpacking
2324         # keyword arguments, so that we can concentrate on optimising
2325         # common cases above.
2326         if max_positional_args == 0:
2327             pos_arg_count = "0"
2328         elif self.star_arg:
2329             code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2330                     Naming.args_cname, max_positional_args,
2331                     Naming.args_cname, max_positional_args))
2332             pos_arg_count = "used_pos_args"
2333         else:
2334             pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2335         code.globalstate.use_utility_code(parse_keywords_utility_code)
2336         code.put(
2337             'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2338                 Naming.kwds_cname,
2339                 Naming.pykwdlist_cname,
2340                 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2341                 pos_arg_count,
2342                 self.name.utf8encode()))
2343         code.putln(code.error_goto(self.pos))
2344         code.putln('}')
2345
2346         # convert arg values to their final type and assign them
2347         for i, arg in enumerate(all_args):
2348             if arg.default and not arg.type.is_pyobject:
2349                 code.putln("if (values[%d]) {" % i)
2350             self.generate_arg_assignment(arg, "values[%d]" % i, code)
2351             if arg.default and not arg.type.is_pyobject:
2352                 code.putln('} else {')
2353                 code.putln(
2354                     "%s = %s;" % (
2355                         arg.entry.cname,
2356                         arg.default_result_code))
2357                 code.putln('}')
2358
2359     def generate_argument_conversion_code(self, code):
2360         # Generate code to convert arguments from
2361         # signature type to declared type, if needed.
2362         for arg in self.args:
2363             if arg.needs_conversion:
2364                 self.generate_arg_conversion(arg, code)
2365
2366     def generate_arg_conversion(self, arg, code):
2367         # Generate conversion code for one argument.
2368         old_type = arg.hdr_type
2369         new_type = arg.type
2370         if old_type.is_pyobject:
2371             if arg.default:
2372                 code.putln("if (%s) {" % arg.hdr_cname)
2373             else:
2374                 code.putln("assert(%s); {" % arg.hdr_cname)
2375             self.generate_arg_conversion_from_pyobject(arg, code)
2376             code.putln("}")
2377         elif new_type.is_pyobject:
2378             self.generate_arg_conversion_to_pyobject(arg, code)
2379         else:
2380             if new_type.assignable_from(old_type):
2381                 code.putln(
2382                     "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2383             else:
2384                 error(arg.pos,
2385                     "Cannot convert 1 argument from '%s' to '%s'" %
2386                         (old_type, new_type))
2387     
2388     def generate_arg_conversion_from_pyobject(self, arg, code):
2389         new_type = arg.type
2390         func = new_type.from_py_function
2391         # copied from CoerceFromPyTypeNode
2392         if func:
2393             code.putln("%s = %s(%s); %s" % (
2394                 arg.entry.cname,
2395                 func,
2396                 arg.hdr_cname,
2397                 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2398         else:
2399             error(arg.pos, 
2400                 "Cannot convert Python object argument to type '%s'" 
2401                     % new_type)
2402     
2403     def generate_arg_conversion_to_pyobject(self, arg, code):
2404         old_type = arg.hdr_type
2405         func = old_type.to_py_function
2406         if func:
2407             code.putln("%s = %s(%s); %s" % (
2408                 arg.entry.cname,
2409                 func,
2410                 arg.hdr_cname,
2411                 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2412             code.put_var_gotref(arg.entry)
2413         else:
2414             error(arg.pos,
2415                 "Cannot convert argument of type '%s' to Python object"
2416                     % old_type)
2417
2418     def generate_argument_type_tests(self, code):
2419         # Generate type tests for args whose signature
2420         # type is PyObject * and whose declared type is
2421         # a subtype thereof.
2422         for arg in self.args:
2423             if arg.needs_type_test:
2424                 self.generate_arg_type_test(arg, code)
2425     
2426     def generate_arg_type_test(self, arg, code):
2427         # Generate type test for one argument.
2428         if arg.type.typeobj_is_available():
2429             typeptr_cname = arg.type.typeptr_cname
2430             arg_code = "((PyObject *)%s)" % arg.entry.cname
2431             code.putln(
2432                 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2433                     arg_code, 
2434                     typeptr_cname,
2435                     not arg.not_none,
2436                     arg.name,
2437                     arg.type.is_builtin_type,
2438                     code.error_goto(arg.pos)))
2439         else:
2440             error(arg.pos, "Cannot test type of extern C class "
2441                 "without type object name specification")
2442     
2443     def error_value(self):
2444         return self.entry.signature.error_value
2445     
2446     def caller_will_check_exceptions(self):
2447         return 1
2448             
2449 class OverrideCheckNode(StatNode):
2450     # A Node for dispatching to the def method if it
2451     # is overriden. 
2452     #
2453     #  py_func
2454     #
2455     #  args
2456     #  func_temp
2457     #  body
2458     
2459     child_attrs = ['body']
2460     
2461     body = None
2462
2463     def analyse_expressions(self, env):
2464         self.args = env.arg_entries
2465         if self.py_func.is_module_scope:
2466             first_arg = 0
2467         else:
2468             first_arg = 1
2469         import ExprNodes
2470         self.func_node = ExprNodes.PyTempNode(self.pos, env)
2471         call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2472         call_node = ExprNodes.SimpleCallNode(self.pos,
2473                                              function=self.func_node, 
2474                                              args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2475         self.body = ReturnStatNode(self.pos, value=call_node)
2476         self.body.analyse_expressions(env)
2477         
2478     def generate_execution_code(self, code):
2479         # Check to see if we are an extension type
2480         if self.py_func.is_module_scope:
2481             self_arg = "((PyObject *)%s)" % Naming.module_cname
2482         else:
2483             self_arg = "((PyObject *)%s)" % self.args[0].cname
2484         code.putln("/* Check if called by wrapper */")
2485         code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2486         code.putln("/* Check if overriden in Python */")
2487         if self.py_func.is_module_scope:
2488             code.putln("else {")
2489         else:
2490             code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2491         err = code.error_goto_if_null(self.func_node.result(), self.pos)
2492         # need to get attribute manually--scope would return cdef method
2493         code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2494         code.put_gotref(self.func_node.py_result())
2495         is_builtin_function_or_method = 'PyCFunction_Check(%s)' % self.func_node.result()
2496         is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2497         code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
2498         self.body.generate_execution_code(code)
2499         code.putln('}')
2500         code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2501         code.putln("}")
2502
2503 class ClassDefNode(StatNode, BlockNode):
2504     pass
2505
2506 class PyClassDefNode(ClassDefNode):
2507     #  A Python class definition.
2508     #
2509     #  name     EncodedString   Name of the class
2510     #  doc      string or None
2511     #  body     StatNode        Attribute definition code
2512     #  entry    Symtab.Entry
2513     #  scope    PyClassScope
2514     #
2515     #  The following subnodes are constructed internally:
2516     #
2517     #  dict     DictNode   Class dictionary
2518     #  classobj ClassNode  Class object
2519     #  target   NameNode   Variable to assign class object to
2520
2521     child_attrs = ["body", "dict", "classobj", "target"]
2522     
2523     def __init__(self, pos, name, bases, doc, body):
2524         StatNode.__init__(self, pos)
2525         self.name = name
2526         self.doc = doc
2527         self.body = body
2528         import ExprNodes
2529         self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2530         if self.doc and Options.docstrings:
2531             doc = embed_position(self.pos, self.doc)
2532             doc_node = ExprNodes.StringNode(pos, value = doc)
2533         else:
2534             doc_node = None
2535         self.classobj = ExprNodes.ClassNode(pos, name = name,
2536             bases = bases, dict = self.dict, doc = doc_node)
2537         self.target = ExprNodes.NameNode(pos, name = name)
2538         
2539     def as_cclass(self):
2540         """
2541         Return this node as if it were declared as an extension class
2542         """
2543         bases = self.classobj.bases.args
2544         if len(bases) == 0:
2545             base_class_name = None
2546             base_class_module = None
2547         elif len(bases) == 1:
2548             base = bases[0]
2549             path = []
2550             from ExprNodes import AttributeNode, NameNode
2551             while isinstance(base, AttributeNode):
2552                 path.insert(0, base.attribute)
2553                 base = base.obj
2554             if isinstance(base, NameNode):
2555                 path.insert(0, base.name)
2556                 base_class_name = path[-1]
2557                 if len(path) > 1:
2558                     base_class_module = u'.'.join(path[:-1])
2559                 else:
2560                     base_class_module = None
2561             else:
2562                 error(self.classobj.bases.args.pos, "Invalid base class")
2563         else:
2564             error(self.classobj.bases.args.pos, "C class may only have one base class")
2565             return None
2566         
2567         return CClassDefNode(self.pos, 
2568                              visibility = 'private',
2569                              module_name = None,
2570                              class_name = self.name,
2571                              base_class_module = base_class_module,
2572                              base_class_name = base_class_name,
2573                              body = self.body,
2574                              in_pxd = False,
2575                              doc = self.doc)
2576         
2577     def create_scope(self, env):
2578         genv = env
2579         while env.is_py_class_scope or env.is_c_class_scope:
2580             env = env.outer_scope
2581         cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2582         return cenv
2583     
2584     def analyse_declarations(self, env):
2585         self.target.analyse_target_declaration(env)
2586         cenv = self.create_scope(env)
2587         cenv.directives = env.directives
2588         cenv.class_obj_cname = self.target.entry.cname
2589         self.body.analyse_declarations(cenv)
2590     
2591     def analyse_expressions(self, env):
2592         self.dict.analyse_expressions(env)
2593         self.classobj.analyse_expressions(env)
2594         genv = env.global_scope()
2595         cenv = self.scope
2596         cenv.class_dict_cname = self.dict.result()
2597         cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2598         self.body.analyse_expressions(cenv)
2599         self.target.analyse_target_expression(env, self.classobj)
2600         self.dict.release_temp(env)
2601         #self.classobj.release_temp(env)
2602         #self.target.release_target_temp(env)
2603     
2604     def generate_function_definitions(self, env, code):
2605         self.generate_py_string_decls(self.scope, code)
2606         self.body.generate_function_definitions(self.scope, code)
2607     
2608     def generate_execution_code(self, code):
2609         self.dict.generate_evaluation_code(code)
2610         self.classobj.generate_evaluation_code(code)
2611         self.body.generate_execution_code(code)
2612         self.target.generate_assignment_code(self.classobj, code)
2613         self.dict.generate_disposal_code(code)
2614         self.dict.free_temps(code)
2615
2616
2617 class CClassDefNode(ClassDefNode):
2618     #  An extension type definition.
2619     #
2620     #  visibility         'private' or 'public' or 'extern'
2621     #  typedef_flag       boolean
2622     #  api                boolean
2623     #  module_name        string or None    For import of extern type objects
2624     #  class_name         string            Unqualified name of class
2625     #  as_name            string or None    Name to declare as in this scope
2626     #  base_class_module  string or None    Module containing the base class
2627     #  base_class_name    string or None    Name of the base class
2628     #  objstruct_name     string or None    Specified C name of object struct
2629     #  typeobj_name       string or None    Specified C name of type object
2630     #  in_pxd             boolean           Is in a .pxd file
2631     #  doc                string or None
2632     #  body               StatNode or None
2633     #  entry              Symtab.Entry
2634     #  base_type          PyExtensionType or None
2635     #  buffer_defaults_node DictNode or None Declares defaults for a buffer
2636     #  buffer_defaults_pos
2637
2638     child_attrs = ["body"]
2639     buffer_defaults_node = None
2640     buffer_defaults_pos = None
2641     typedef_flag = False
2642     api = False
2643     objstruct_name = None
2644     typeobj_name = None
2645
2646     def analyse_declarations(self, env):
2647         #print "CClassDefNode.analyse_declarations:", self.class_name
2648         #print "...visibility =", self.visibility
2649         #print "...module_name =", self.module_name
2650
2651         import Buffer
2652         if self.buffer_defaults_node:
2653             buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2654                                                             env, [], self.buffer_defaults_node,
2655                                                             need_complete=False)
2656         else:
2657             buffer_defaults = None
2658
2659         if env.in_cinclude and not self.objstruct_name:
2660             error(self.pos, "Object struct name specification required for "
2661                 "C class defined in 'extern from' block")
2662         self.base_type = None
2663         # Now that module imports are cached, we need to 
2664         # import the modules for extern classes. 
2665         if self.module_name:
2666             self.module = None
2667             for module in env.cimported_modules:
2668                 if module.name == self.module_name:
2669                     self.module = module
2670             if self.module is None:
2671                 self.module = ModuleScope(self.module_name, None, env.context)
2672                 self.module.has_extern_class = 1
2673                 env.add_imported_module(self.module)
2674
2675         if self.base_class_name:
2676             if self.base_class_module:
2677                 base_class_scope = env.find_module(self.base_class_module, self.pos)
2678             else:
2679                 base_class_scope = env
2680             if self.base_class_name == 'object':
2681                 # extension classes are special and don't need to inherit from object
2682                 if base_class_scope is None or base_class_scope.lookup('object') is None:
2683                     self.base_class_name = None
2684                     self.base_class_module = None
2685                     base_class_scope = None
2686             if base_class_scope:
2687                 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2688                 if base_class_entry:
2689                     if not base_class_entry.is_type:
2690                         error(self.pos, "'%s' is not a type name" % self.base_class_name)
2691                     elif not base_class_entry.type.is_extension_type:
2692                         error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2693                     elif not base_class_entry.type.is_complete():
2694                         error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2695                     else:
2696                         self.base_type = base_class_entry.type
2697         has_body = self.body is not None
2698         if self.module_name and self.visibility != 'extern':
2699             module_path = self.module_name.split(".")
2700             home_scope = env.find_imported_module(module_path, self.pos)
2701             if not home_scope:
2702                 return
2703         else:
2704             home_scope = env
2705
2706         if self.visibility == 'extern':
2707             if self.module_name == '__builtin__' and self.class_name in Builtin.builtin_types:
2708                 warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
2709
2710         self.entry = home_scope.declare_c_class(
2711             name = self.class_name, 
2712             pos = self.pos,
2713             defining = has_body and self.in_pxd,
2714             implementing = has_body and not self.in_pxd,
2715             module_name = self.module_name,
2716             base_type = self.base_type,
2717             objstruct_cname = self.objstruct_name,
2718             typeobj_cname = self.typeobj_name,
2719             visibility = self.visibility,
2720             typedef_flag = self.typedef_flag,
2721             api = self.api,
2722             buffer_defaults = buffer_defaults)
2723         if home_scope is not env and self.visibility == 'extern':
2724             env.add_imported_entry(self.class_name, self.entry, pos)
2725         scope = self.entry.type.scope
2726         if scope is not None:
2727             scope.directives = env.directives
2728
2729         if self.doc and Options.docstrings:
2730             scope.doc = embed_position(self.pos, self.doc)
2731             
2732         if has_body:
2733             self.body.analyse_declarations(scope)
2734             if self.in_pxd:
2735                 scope.defined = 1
2736             else:
2737                 scope.implemented = 1
2738         env.allocate_vtable_names(self.entry)
2739         
2740     def analyse_expressions(self, env):
2741         if self.body:
2742             scope = self.entry.type.scope
2743             self.body.analyse_expressions(scope)
2744     
2745     def generate_function_definitions(self, env, code):
2746         self.generate_py_string_decls(self.entry.type.scope, code)
2747         if self.body:
2748             self.body.generate_function_definitions(
2749                 self.entry.type.scope, code)
2750     
2751     def generate_execution_code(self, code):
2752         # This is needed to generate evaluation code for
2753         # default values of method arguments.
2754         if self.body:
2755             self.body.generate_execution_code(code)
2756             
2757     def annotate(self, code):
2758         if self.body:
2759             self.body.annotate(code)
2760
2761
2762 class PropertyNode(StatNode):
2763     #  Definition of a property in an extension type.
2764     #
2765     #  name   string
2766     #  doc    EncodedString or None    Doc string
2767     #  body   StatListNode
2768     
2769     child_attrs = ["body"]
2770
2771     def analyse_declarations(self, env):
2772         entry = env.declare_property(self.name, self.doc, self.pos)
2773         if entry:
2774             if self.doc and Options.docstrings:
2775                 doc_entry = env.get_string_const(
2776                     self.doc, identifier = False)
2777                 entry.doc_cname = doc_entry.cname
2778             entry.scope.directives = env.directives
2779             self.body.analyse_declarations(entry.scope)
2780
2781     def analyse_expressions(self, env):
2782         self.body.analyse_expressions(env)
2783     
2784     def generate_function_definitions(self, env, code):
2785         self.body.generate_function_definitions(env, code)
2786
2787     def generate_execution_code(self, code):
2788         pass
2789
2790     def annotate(self, code):
2791         self.body.annotate(code)
2792
2793
2794 class GlobalNode(StatNode):
2795     # Global variable declaration.
2796     #
2797     # names    [string]
2798     
2799     child_attrs = []
2800
2801     def analyse_declarations(self, env):
2802         for name in self.names:
2803             env.declare_global(name, self.pos)
2804
2805     def analyse_expressions(self, env):
2806         pass
2807     
2808     def generate_execution_code(self, code):
2809         pass
2810
2811
2812 class ExprStatNode(StatNode):
2813     #  Expression used as a statement.
2814     #
2815     #  expr   ExprNode
2816
2817     child_attrs = ["expr"]
2818     
2819     def analyse_declarations(self, env):
2820         import ExprNodes
2821         if isinstance(self.expr, ExprNodes.GeneralCallNode):
2822             func = self.expr.function.as_cython_attribute()
2823             if func == u'declare':
2824                 args, kwds = self.expr.explicit_args_kwds()
2825                 if len(args):
2826                     error(self.expr.pos, "Variable names must be specified.")
2827                 for var, type_node in kwds.key_value_pairs:
2828                     type = type_node.analyse_as_type(env)
2829                     if type is None:
2830                         error(type_node.pos, "Unknown type")
2831                     else:
2832                         env.declare_var(var.value, type, var.pos, is_cdef = True)
2833                 self.__class__ = PassStatNode
2834     
2835     def analyse_expressions(self, env):
2836         self.expr.analyse_expressions(env)
2837         self.expr.release_temp(env)
2838     
2839     def generate_execution_code(self, code):
2840         self.expr.generate_evaluation_code(code)
2841         if not self.expr.is_temp and self.expr.result():
2842             code.putln("%s;" % self.expr.result())
2843         self.expr.generate_disposal_code(code)
2844         self.expr.free_temps(code)
2845
2846     def annotate(self, code):
2847         self.expr.annotate(code)
2848
2849
2850 class AssignmentNode(StatNode):
2851     #  Abstract base class for assignment nodes.
2852     #
2853     #  The analyse_expressions and generate_execution_code
2854     #  phases of assignments are split into two sub-phases
2855     #  each, to enable all the right hand sides of a
2856     #  parallel assignment to be evaluated before assigning
2857     #  to any of the left hand sides.
2858
2859     def analyse_expressions(self, env):
2860         self.analyse_types(env)
2861         self.allocate_rhs_temps(env)
2862         self.allocate_lhs_temps(env)
2863
2864 #       def analyse_expressions(self, env):
2865 #           self.analyse_expressions_1(env)
2866 #           self.analyse_expressions_2(env)
2867
2868     def generate_execution_code(self, code):
2869         self.generate_rhs_evaluation_code(code)
2870         self.generate_assignment_code(code)
2871         
2872
2873 class SingleAssignmentNode(AssignmentNode):
2874     #  The simplest case:
2875     #
2876     #    a = b
2877     #
2878     #  lhs      ExprNode      Left hand side
2879     #  rhs      ExprNode      Right hand side
2880     #  first    bool          Is this guaranteed the first assignment to lhs?
2881     
2882     child_attrs = ["lhs", "rhs"]
2883     first = False
2884     declaration_only = False
2885
2886     def analyse_declarations(self, env):
2887         import ExprNodes
2888         
2889         # handle declarations of the form x = cython.foo()
2890         if isinstance(self.rhs, ExprNodes.CallNode):
2891             func_name = self.rhs.function.as_cython_attribute()
2892             if func_name:
2893                 args, kwds = self.rhs.explicit_args_kwds()
2894                 
2895                 if func_name in ['declare', 'typedef']:
2896                     if len(args) > 2 or kwds is not None:
2897                         error(rhs.pos, "Can only declare one type at a time.")
2898                         return
2899                     type = args[0].analyse_as_type(env)
2900                     if type is None:
2901                         error(args[0].pos, "Unknown type")
2902                         return
2903                     lhs = self.lhs
2904                     if func_name == 'declare':
2905                         if isinstance(lhs, ExprNodes.NameNode):
2906                             vars = [(lhs.name, lhs.pos)]
2907                         elif isinstance(lhs, ExprNodes.TupleNode):
2908                             vars = [(var.name, var.pos) for var in lhs.args]
2909                         else:
2910                             error(lhs.pos, "Invalid declaration")
2911                             return
2912                         for var, pos in vars:
2913                             env.declare_var(var, type, pos, is_cdef = True)
2914                         if len(args) == 2:
2915                             # we have a value
2916                             self.rhs = args[1]
2917                         else:
2918                             self.declaration_only = True
2919                     else:
2920                         self.declaration_only = True
2921                         if not isinstance(lhs, ExprNodes.NameNode):
2922                             error(lhs.pos, "Invalid declaration.")
2923                         env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2924                     
2925                 elif func_name in ['struct', 'union']:
2926                     self.declaration_only = True
2927                     if len(args) > 0 or kwds is None:
2928                         error(rhs.pos, "Struct or union members must be given by name.")
2929                         return
2930                     members = []
2931                     for member, type_node in kwds.key_value_pairs:
2932                         type = type_node.analyse_as_type(env)
2933                         if type is None:
2934                             error(type_node.pos, "Unknown type")
2935                         else:
2936                             members.append((member.value, type, member.pos))
2937                     if len(members) < len(kwds.key_value_pairs):
2938                         return
2939                     if not isinstance(self.lhs, ExprNodes.NameNode):
2940                         error(self.lhs.pos, "Invalid declaration.")
2941                     name = self.lhs.name
2942                     scope = StructOrUnionScope(name)
2943                     env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2944                     for member, type, pos in members:
2945                         scope.declare_var(member, type, pos)
2946                     
2947         if self.declaration_only:
2948             return
2949         else:
2950             self.lhs.analyse_target_declaration(env)
2951     
2952     def analyse_types(self, env, use_temp = 0):
2953         self.rhs.analyse_types(env)
2954         self.lhs.analyse_target_types(env)
2955         self.lhs.gil_assignment_check(env)
2956         self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2957         if use_temp:
2958             self.rhs = self.rhs.coerce_to_temp(env)
2959     
2960     def allocate_rhs_temps(self, env):
2961         self.rhs.allocate_temps(env)
2962
2963     def allocate_lhs_temps(self, env):
2964         self.lhs.allocate_target_temps(env, self.rhs)
2965         #self.lhs.release_target_temp(env)
2966         #self.rhs.release_temp(env)
2967
2968     def generate_rhs_evaluation_code(self, code):
2969         self.rhs.generate_evaluation_code(code)
2970     
2971     def generate_assignment_code(self, code):
2972         self.lhs.generate_assignment_code(self.rhs, code)
2973
2974     def annotate(self, code):
2975         self.lhs.annotate(code)
2976         self.rhs.annotate(code)
2977
2978
2979 class CascadedAssignmentNode(AssignmentNode):
2980     #  An assignment with multiple left hand sides:
2981     #
2982     #    a = b = c
2983     #
2984     #  lhs_list   [ExprNode]   Left hand sides
2985     #  rhs        ExprNode     Right hand sides
2986     #
2987     #  Used internally:
2988     #
2989     #  coerced_rhs_list   [ExprNode]   RHS coerced to type of each LHS
2990     
2991     child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2992     coerced_rhs_list = None
2993
2994     def analyse_declarations(self, env):
2995         for lhs in self.lhs_list:
2996             lhs.analyse_target_declaration(env)
2997     
2998     def analyse_types(self, env, use_temp = 0):
2999         self.rhs.analyse_types(env)
3000         if use_temp:
3001             self.rhs = self.rhs.coerce_to_temp(env)
3002         else:
3003             self.rhs = self.rhs.coerce_to_simple(env)
3004         from ExprNodes import CloneNode
3005         self.coerced_rhs_list = []
3006         for lhs in self.lhs_list:
3007             lhs.analyse_target_types(env)
3008             lhs.gil_assignment_check(env)
3009             rhs = CloneNode(self.rhs)
3010             rhs = rhs.coerce_to(lhs.type, env)
3011             self.coerced_rhs_list.append(rhs)
3012
3013     def allocate_rhs_temps(self, env):
3014         self.rhs.allocate_temps(env)
3015     
3016     def allocate_lhs_temps(self, env):
3017         for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
3018             rhs.allocate_temps(env)
3019             lhs.allocate_target_temps(env, rhs)
3020             #lhs.release_target_temp(env)
3021             #rhs.release_temp(env)
3022         self.rhs.release_temp(env)
3023     
3024     def generate_rhs_evaluation_code(self, code):
3025         self.rhs.generate_evaluation_code(code)
3026     
3027     def generate_assignment_code(self, code):
3028         for i in range(len(self.lhs_list)):
3029             lhs = self.lhs_list[i]
3030             rhs = self.coerced_rhs_list[i]
3031             rhs.generate_evaluation_code(code)
3032             lhs.generate_assignment_code(rhs, code)
3033             # Assignment has disposed of the cloned RHS
3034         self.rhs.generate_disposal_code(code)
3035         self.rhs.free_temps(code)
3036
3037     def annotate(self, code):
3038         for i in range(len(self.lhs_list)):
3039             lhs = self.lhs_list[i].annotate(code)
3040             rhs = self.coerced_rhs_list[i].annotate(code)
3041         self.rhs.annotate(code)
3042         
3043
3044 class ParallelAssignmentNode(AssignmentNode):
3045     #  A combined packing/unpacking assignment:
3046     #
3047     #    a, b, c =  d, e, f
3048     #
3049     #  This has been rearranged by the parser into
3050     #
3051     #    a = d ; b = e ; c = f
3052     #
3053     #  but we must evaluate all the right hand sides
3054     #  before assigning to any of the left hand sides.
3055     #
3056     #  stats     [AssignmentNode]   The constituent assignments
3057     
3058     child_attrs = ["stats"]
3059
3060     def analyse_declarations(self, env):
3061         for stat in self.stats:
3062             stat.analyse_declarations(env)
3063     
3064     def analyse_expressions(self, env):
3065         for stat in self.stats:
3066             stat.analyse_types(env, use_temp = 1)
3067             stat.allocate_rhs_temps(env)
3068         for stat in self.stats:
3069             stat.allocate_lhs_temps(env)
3070
3071 #    def analyse_expressions(self, env):
3072 #        for stat in self.stats:
3073 #            stat.analyse_expressions_1(env, use_temp = 1)
3074 #        for stat in self.stats:
3075 #            stat.analyse_expressions_2(env)
3076     
3077     def generate_execution_code(self, code):
3078         for stat in self.stats:
3079             stat.generate_rhs_evaluation_code(code)
3080         for stat in self.stats:
3081             stat.generate_assignment_code(code)
3082
3083     def annotate(self, code):
3084         for stat in self.stats:
3085             stat.annotate(code)
3086
3087
3088 class InPlaceAssignmentNode(AssignmentNode):
3089     #  An in place arithmatic operand:
3090     #
3091     #    a += b
3092     #    a -= b
3093     #    ...
3094     #
3095     #  lhs      ExprNode      Left hand side
3096     #  rhs      ExprNode      Right hand side
3097     #  op       char          one of "+-*/%^&|"
3098     #  dup     (ExprNode)     copy of lhs used for operation (auto-generated)
3099     #
3100     #  This code is a bit tricky because in order to obey Python 
3101     #  semantics the sub-expressions (e.g. indices) of the lhs must 
3102     #  not be evaluated twice. So we must re-use the values calculated 
3103     #  in evaluation phase for the assignment phase as well. 
3104     #  Fortunately, the type of the lhs node is fairly constrained 
3105     #  (it must be a NameNode, AttributeNode, or IndexNode).     
3106     
3107     child_attrs = ["lhs", "rhs"]
3108     dup = None
3109
3110     def analyse_declarations(self, env):
3111         self.lhs.analyse_target_declaration(env)
3112         
3113     def analyse_types(self, env):
3114         self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3115         self.rhs.analyse_types(env)
3116         self.lhs.analyse_target_types(env)
3117         if Options.incref_local_binop and self.dup.type.is_pyobject:
3118             self.dup = self.dup.coerce_to_temp(env)
3119         
3120     def allocate_rhs_temps(self, env):
3121         import ExprNodes
3122         if self.lhs.type.is_pyobject:
3123             self.rhs = self.rhs.coerce_to_pyobject(env)
3124         elif self.rhs.type.is_pyobject:
3125             self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3126         if self.lhs.type.is_pyobject:
3127              self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
3128              self.result_value.allocate_temps(env)
3129 #        if use_temp:
3130 #            self.rhs = self.rhs.coerce_to_temp(env)
3131         self.rhs.allocate_temps(env)
3132         self.dup.allocate_subexpr_temps(env)
3133         self.dup.allocate_temp(env)
3134     
3135     def allocate_lhs_temps(self, env):
3136         self.lhs.allocate_target_temps(env, self.rhs)
3137 #        self.lhs.release_target_temp(env)
3138         self.dup.release_temp(env)
3139         if self.dup.is_temp:
3140             self.dup.release_subexpr_temps(env)
3141 #        self.rhs.release_temp(env)
3142         if self.lhs.type.is_pyobject:
3143             self.result_value.release_temp(env)
3144
3145     def generate_execution_code(self, code):
3146         import ExprNodes
3147         self.rhs.generate_evaluation_code(code)
3148         self.dup.generate_subexpr_evaluation_code(code)
3149         if isinstance(self.dup, ExprNodes.NewTempExprNode):
3150             # This is because we're manually messing with subexpr nodes
3151             if self.dup.is_temp:
3152                 self.dup.allocate_temp_result(code)
3153         # self.dup.generate_result_code is run only if it is not buffer access
3154         if self.operator == "**":
3155             extra = ", Py_None"
3156         else:
3157             extra = ""
3158         if self.lhs.type.is_pyobject:
3159             if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3160                 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3161             self.dup.generate_result_code(code)
3162             code.putln(
3163                 "%s = %s(%s, %s%s); %s" % (
3164                     self.result_value.result(), 
3165                     self.py_operation_function(), 
3166                     self.dup.py_result(),
3167                     self.rhs.py_result(),
3168                     extra,
3169                     code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3170             code.put_gotref(self.result_value.py_result())
3171             self.result_value.generate_evaluation_code(code) # May be a type check...
3172             self.rhs.generate_disposal_code(code)
3173             self.rhs.free_temps(code)
3174             self.dup.generate_disposal_code(code)
3175             self.dup.free_temps(code)
3176             self.lhs.generate_assignment_code(self.result_value, code)
3177         else: 
3178             c_op = self.operator
3179             if c_op == "//":
3180                 c_op = "/"
3181             elif c_op == "**":
3182                 error(self.pos, "No C inplace power operator")
3183             elif self.lhs.type.is_complex and not code.globalstate.directives['c99_complex']:
3184                 error(self.pos, "Inplace operators not implemented for complex types.")
3185                 
3186             # have to do assignment directly to avoid side-effects
3187             if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3188                 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3189             else:
3190                 self.dup.generate_result_code(code)
3191                 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3192             self.rhs.generate_disposal_code(code)
3193             self.rhs.free_temps(code)
3194         if self.dup.is_temp:
3195             self.dup.generate_subexpr_disposal_code(code)
3196             self.dup.free_subexpr_temps(code)
3197             
3198     def create_dup_node(self, env): 
3199         import ExprNodes
3200         self.dup = self.lhs
3201         self.dup.analyse_types(env)
3202         if isinstance(self.lhs, ExprNodes.NameNode):
3203             target_lhs = ExprNodes.NameNode(self.dup.pos,
3204                                             name = self.dup.name,
3205                                             is_temp = self.dup.is_temp,
3206                                             entry = self.dup.entry)
3207         elif isinstance(self.lhs, ExprNodes.AttributeNode):
3208             target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3209                                                  obj = ExprNodes.CloneNode(self.lhs.obj),
3210                                                  attribute = self.dup.attribute,
3211                                                  is_temp = self.dup.is_temp)
3212         elif isinstance(self.lhs, ExprNodes.IndexNode):
3213             if self.lhs.index:
3214                 index = ExprNodes.CloneNode(self.lhs.index)
3215             else:
3216                 index = None
3217             if self.lhs.indices:
3218                 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3219             else:
3220                 indices = []
3221             target_lhs = ExprNodes.IndexNode(self.dup.pos,
3222                                              base = ExprNodes.CloneNode(self.dup.base),
3223                                              index = index,
3224                                              indices = indices,
3225                                              is_temp = self.dup.is_temp)
3226         else:
3227             assert False
3228         self.lhs = target_lhs
3229         return self.dup
3230     
3231     def py_operation_function(self):
3232         return self.py_functions[self.operator]
3233
3234     py_functions = {
3235         "|":        "PyNumber_InPlaceOr",
3236         "^":        "PyNumber_InPlaceXor",
3237         "&":        "PyNumber_InPlaceAnd",
3238         "+":        "PyNumber_InPlaceAdd",
3239         "-":        "PyNumber_InPlaceSubtract",
3240         "*":        "PyNumber_InPlaceMultiply",
3241         "/":        "PyNumber_InPlaceDivide",
3242         "%":        "PyNumber_InPlaceRemainder",
3243         "<<":        "PyNumber_InPlaceLshift",
3244         ">>":        "PyNumber_InPlaceRshift",
3245         "**":        "PyNumber_InPlacePower",
3246         "//":        "PyNumber_InPlaceFloorDivide",
3247     }
3248
3249     def annotate(self, code):
3250         self.lhs.annotate(code)
3251         self.rhs.annotate(code)
3252         self.dup.annotate(code)
3253
3254
3255 class PrintStatNode(StatNode):
3256     #  print statement
3257     #
3258     #  arg_tuple         TupleNode
3259     #  append_newline    boolean
3260
3261     child_attrs = ["arg_tuple"]
3262
3263     def analyse_expressions(self, env):
3264         self.arg_tuple.analyse_expressions(env)
3265         self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3266         self.arg_tuple.release_temp(env)
3267         env.use_utility_code(printing_utility_code)
3268         if len(self.arg_tuple.args) == 1 and self.append_newline:
3269             env.use_utility_code(printing_one_utility_code)
3270         self.gil_check(env)
3271
3272     gil_message = "Python print statement"
3273
3274     def generate_execution_code(self, code):
3275         if len(self.arg_tuple.args) == 1 and self.append_newline:
3276             arg = self.arg_tuple.args[0]
3277             arg.generate_evaluation_code(code)
3278             
3279             code.putln(
3280                 "if (__Pyx_PrintOne(%s) < 0) %s" % (
3281                     arg.py_result(),
3282                     code.error_goto(self.pos)))
3283             arg.generate_disposal_code(code)
3284             arg.free_temps(code)
3285         else:
3286             self.arg_tuple.generate_evaluation_code(code)
3287             code.putln(
3288                 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3289                     self.arg_tuple.py_result(),
3290                     self.append_newline,
3291                     code.error_goto(self.pos)))
3292             self.arg_tuple.generate_disposal_code(code)
3293             self.arg_tuple.free_temps(code)
3294
3295     def annotate(self, code):
3296         self.arg_tuple.annotate(code)
3297
3298
3299 class ExecStatNode(StatNode):
3300     #  exec statement
3301     #
3302     #  args     [ExprNode]
3303
3304     child_attrs = ["args"]
3305
3306     def analyse_expressions(self, env):
3307         for i, arg in enumerate(self.args):
3308             arg.analyse_expressions(env)
3309             arg = arg.coerce_to_pyobject(env)
3310             arg.release_temp(env)
3311             self.args[i] = arg
3312         self.temp_result = env.allocate_temp_pyobject()
3313         env.release_temp(self.temp_result)
3314         env.use_utility_code(Builtin.pyexec_utility_code)
3315         self.gil_check(env)
3316
3317     gil_message = "Python exec statement"
3318
3319     def generate_execution_code(self, code):
3320         args = []
3321         for arg in self.args:
3322             arg.generate_evaluation_code(code)
3323             args.append( arg.py_result() )
3324         args = tuple(args + ['0', '0'][:3-len(args)])
3325         code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3326                 (self.temp_result,) + args))
3327         for arg in self.args:
3328             arg.generate_disposal_code(code)
3329             arg.free_temps(code)
3330         code.putln(
3331             code.error_goto_if_null(self.temp_result, self.pos))
3332         code.put_gotref(self.temp_result)
3333         code.put_decref_clear(self.temp_result, py_object_type)
3334
3335     def annotate(self, code):
3336         for arg in self.args:
3337             arg.annotate(code)
3338
3339
3340 class DelStatNode(StatNode):
3341     #  del statement
3342     #
3343     #  args     [ExprNode]
3344     
3345     child_attrs = ["args"]
3346
3347     def analyse_declarations(self, env):
3348         for arg in self.args:
3349             arg.analyse_target_declaration(env)
3350     
3351     def analyse_expressions(self, env):
3352         for arg in self.args:
3353             arg.analyse_target_expression(env, None)
3354             if arg.type.is_pyobject:
3355                 self.gil_check(env)
3356             else:
3357                 error(arg.pos, "Deletion of non-Python object")
3358             #arg.release_target_temp(env)
3359
3360     gil_message = "Deleting Python object"
3361
3362     def generate_execution_code(self, code):
3363         for arg in self.args:
3364             if arg.type.is_pyobject:
3365                 arg.generate_deletion_code(code)
3366             # else error reported earlier
3367
3368     def annotate(self, code):
3369         for arg in self.args:
3370             arg.annotate(code)
3371
3372
3373 class PassStatNode(StatNode):
3374     #  pass statement
3375
3376     child_attrs = []
3377     
3378     def analyse_expressions(self, env):
3379         pass
3380     
3381     def generate_execution_code(self, code):
3382         pass
3383
3384
3385 class BreakStatNode(StatNode):
3386
3387     child_attrs = []
3388
3389     def analyse_expressions(self, env):
3390         pass
3391     
3392     def generate_execution_code(self, code):
3393         if not code.break_label:
3394             error(self.pos, "break statement not inside loop")
3395         else:
3396             code.put_goto(code.break_label)
3397
3398
3399 class ContinueStatNode(StatNode):
3400
3401     child_attrs = []
3402
3403     def analyse_expressions(self, env):
3404         pass
3405     
3406     def generate_execution_code(self, code):
3407         if code.funcstate.in_try_finally:
3408             error(self.pos, "continue statement inside try of try...finally")
3409         elif not code.continue_label:
3410             error(self.pos, "continue statement not inside loop")
3411         else:
3412             code.put_goto(code.continue_label)
3413
3414
3415 class ReturnStatNode(StatNode):
3416     #  return statement
3417     #
3418     #  value         ExprNode or None
3419     #  return_type   PyrexType
3420     #  temps_in_use  [Entry]            Temps in use at time of return
3421     
3422     child_attrs = ["value"]
3423
3424     def analyse_expressions(self, env):
3425         return_type = env.return_type
3426         self.return_type = return_type
3427         self.temps_in_use = env.temps_in_use()
3428         if not return_type:
3429             error(self.pos, "Return not inside a function body")
3430             return
3431         if self.value:
3432             self.value.analyse_types(env)
3433             if return_type.is_void or return_type.is_returncode:
3434                 error(self.value.pos, 
3435                     "Return with value in void function")
3436             else:
3437                 self.value = self.value.coerce_to(env.return_type, env)
3438             self.value.allocate_temps(env)
3439             self.value.release_temp(env)
3440         else:
3441             if (not return_type.is_void
3442                 and not return_type.is_pyobject
3443                 and not return_type.is_returncode):
3444                     error(self.pos, "Return value required")
3445         if return_type.is_pyobject:
3446             self.gil_check(env)
3447
3448     gil_message = "Returning Python object"
3449
3450     def generate_execution_code(self, code):
3451         code.mark_pos(self.pos)
3452         if not self.return_type:
3453             # error reported earlier
3454             return
3455         if self.return_type.is_pyobject:
3456             code.put_xdecref(Naming.retval_cname,
3457                              self.return_type)
3458         if self.value:
3459             self.value.generate_evaluation_code(code)
3460             self.value.make_owned_reference(code)
3461             code.putln(
3462                 "%s = %s;" % (
3463                     Naming.retval_cname,
3464                     self.value.result_as(self.return_type)))
3465             self.value.generate_post_assignment_code(code)
3466             self.value.free_temps(code)
3467         else:
3468             if self.return_type.is_pyobject:
3469                 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3470             elif self.return_type.is_returncode:
3471                 code.putln(
3472                     "%s = %s;" % (
3473                         Naming.retval_cname,
3474                         self.return_type.default_value))
3475         # free temps the old way
3476         for entry in self.temps_in_use:
3477             code.put_var_decref_clear(entry)
3478         # free temps the new way
3479         for cname, type in code.funcstate.temps_holding_reference():
3480             code.put_decref_clear(cname, type)
3481         #code.putln(
3482         #    "goto %s;" %
3483         #        code.return_label)
3484         code.put_goto(code.return_label)
3485         
3486     def annotate(self, code):
3487         if self.value:
3488             self.value.annotate(code)
3489
3490
3491 class RaiseStatNode(StatNode):
3492     #  raise statement
3493     #
3494     #  exc_type    ExprNode or None
3495     #  exc_value   ExprNode or None
3496     #  exc_tb      ExprNode or None
3497     
3498     child_attrs = ["exc_type", "exc_value", "exc_tb"]
3499
3500     def analyse_expressions(self, env):
3501         if self.exc_type:
3502             self.exc_type.analyse_types(env)
3503             self.exc_type = self.exc_type.coerce_to_pyobject(env)
3504             self.exc_type.allocate_temps(env)
3505         if self.exc_value:
3506             self.exc_value.analyse_types(env)
3507             self.exc_value = self.exc_value.coerce_to_pyobject(env)
3508             self.exc_value.allocate_temps(env)
3509         if self.exc_tb:
3510             self.exc_tb.analyse_types(env)
3511             self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3512             self.exc_tb.allocate_temps(env)
3513         if self.exc_type:
3514             self.exc_type.release_temp(env)
3515         if self.exc_value:
3516             self.exc_value.release_temp(env)
3517         if self.exc_tb:
3518             self.exc_tb.release_temp(env)
3519         env.use_utility_code(raise_utility_code)
3520         env.use_utility_code(restore_exception_utility_code)
3521         self.gil_check(env)
3522
3523     gil_message = "Raising exception"
3524
3525     def generate_execution_code(self, code):
3526         if self.exc_type:
3527             self.exc_type.generate_evaluation_code(code)
3528             type_code = self.exc_type.py_result()
3529         else:
3530             type_code = "0"
3531         if self.exc_value:
3532             self.exc_value.generate_evaluation_code(code)
3533             value_code = self.exc_value.py_result()
3534         else:
3535             value_code = "0"
3536         if self.exc_tb:
3537             self.exc_tb.generate_evaluation_code(code)
3538             tb_code = self.exc_tb.py_result()
3539         else:
3540             tb_code = "0"
3541         if self.exc_type or self.exc_value or self.exc_tb:
3542             code.putln(
3543                 "__Pyx_Raise(%s, %s, %s);" % (
3544                     type_code,
3545                     value_code,
3546                     tb_code))
3547         else:
3548             code.putln(
3549                 "__Pyx_ReRaise();")
3550         for obj in (self.exc_type, self.exc_value, self.exc_tb):
3551             if obj:
3552                 obj.generate_disposal_code(code)
3553                 obj.free_temps(code)
3554         code.putln(
3555             code.error_goto(self.pos))
3556
3557     def annotate(self, code):
3558         if self.exc_type:
3559             self.exc_type.annotate(code)
3560         if self.exc_value:
3561             self.exc_value.annotate(code)
3562         if self.exc_tb:
3563             self.exc_tb.annotate(code)
3564
3565
3566 class ReraiseStatNode(StatNode):
3567
3568     child_attrs = []
3569
3570     def analyse_expressions(self, env):
3571         self.gil_check(env)
3572         env.use_utility_code(raise_utility_code)
3573         env.use_utility_code(restore_exception_utility_code)
3574
3575     gil_message = "Raising exception"
3576
3577     def generate_execution_code(self, code):
3578         vars = code.funcstate.exc_vars
3579         if vars:
3580             code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
3581             code.putln(code.error_goto(self.pos))
3582         else:
3583             error(self.pos, "Reraise not inside except clause")
3584         
3585
3586 class AssertStatNode(StatNode):
3587     #  assert statement
3588     #
3589     #  cond    ExprNode
3590     #  value   ExprNode or None
3591     
3592     child_attrs = ["cond", "value"]
3593
3594     def analyse_expressions(self, env):
3595         self.cond = self.cond.analyse_boolean_expression(env)
3596         if self.value:
3597             self.value.analyse_types(env)
3598             self.value = self.value.coerce_to_pyobject(env)
3599             self.value.allocate_temps(env)
3600         self.cond.release_temp(env)
3601         if self.value:
3602             self.value.release_temp(env)
3603         self.gil_check(env)
3604         #env.recycle_pending_temps() # TEMPORARY
3605
3606     gil_message = "Raising exception"
3607     
3608     def generate_execution_code(self, code):
3609         code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3610         self.cond.generate_evaluation_code(code)
3611         code.putln(
3612             "if (unlikely(!%s)) {" %
3613                 self.cond.result())
3614         if self.value:
3615             self.value.generate_evaluation_code(code)
3616             code.putln(
3617                 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3618                     self.value.py_result())
3619             self.value.generate_disposal_code(code)
3620             self.value.free_temps(code)
3621         else:
3622             code.putln(
3623                 "PyErr_SetNone(PyExc_AssertionError);")
3624         code.putln(
3625                 code.error_goto(self.pos))
3626         code.putln(
3627             "}")
3628         self.cond.generate_disposal_code(code)
3629         self.cond.free_temps(code)
3630         code.putln("#endif")
3631
3632     def annotate(self, code):
3633         self.cond.annotate(code)
3634         if self.value:
3635             self.value.annotate(code)
3636
3637
3638 class IfStatNode(StatNode):
3639     #  if statement
3640     #
3641     #  if_clauses   [IfClauseNode]
3642     #  else_clause  StatNode or None
3643
3644     child_attrs = ["if_clauses", "else_clause"]
3645     
3646     def analyse_control_flow(self, env):
3647         env.start_branching(self.pos)
3648         for if_clause in self.if_clauses:
3649             if_clause.analyse_control_flow(env)
3650             env.next_branch(if_clause.end_pos())
3651         if self.else_clause:
3652             self.else_clause.analyse_control_flow(env)
3653         env.finish_branching(self.end_pos())
3654
3655     def analyse_declarations(self, env):
3656         for if_clause in self.if_clauses:
3657             if_clause.analyse_declarations(env)
3658         if self.else_clause:
3659             self.else_clause.analyse_declarations(env)
3660     
3661     def analyse_expressions(self, env):
3662         for if_clause in self.if_clauses:
3663             if_clause.analyse_expressions(env)
3664         if self.else_clause:
3665             self.else_clause.analyse_expressions(env)
3666     
3667     def generate_execution_code(self, code):
3668         code.mark_pos(self.pos)
3669         end_label = code.new_label()
3670         for if_clause in self.if_clauses:
3671             if_clause.generate_execution_code(code, end_label)
3672         if self.else_clause:
3673             code.putln("/*else*/ {")
3674             self.else_clause.generate_execution_code(code)
3675             code.putln("}")
3676         code.put_label(end_label)
3677         
3678     def annotate(self, code):
3679         for if_clause in self.if_clauses:
3680             if_clause.annotate(code)
3681         if self.else_clause:
3682             self.else_clause.annotate(code)
3683
3684
3685 class IfClauseNode(Node):
3686     #  if or elif clause in an if statement
3687     #
3688     #  condition   ExprNode
3689     #  body        StatNode
3690     
3691     child_attrs = ["condition", "body"]
3692
3693     def analyse_control_flow(self, env):
3694         self.body.analyse_control_flow(env)
3695         
3696     def analyse_declarations(self, env):
3697         self.condition.analyse_declarations(env)
3698         self.body.analyse_declarations(env)
3699     
3700     def analyse_expressions(self, env):
3701         self.condition = \
3702             self.condition.analyse_temp_boolean_expression(env)
3703         self.condition.release_temp(env)
3704         self.body.analyse_expressions(env)
3705     
3706     def generate_execution_code(self, code, end_label):
3707         self.condition.generate_evaluation_code(code)
3708         code.putln(
3709             "if (%s) {" %
3710                 self.condition.result())
3711         self.condition.generate_disposal_code(code)
3712         self.condition.free_temps(code)
3713         self.body.generate_execution_code(code)
3714         #code.putln(
3715         #    "goto %s;" %
3716         #        end_label)
3717         code.put_goto(end_label)
3718         code.putln("}")
3719
3720     def annotate(self, code):
3721         self.condition.annotate(code)
3722         self.body.annotate(code)
3723         
3724
3725 class SwitchCaseNode(StatNode):
3726     # Generated in the optimization of an if-elif-else node
3727     #
3728     # conditions    [ExprNode]
3729     # body          StatNode
3730     
3731     child_attrs = ['conditions', 'body']
3732     
3733     def generate_execution_code(self, code):
3734         for cond in self.conditions:
3735             code.mark_pos(cond.pos)
3736             code.putln("case %s:" % cond.calculate_result_code())
3737         self.body.generate_execution_code(code)
3738         code.putln("break;")
3739         
3740     def annotate(self, code):
3741         for cond in self.conditions:
3742             cond.annotate(code)
3743         self.body.annotate(code)
3744
3745 class SwitchStatNode(StatNode):
3746     # Generated in the optimization of an if-elif-else node
3747     #
3748     # test          ExprNode
3749     # cases         [SwitchCaseNode]
3750     # else_clause   StatNode or None
3751     
3752     child_attrs = ['test', 'cases', 'else_clause']
3753     
3754     def generate_execution_code(self, code):
3755         code.putln("switch (%s) {" % self.test.calculate_result_code())
3756         for case in self.cases:
3757             case.generate_execution_code(code)
3758         if self.else_clause is not None:
3759             code.putln("default:")
3760             self.else_clause.generate_execution_code(code)
3761             code.putln("break;")
3762         code.putln("}")
3763
3764     def annotate(self, code):
3765         self.test.annotate(code)
3766         for case in self.cases:
3767             case.annotate(code)
3768         if self.else_clause is not None:
3769             self.else_clause.annotate(code)
3770             
3771 class LoopNode(object):
3772     
3773     def analyse_control_flow(self, env):
3774         env.start_branching(self.pos)
3775         self.body.analyse_control_flow(env)
3776         env.next_branch(self.body.end_pos())
3777         if self.else_clause:
3778             self.else_clause.analyse_control_flow(env)
3779         env.finish_branching(self.end_pos())
3780
3781     
3782 class WhileStatNode(LoopNode, StatNode):
3783     #  while statement
3784     #
3785     #  condition    ExprNode
3786     #  body         StatNode
3787     #  else_clause  StatNode
3788
3789     child_attrs = ["condition", "body", "else_clause"]
3790
3791     def analyse_declarations(self, env):
3792         self.body.analyse_declarations(env)
3793         if self.else_clause:
3794             self.else_clause.analyse_declarations(env)
3795     
3796     def analyse_expressions(self, env):
3797         self.condition = \
3798             self.condition.analyse_temp_boolean_expression(env)
3799         self.condition.release_temp(env)
3800         #env.recycle_pending_temps() # TEMPORARY
3801         self.body.analyse_expressions(env)
3802         if self.else_clause:
3803             self.else_clause.analyse_expressions(env)
3804     
3805     def generate_execution_code(self, code):
3806         old_loop_labels = code.new_loop_labels()
3807         code.putln(
3808             "while (1) {")
3809         self.condition.generate_evaluation_code(code)
3810         self.condition.generate_disposal_code(code)
3811         code.putln(
3812             "if (!%s) break;" %
3813                 self.condition.result())
3814         self.condition.free_temps(code)
3815         self.body.generate_execution_code(code)
3816         code.put_label(code.continue_label)
3817         code.putln("}")
3818         break_label = code.break_label
3819         code.set_loop_labels(old_loop_labels)
3820         if self.else_clause:
3821             code.putln("/*else*/ {")
3822             self.else_clause.generate_execution_code(code)
3823             code.putln("}")
3824         code.put_label(break_label)
3825
3826     def annotate(self, code):
3827         self.condition.annotate(code)
3828         self.body.annotate(code)
3829         if self.else_clause:
3830             self.else_clause.annotate(code)
3831
3832
3833 def ForStatNode(pos, **kw):
3834     if 'iterator' in kw:
3835         return ForInStatNode(pos, **kw)
3836     else:
3837         return ForFromStatNode(pos, **kw)
3838
3839 class ForInStatNode(LoopNode, StatNode):
3840     #  for statement
3841     #
3842     #  target        ExprNode
3843     #  iterator      IteratorNode
3844     #  body          StatNode
3845     #  else_clause   StatNode
3846     #  item          NextNode       used internally
3847     
3848     child_attrs = ["target", "iterator", "body", "else_clause"]
3849     item = None
3850     
3851     def analyse_declarations(self, env):
3852         self.target.analyse_target_declaration(env)
3853         self.body.analyse_declarations(env)
3854         if self.else_clause:
3855             self.else_clause.analyse_declarations(env)
3856
3857     def analyse_expressions(self, env):
3858         import ExprNodes
3859         self.target.analyse_target_types(env)
3860         self.iterator.analyse_expressions(env)
3861         self.item = ExprNodes.NextNode(self.iterator, env)
3862         self.item = self.item.coerce_to(self.target.type, env)
3863         self.item.allocate_temps(env)
3864         self.target.allocate_target_temps(env, self.item)
3865         #self.item.release_temp(env)
3866         #self.target.release_target_temp(env)
3867         self.body.analyse_expressions(env)
3868         if self.else_clause:
3869             self.else_clause.analyse_expressions(env)
3870         self.iterator.release_temp(env)
3871
3872     def generate_execution_code(self, code):
3873         old_loop_labels = code.new_loop_labels()
3874         self.iterator.allocate_counter_temp(code)
3875         self.iterator.generate_evaluation_code(code)
3876         code.putln(
3877             "for (;;) {")
3878         self.item.generate_evaluation_code(code)
3879         self.target.generate_assignment_code(self.item, code)
3880         self.body.generate_execution_code(code)
3881         code.put_label(code.continue_label)
3882         code.putln(
3883             "}")
3884         break_label = code.break_label
3885         code.set_loop_labels(old_loop_labels)
3886         if self.else_clause:
3887             code.putln("/*else*/ {")
3888             self.else_clause.generate_execution_code(code)
3889             code.putln("}")
3890         code.put_label(break_label)
3891         self.iterator.release_counter_temp(code)
3892         self.iterator.generate_disposal_code(code)
3893         self.iterator.free_temps(code)
3894
3895     def annotate(self, code):
3896         self.target.annotate(code)
3897         self.iterator.annotate(code)
3898         self.body.annotate(code)
3899         if self.else_clause:
3900             self.else_clause.annotate(code)
3901         self.item.annotate(code)
3902
3903
3904 class ForFromStatNode(LoopNode, StatNode):
3905     #  for name from expr rel name rel expr
3906     #
3907     #  target        NameNode
3908     #  bound1        ExprNode
3909     #  relation1     string
3910     #  relation2     string
3911     #  bound2        ExprNode
3912     #  step          ExprNode or None
3913     #  body          StatNode
3914     #  else_clause   StatNode or None
3915     #
3916     #  Used internally:
3917     #
3918     #  from_range         bool
3919     #  is_py_target       bool
3920     #  loopvar_node       ExprNode (usually a NameNode or temp node)
3921     #  py_loopvar_node    PyTempNode or None
3922     child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3923
3924     is_py_target = False
3925     loopvar_node = None
3926     py_loopvar_node = None
3927     from_range = False
3928
3929     def analyse_declarations(self, env):
3930         self.target.analyse_target_declaration(env)
3931         self.body.analyse_declarations(env)
3932         if self.else_clause:
3933             self.else_clause.analyse_declarations(env)
3934
3935     def analyse_expressions(self, env):
3936         import ExprNodes
3937         self.target.analyse_target_types(env)
3938         self.bound1.analyse_types(env)
3939         self.bound2.analyse_types(env)
3940         if self.step is not None:
3941             if isinstance(self.step, ExprNodes.UnaryMinusNode):
3942                 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3943             self.step.analyse_types(env)
3944         
3945         target_type = self.target.type
3946         if self.target.type.is_numeric:
3947             loop_type = self.target.type
3948         else:
3949             loop_type = PyrexTypes.c_int_type
3950             if not self.bound1.type.is_pyobject:
3951                 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
3952             if not self.bound2.type.is_pyobject:
3953                 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
3954             if self.step is not None and not self.step.type.is_pyobject:
3955                 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
3956         self.bound1 = self.bound1.coerce_to(loop_type, env)
3957         self.bound2 = self.bound2.coerce_to(loop_type, env)
3958         if not self.bound2.is_literal:
3959             self.bound2 = self.bound2.coerce_to_temp(env)
3960         if self.step is not None:
3961             self.step = self.step.coerce_to(loop_type, env)            
3962             if not self.step.is_literal:
3963                 self.step = self.step.coerce_to_temp(env)
3964
3965         target_type = self.target.type
3966         if not (target_type.is_pyobject or target_type.is_numeric):
3967             error(self.target.pos,
3968                 "for-from loop variable must be c numeric type or Python object")
3969         if target_type.is_numeric:
3970             self.is_py_target = False
3971             if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3972                 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3973             self.loopvar_node = self.target
3974             self.py_loopvar_node = None
3975         else:
3976             self.is_py_target = True
3977             c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
3978             c_loopvar_node.allocate_temps(env)
3979             self.loopvar_node = c_loopvar_node
3980             self.py_loopvar_node = \
3981                 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3982         self.bound1.allocate_temps(env)
3983         self.bound2.allocate_temps(env)
3984         if self.step is not None:
3985             self.step.allocate_temps(env)
3986         if self.is_py_target:
3987             self.py_loopvar_node.allocate_temps(env)
3988             self.target.allocate_target_temps(env, self.py_loopvar_node)
3989             #self.target.release_target_temp(env)
3990             #self.py_loopvar_node.release_temp(env)
3991         self.body.analyse_expressions(env)
3992         if self.is_py_target:
3993             c_loopvar_node.release_temp(env)
3994         if self.else_clause:
3995             self.else_clause.analyse_expressions(env)
3996         self.bound1.release_temp(env)
3997         self.bound2.release_temp(env)
3998         if self.step is not None:
3999             self.step.release_temp(env)
4000             
4001     def generate_execution_code(self, code):
4002         old_loop_labels = code.new_loop_labels()
4003         from_range = self.from_range
4004         self.bound1.generate_evaluation_code(code)
4005         self.bound2.generate_evaluation_code(code)
4006         offset, incop = self.relation_table[self.relation1]
4007         if self.step is not None:
4008             self.step.generate_evaluation_code(code)
4009             step = self.step.result()
4010             incop = "%s=%s" % (incop[0], step)
4011         if from_range:
4012             loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
4013         else:
4014             loopvar_name = self.loopvar_node.result()
4015         code.putln(
4016             "for (%s = %s%s; %s %s %s; %s%s) {" % (
4017                 loopvar_name,
4018                 self.bound1.result(), offset,
4019                 loopvar_name, self.relation2, self.bound2.result(),
4020                 loopvar_name, incop))
4021         if self.py_loopvar_node:
4022             self.py_loopvar_node.generate_evaluation_code(code)
4023             self.target.generate_assignment_code(self.py_loopvar_node, code)
4024         elif from_range:
4025             code.putln("%s = %s;" % (
4026                             self.target.result(), loopvar_name))
4027         self.body.generate_execution_code(code)
4028         code.put_label(code.continue_label)
4029         if self.py_loopvar_node:
4030             # This mess is to make for..from loops with python targets behave 
4031             # exactly like those with C targets with regards to re-assignment 
4032             # of the loop variable. 
4033             import ExprNodes
4034             if self.target.entry.is_pyglobal:
4035                 # We know target is a NameNode, this is the only ugly case. 
4036                 target_node = ExprNodes.PyTempNode(self.target.pos, None)
4037                 target_node.result_code = code.funcstate.allocate_temp(py_object_type, False)
4038                 code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
4039                                 target_node.result_code,
4040                                 Naming.module_cname, 
4041                                 self.target.entry.interned_cname,
4042                                 code.error_goto_if_null(target_node.result_code, self.target.pos)))
4043                 code.put_gotref(target_node.result_code)
4044             else:
4045                 target_node = self.target
4046             from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
4047             from_py_node.temp_code = loopvar_name
4048             from_py_node.generate_result_code(code)
4049             if self.target.entry.is_pyglobal:
4050                 code.put_decref_clear(target_node.result_code, py_object_type)
4051                 code.funcstate.release_temp(target_node.result_code)
4052         code.putln("}")
4053         if self.py_loopvar_node:
4054             # This is potentially wasteful, but we don't want the semantics to 
4055             # depend on whether or not the loop is a python type. 
4056             self.py_loopvar_node.generate_evaluation_code(code)
4057             self.target.generate_assignment_code(self.py_loopvar_node, code)
4058         break_label = code.break_label
4059         code.set_loop_labels(old_loop_labels)
4060         if self.else_clause:
4061             code.putln("/*else*/ {")
4062             self.else_clause.generate_execution_code(code)
4063             code.putln("}")
4064         code.put_label(break_label)
4065         self.bound1.generate_disposal_code(code)
4066         self.bound1.free_temps(code)
4067         self.bound2.generate_disposal_code(code)
4068         self.bound2.free_temps(code)
4069         if self.step is not None:
4070             self.step.generate_disposal_code(code)
4071             self.step.free_temps(code)
4072         if from_range:
4073             code.funcstate.release_temp(loopvar_name)
4074     
4075     relation_table = {
4076         # {relop : (initial offset, increment op)}
4077         '<=': ("",   "++"),
4078         '<' : ("+1", "++"),
4079         '>=': ("",   "--"),
4080         '>' : ("-1", "--")
4081     }
4082     
4083     def annotate(self, code):
4084         self.target.annotate(code)
4085         self.bound1.annotate(code)
4086         self.bound2.annotate(code)
4087         if self.step:
4088             self.bound2.annotate(code)
4089         self.body.annotate(code)
4090         if self.else_clause:
4091             self.else_clause.annotate(code)
4092
4093
4094 class WithStatNode(StatNode):
4095     """
4096     Represents a Python with statement.
4097     
4098     This is only used at parse tree level; and is not present in
4099     analysis or generation phases.
4100     """
4101     #  manager          The with statement manager object
4102     #  target            Node (lhs expression)
4103     #  body             StatNode
4104     child_attrs = ["manager", "target", "body"]
4105
4106 class TryExceptStatNode(StatNode):
4107     #  try .. except statement
4108     #
4109     #  body             StatNode
4110     #  except_clauses   [ExceptClauseNode]
4111     #  else_clause      StatNode or None
4112     #  cleanup_list     [Entry]            old style temps to clean up on error
4113
4114     child_attrs = ["body", "except_clauses", "else_clause"]
4115     
4116     def analyse_control_flow(self, env):
4117         env.start_branching(self.pos)
4118         self.body.analyse_control_flow(env)
4119         successful_try = env.control_flow # grab this for later
4120         env.next_branch(self.body.end_pos())
4121         env.finish_branching(self.body.end_pos())
4122         
4123         env.start_branching(self.except_clauses[0].pos)
4124         for except_clause in self.except_clauses:
4125             except_clause.analyse_control_flow(env)
4126             env.next_branch(except_clause.end_pos())
4127             
4128         # the else cause it executed only when the try clause finishes
4129         env.control_flow.incoming = successful_try
4130         if self.else_clause:
4131             self.else_clause.analyse_control_flow(env)
4132         env.finish_branching(self.end_pos())
4133
4134     def analyse_declarations(self, env):
4135         self.body.analyse_declarations(env)
4136         for except_clause in self.except_clauses:
4137             except_clause.analyse_declarations(env)
4138         if self.else_clause:
4139             self.else_clause.analyse_declarations(env)
4140         self.gil_check(env)
4141         env.use_utility_code(reset_exception_utility_code)
4142     
4143     def analyse_expressions(self, env):
4144         self.body.analyse_expressions(env)
4145         self.cleanup_list = env.free_temp_entries[:]
4146         default_clause_seen = 0
4147         for except_clause in self.except_clauses:
4148             except_clause.analyse_expressions(env)
4149             if default_clause_seen:
4150                 error(except_clause.pos, "default 'except:' must be last")
4151             if not except_clause.pattern:
4152                 default_clause_seen = 1
4153         self.has_default_clause = default_clause_seen
4154         if self.else_clause:
4155             self.else_clause.analyse_expressions(env)
4156         self.gil_check(env)
4157
4158     gil_message = "Try-except statement"
4159
4160     def generate_execution_code(self, code):
4161         old_return_label = code.return_label
4162         old_break_label = code.break_label
4163         old_continue_label = code.continue_label
4164         old_error_label = code.new_error_label()
4165         our_error_label = code.error_label
4166         except_end_label = code.new_label('exception_handled')
4167         except_error_label = code.new_label('except_error')
4168         except_return_label = code.new_label('except_return')
4169         try_return_label = code.new_label('try_return')
4170         try_break_label = code.new_label('try_break')
4171         try_continue_label = code.new_label('try_continue')
4172         try_end_label = code.new_label('try_end')
4173
4174         code.putln("{")
4175         code.putln("PyObject %s;" %
4176                    ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4177         code.putln("__Pyx_ExceptionSave(%s);" %
4178                    ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4179         for var in Naming.exc_save_vars:
4180             code.put_xgotref(var)
4181         code.putln(
4182             "/*try:*/ {")
4183         code.return_label = try_return_label
4184         code.break_label = try_break_label
4185         code.continue_label = try_continue_label
4186         self.body.generate_execution_code(code)
4187         code.putln(
4188             "}")
4189         temps_to_clean_up = code.funcstate.all_free_managed_temps()
4190         code.error_label = except_error_label
4191         code.return_label = except_return_label
4192         if self.else_clause:
4193             code.putln(
4194                 "/*else:*/ {")
4195             self.else_clause.generate_execution_code(code)
4196             code.putln(
4197                 "}")
4198         for var in Naming.exc_save_vars:
4199             code.put_xdecref_clear(var, py_object_type)
4200         code.put_goto(try_end_label)
4201         if code.label_used(try_return_label):
4202             code.put_label(try_return_label)
4203             for var in Naming.exc_save_vars:
4204                 code.put_xdecref_clear(var, py_object_type)
4205             code.put_goto(old_return_label)
4206         code.put_label(our_error_label)
4207         code.put_var_xdecrefs_clear(self.cleanup_list)
4208         for temp_name, type in temps_to_clean_up:
4209             code.put_xdecref_clear(temp_name, type)
4210         for except_clause in self.except_clauses:
4211             except_clause.generate_handling_code(code, except_end_label)
4212
4213         error_label_used = code.label_used(except_error_label)
4214         if error_label_used or not self.has_default_clause:
4215             if error_label_used:
4216                 code.put_label(except_error_label)
4217             for var in Naming.exc_save_vars:
4218                 code.put_xdecref(var, py_object_type)
4219             code.put_goto(old_error_label)
4220             
4221         if code.label_used(try_break_label):
4222             code.put_label(try_break_label)
4223             for var in Naming.exc_save_vars: code.put_xgiveref(var)
4224             code.putln("__Pyx_ExceptionReset(%s);" %
4225                        ', '.join(Naming.exc_save_vars))
4226             code.put_goto(old_break_label)
4227             
4228         if code.label_used(try_continue_label):
4229             code.put_label(try_continue_label)
4230             for var in Naming.exc_save_vars: code.put_xgiveref(var)
4231             code.putln("__Pyx_ExceptionReset(%s);" %
4232                        ', '.join(Naming.exc_save_vars))
4233             code.put_goto(old_continue_label)
4234
4235         if code.label_used(except_return_label):
4236             code.put_label(except_return_label)
4237             for var in Naming.exc_save_vars: code.put_xgiveref(var)
4238             code.putln("__Pyx_ExceptionReset(%s);" %
4239                        ', '.join(Naming.exc_save_vars))
4240             code.put_goto(old_return_label)
4241
4242         if code.label_used(except_end_label):
4243             code.put_label(except_end_label)
4244             for var in Naming.exc_save_vars: code.put_xgiveref(var)
4245             code.putln("__Pyx_ExceptionReset(%s);" %
4246                        ', '.join(Naming.exc_save_vars))
4247         code.put_label(try_end_label)
4248         code.putln("}")
4249
4250         code.return_label = old_return_label
4251         code.break_label = old_break_label
4252         code.continue_label = old_continue_label
4253         code.error_label = old_error_label
4254
4255     def annotate(self, code):
4256         self.body.annotate(code)
4257         for except_node in self.except_clauses:
4258             except_node.annotate(code)
4259         if self.else_clause:
4260             self.else_clause.annotate(code)
4261
4262
4263 class ExceptClauseNode(Node):
4264     #  Part of try ... except statement.
4265     #
4266     #  pattern        ExprNode
4267     #  target         ExprNode or None
4268     #  body           StatNode
4269     #  excinfo_target NameNode or None   optional target for exception info
4270     #  match_flag     string             result of exception match
4271     #  exc_value      ExcValueNode       used internally
4272     #  function_name  string             qualified name of enclosing function
4273     #  exc_vars       (string * 3)       local exception variables
4274
4275     # excinfo_target is never set by the parser, but can be set by a transform
4276     # in order to extract more extensive information about the exception as a
4277     # sys.exc_info()-style tuple into a target variable
4278     
4279     child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4280
4281     exc_value = None
4282     excinfo_target = None
4283
4284     def analyse_declarations(self, env):
4285         if self.target:
4286             self.target.analyse_target_declaration(env)
4287         if self.excinfo_target is not None:
4288             self.excinfo_target.analyse_target_declaration(env)
4289         self.body.analyse_declarations(env)
4290     
4291     def analyse_expressions(self, env):
4292         import ExprNodes
4293         genv = env.global_scope()
4294         self.function_name = env.qualified_name
4295         if self.pattern:
4296             self.pattern.analyse_expressions(env)
4297             self.pattern = self.pattern.coerce_to_pyobject(env)
4298             self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
4299             self.pattern.release_temp(env)
4300             env.release_temp(self.match_flag)
4301
4302         if self.target or self.excinfo_target:
4303             self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
4304         else:
4305             self.exc_vars = None
4306
4307         if self.target:
4308             self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
4309             self.exc_value.allocate_temps(env)
4310             self.target.analyse_target_expression(env, self.exc_value)
4311         if self.excinfo_target is not None:
4312             import ExprNodes
4313             self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4314                 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
4315                 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
4316                 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
4317             ])
4318             self.excinfo_tuple.analyse_expressions(env)
4319             self.excinfo_tuple.allocate_temps(env)
4320             self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4321
4322         self.body.analyse_expressions(env)
4323
4324         if self.exc_vars:
4325             for var in self.exc_vars:
4326                 env.release_temp(var)
4327     
4328     def generate_handling_code(self, code, end_label):
4329         code.mark_pos(self.pos)
4330         if self.pattern:
4331             self.pattern.generate_evaluation_code(code)
4332             code.putln(
4333                 "%s = PyErr_ExceptionMatches(%s);" % (
4334                     self.match_flag,
4335                     self.pattern.py_result()))
4336             self.pattern.generate_disposal_code(code)
4337             self.pattern.free_temps(code)
4338             code.putln(
4339                 "if (%s) {" %
4340                     self.match_flag)
4341         else:
4342             code.putln("/*except:*/ {")
4343
4344         if self.exc_vars:
4345             exc_vars = self.exc_vars
4346         elif not getattr(self.body, 'stats', True):
4347             # most simple case: no exception variable, empty body (pass)
4348             # => reset the exception state, done
4349             code.putln("PyErr_Restore(0,0,0);")
4350             code.put_goto(end_label)
4351             code.putln("}")
4352             return
4353         else:
4354             # during type analysis, we didn't know if we need the
4355             # exception value, but apparently, we do
4356             exc_vars = [code.funcstate.allocate_temp(py_object_type,
4357                                                      manage_ref=True)
4358                         for i in xrange(3)]
4359
4360         code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4361         # We always have to fetch the exception value even if
4362         # there is no target, because this also normalises the 
4363         # exception and stores it in the thread state.
4364         code.globalstate.use_utility_code(get_exception_utility_code)
4365         exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
4366         code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4367             code.error_goto(self.pos)))
4368         for x in exc_vars:
4369             code.put_gotref(x)
4370         if self.target:
4371             self.exc_value.generate_evaluation_code(code)
4372             self.target.generate_assignment_code(self.exc_value, code)
4373         if self.excinfo_target is not None:
4374             self.excinfo_tuple.generate_evaluation_code(code)
4375             self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4376
4377
4378         old_break_label, old_continue_label = code.break_label, code.continue_label
4379         code.break_label = code.new_label('except_break')
4380         code.continue_label = code.new_label('except_continue')
4381
4382         old_exc_vars = code.funcstate.exc_vars
4383         code.funcstate.exc_vars = exc_vars
4384         self.body.generate_execution_code(code)
4385         code.funcstate.exc_vars = old_exc_vars
4386         for var in exc_vars:
4387             code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4388         code.put_goto(end_label)
4389         
4390         if code.label_used(code.break_label):
4391             code.put_label(code.break_label)
4392             for var in exc_vars:
4393                 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4394             code.put_goto(old_break_label)
4395         code.break_label = old_break_label
4396
4397         if code.label_used(code.continue_label):
4398             code.put_label(code.continue_label)
4399             for var in exc_vars:
4400                 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4401             code.put_goto(old_continue_label)
4402         code.continue_label = old_continue_label
4403
4404         if not self.exc_vars:
4405             # clean up locally allocated temps
4406             for temp in exc_vars:
4407                 code.funcstate.release_temp(temp)
4408
4409         code.putln(
4410             "}")
4411
4412     def annotate(self, code):
4413         if self.pattern:
4414             self.pattern.annotate(code)
4415         if self.target:
4416             self.target.annotate(code)
4417         self.body.annotate(code)
4418
4419
4420 class TryFinallyStatNode(StatNode):
4421     #  try ... finally statement
4422     #
4423     #  body             StatNode
4424     #  finally_clause   StatNode
4425     #
4426     #  cleanup_list     [Entry]     old_style temps to clean up on error
4427     #
4428     #  The plan is that we funnel all continue, break
4429     #  return and error gotos into the beginning of the
4430     #  finally block, setting a variable to remember which
4431     #  one we're doing. At the end of the finally block, we
4432     #  switch on the variable to figure out where to go.
4433     #  In addition, if we're doing an error, we save the
4434     #  exception on entry to the finally block and restore
4435     #  it on exit.
4436
4437     child_attrs = ["body", "finally_clause"]
4438     
4439     preserve_exception = 1
4440     
4441     disallow_continue_in_try_finally = 0
4442     # There doesn't seem to be any point in disallowing
4443     # continue in the try block, since we have no problem
4444     # handling it.
4445
4446     def create_analysed(pos, env, body, finally_clause):
4447         node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4448         node.cleanup_list = []
4449         return node
4450     create_analysed = staticmethod(create_analysed)
4451     
4452     def analyse_control_flow(self, env):
4453         env.start_branching(self.pos)
4454         self.body.analyse_control_flow(env)
4455         env.next_branch(self.body.end_pos())
4456         env.finish_branching(self.body.end_pos())
4457         self.finally_clause.analyse_control_flow(env)
4458
4459     def analyse_declarations(self, env):
4460         self.body.analyse_declarations(env)
4461         self.finally_clause.analyse_declarations(env)
4462     
4463     def analyse_expressions(self, env):
4464         self.body.analyse_expressions(env)
4465         self.cleanup_list = env.free_temp_entries[:]
4466         self.finally_clause.analyse_expressions(env)
4467         self.gil_check(env)
4468
4469     gil_message = "Try-finally statement"
4470
4471     def generate_execution_code(self, code):
4472         old_error_label = code.error_label
4473         old_labels = code.all_new_labels()
4474         new_labels = code.get_all_labels()
4475         new_error_label = code.error_label
4476         catch_label = code.new_label()
4477         code.putln(
4478             "/*try:*/ {")
4479         if self.disallow_continue_in_try_finally:
4480             was_in_try_finally = code.funcstate.in_try_finally
4481             code.funcstate.in_try_finally = 1
4482         self.body.generate_execution_code(code)
4483         if self.disallow_continue_in_try_finally:
4484             code.funcstate.in_try_finally = was_in_try_finally
4485         code.putln(
4486             "}")
4487         temps_to_clean_up = code.funcstate.all_free_managed_temps()
4488         code.putln(
4489             "/*finally:*/ {")
4490         cases_used = []
4491         error_label_used = 0
4492         for i, new_label in enumerate(new_labels):
4493             if new_label in code.labels_used:
4494                 cases_used.append(i)
4495                 if new_label == new_error_label:
4496                     error_label_used = 1
4497                     error_label_case = i
4498         if cases_used:
4499             code.putln(
4500                     "int __pyx_why;")
4501             if error_label_used and self.preserve_exception:
4502                 code.putln(
4503                     "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4504                 code.putln(
4505                     "int %s;" % Naming.exc_lineno_name)
4506                 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4507                 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4508                 code.putln(exc_var_init_zero)
4509             else:
4510                 exc_var_init_zero = None
4511             code.use_label(catch_label)
4512             code.putln(
4513                     "__pyx_why = 0; goto %s;" % catch_label)
4514             for i in cases_used:
4515                 new_label = new_labels[i]
4516                 #if new_label and new_label != "<try>":
4517                 if new_label == new_error_label and self.preserve_exception:
4518                     self.put_error_catcher(code, 
4519                         new_error_label, i+1, catch_label, temps_to_clean_up)
4520                 else:
4521                     code.put('%s: ' % new_label)
4522                     if exc_var_init_zero:
4523                         code.putln(exc_var_init_zero)
4524                     code.putln("__pyx_why = %s; goto %s;" % (
4525                             i+1,
4526                             catch_label))
4527             code.put_label(catch_label)
4528         code.set_all_labels(old_labels)
4529         if error_label_used:
4530             code.new_error_label()
4531             finally_error_label = code.error_label
4532         self.finally_clause.generate_execution_code(code)
4533         if error_label_used:
4534             if finally_error_label in code.labels_used and self.preserve_exception:
4535                 over_label = code.new_label()
4536                 code.put_goto(over_label);
4537                 code.put_label(finally_error_label)
4538                 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4539                 for var in Naming.exc_vars:
4540                     code.putln("Py_XDECREF(%s);" % var)
4541                 code.putln("}")
4542                 code.put_goto(old_error_label)
4543                 code.put_label(over_label)
4544             code.error_label = old_error_label
4545         if cases_used:
4546             code.putln(
4547                 "switch (__pyx_why) {")
4548             for i in cases_used:
4549                 old_label = old_labels[i]
4550                 if old_label == old_error_label and self.preserve_exception:
4551                     self.put_error_uncatcher(code, i+1, old_error_label)
4552                 else:
4553                     code.use_label(old_label)
4554                     code.putln(
4555                         "case %s: goto %s;" % (
4556                             i+1,
4557                             old_label))
4558             code.putln(
4559                 "}")
4560         code.putln(
4561             "}")
4562
4563     def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4564         code.globalstate.use_utility_code(restore_exception_utility_code)
4565         code.putln(
4566             "%s: {" %
4567                 error_label)
4568         code.putln(
4569                 "__pyx_why = %s;" %
4570                     i)
4571         code.put_var_xdecrefs_clear(self.cleanup_list)
4572         for temp_name, type in temps_to_clean_up:
4573             code.put_xdecref_clear(temp_name, type)
4574         code.putln(
4575                 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4576                     Naming.exc_vars)
4577         code.putln(
4578                 "%s = %s;" % (
4579                     Naming.exc_lineno_name, Naming.lineno_cname))
4580         #code.putln(
4581         #        "goto %s;" %
4582         #            catch_label)
4583         code.put_goto(catch_label)
4584         code.putln(
4585             "}")
4586             
4587     def put_error_uncatcher(self, code, i, error_label):
4588         code.globalstate.use_utility_code(restore_exception_utility_code)
4589         code.putln(
4590             "case %s: {" %
4591                 i)
4592         code.putln(
4593                 "__Pyx_ErrRestore(%s, %s, %s);" %
4594                     Naming.exc_vars)
4595         code.putln(
4596                 "%s = %s;" % (
4597                     Naming.lineno_cname, Naming.exc_lineno_name))
4598         for var in Naming.exc_vars:
4599             code.putln(
4600                 "%s = 0;" %
4601                     var)
4602         code.put_goto(error_label)
4603         code.putln(
4604             "}")
4605
4606     def annotate(self, code):
4607         self.body.annotate(code)
4608         self.finally_clause.annotate(code)
4609
4610
4611 class GILStatNode(TryFinallyStatNode):
4612     #  'with gil' or 'with nogil' statement
4613     #
4614     #   state   string   'gil' or 'nogil'
4615         
4616     child_attrs = []
4617     
4618     preserve_exception = 0
4619
4620     def __init__(self, pos, state, body):
4621         self.state = state
4622         TryFinallyStatNode.__init__(self, pos,
4623             body = body,
4624             finally_clause = GILExitNode(pos, state = state))
4625
4626     def analyse_expressions(self, env):
4627         env.use_utility_code(force_init_threads_utility_code)
4628         was_nogil = env.nogil
4629         env.nogil = 1
4630         TryFinallyStatNode.analyse_expressions(self, env)
4631         env.nogil = was_nogil
4632
4633     def gil_check(self, env):
4634         pass
4635
4636     def generate_execution_code(self, code):
4637         code.mark_pos(self.pos)
4638         if self.state == 'gil':
4639             code.putln("{ PyGILState_STATE _save = PyGILState_Ensure();")
4640         else:
4641             code.putln("{ PyThreadState *_save;")
4642             code.putln("Py_UNBLOCK_THREADS")
4643         TryFinallyStatNode.generate_execution_code(self, code)
4644         code.putln("}")
4645
4646
4647 class GILExitNode(StatNode):
4648     #  Used as the 'finally' block in a GILStatNode
4649     #
4650     #  state   string   'gil' or 'nogil'
4651
4652     child_attrs = []
4653
4654     def analyse_expressions(self, env):
4655         pass
4656
4657     def generate_execution_code(self, code):
4658         if self.state == 'gil':
4659             code.putln("PyGILState_Release();")
4660         else:
4661             code.putln("Py_BLOCK_THREADS")
4662
4663
4664 class CImportStatNode(StatNode):
4665     #  cimport statement
4666     #
4667     #  module_name   string           Qualified name of module being imported
4668     #  as_name       string or None   Name specified in "as" clause, if any
4669
4670     child_attrs = []
4671     
4672     def analyse_declarations(self, env):
4673         if not env.is_module_scope:
4674             error(self.pos, "cimport only allowed at module level")
4675             return
4676         module_scope = env.find_module(self.module_name, self.pos)
4677         if "." in self.module_name:
4678             names = [EncodedString(name) for name in self.module_name.split(".")]
4679             top_name = names[0]
4680             top_module_scope = env.context.find_submodule(top_name)
4681             module_scope = top_module_scope
4682             for name in names[1:]:
4683                 submodule_scope = module_scope.find_submodule(name)
4684                 module_scope.declare_module(name, submodule_scope, self.pos)
4685                 module_scope = submodule_scope
4686             if self.as_name:
4687                 env.declare_module(self.as_name, module_scope, self.pos)
4688             else:
4689                 env.declare_module(top_name, top_module_scope, self.pos)
4690         else:
4691             name = self.as_name or self.module_name
4692             env.declare_module(name, module_scope, self.pos)
4693
4694     def analyse_expressions(self, env):
4695         pass
4696     
4697     def generate_execution_code(self, code):
4698         pass
4699     
4700
4701 class FromCImportStatNode(StatNode):
4702     #  from ... cimport statement
4703     #
4704     #  module_name     string                        Qualified name of module
4705     #  imported_names  [(pos, name, as_name, kind)]  Names to be imported
4706     
4707     child_attrs = []
4708
4709     def analyse_declarations(self, env):
4710         if not env.is_module_scope:
4711             error(self.pos, "cimport only allowed at module level")
4712             return
4713         module_scope = env.find_module(self.module_name, self.pos)
4714         env.add_imported_module(module_scope)
4715         for pos, name, as_name, kind in self.imported_names:
4716             if name == "*":
4717                 for local_name, entry in module_scope.entries.items():
4718                     env.add_imported_entry(local_name, entry, pos)
4719             else:
4720                 entry = module_scope.lookup(name)
4721                 if entry:
4722                     if kind and not self.declaration_matches(entry, kind):
4723                         entry.redeclared(pos)
4724                 else:
4725                     if kind == 'struct' or kind == 'union':
4726                         entry = module_scope.declare_struct_or_union(name,
4727                             kind = kind, scope = None, typedef_flag = 0, pos = pos)
4728                     elif kind == 'class':
4729                         entry = module_scope.declare_c_class(name, pos = pos,
4730                             module_name = self.module_name)
4731                     else:
4732                         submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
4733                         if submodule_scope.parent_module is module_scope:
4734                             env.declare_module(as_name or name, submodule_scope, self.pos)
4735                         else:
4736                             error(pos, "Name '%s' not declared in module '%s'"
4737                                 % (name, self.module_name))
4738                         
4739                 if entry:
4740                     local_name = as_name or name
4741                     env.add_imported_entry(local_name, entry, pos)
4742     
4743     def declaration_matches(self, entry, kind):
4744         if not entry.is_type:
4745             return 0
4746         type = entry.type
4747         if kind == 'class':
4748             if not type.is_extension_type:
4749                 return 0
4750         else:
4751             if not type.is_struct_or_union:
4752                 return 0
4753             if kind != type.kind:
4754                 return 0
4755         return 1
4756
4757     def analyse_expressions(self, env):
4758         pass
4759     
4760     def generate_execution_code(self, code):
4761         pass
4762
4763
4764 class FromImportStatNode(StatNode):
4765     #  from ... import statement
4766     #
4767     #  module           ImportNode
4768     #  items            [(string, NameNode)]
4769     #  interned_items   [(string, NameNode, ExprNode)]
4770     #  item             PyTempNode            used internally
4771     #  import_star      boolean               used internally
4772
4773     child_attrs = ["module"]
4774     import_star = 0
4775     
4776     def analyse_declarations(self, env):
4777         for name, target in self.items:
4778             if name == "*":
4779                 if not env.is_module_scope:
4780                     error(self.pos, "import * only allowed at module level")
4781                     return
4782                 env.has_import_star = 1
4783                 self.import_star = 1
4784             else:
4785                 target.analyse_target_declaration(env)
4786     
4787     def analyse_expressions(self, env):
4788         import ExprNodes
4789         self.module.analyse_expressions(env)
4790         self.item = ExprNodes.PyTempNode(self.pos, env)
4791         self.item.allocate_temp(env)
4792         self.interned_items = []
4793         for name, target in self.items:
4794             if name == '*':
4795                 for _, entry in env.entries.items():
4796                     if not entry.is_type and entry.type.is_extension_type:
4797                         env.use_utility_code(ExprNodes.type_test_utility_code)
4798                         break
4799             else:
4800                 entry =  env.lookup(target.name)
4801                 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4802                     continue # already cimported
4803                 target.analyse_target_expression(env, None)
4804                 if target.type is py_object_type:
4805                     coerced_item = None
4806                 else:
4807                     coerced_item = self.item.coerce_to(target.type, env)
4808                 self.interned_items.append(
4809                     (env.intern_identifier(name), target, coerced_item))
4810                 #target.release_target_temp(env) # was release_temp ?!?
4811         self.module.release_temp(env)
4812         self.item.release_temp(env)
4813     
4814     def generate_execution_code(self, code):
4815         self.module.generate_evaluation_code(code)
4816         if self.import_star:
4817             code.putln(
4818                 'if (%s(%s) < 0) %s;' % (
4819                     Naming.import_star,
4820                     self.module.py_result(),
4821                     code.error_goto(self.pos)))
4822         for cname, target, coerced_item in self.interned_items:
4823             code.putln(
4824                 '%s = PyObject_GetAttr(%s, %s); %s' % (
4825                     self.item.result(), 
4826                     self.module.py_result(),
4827                     cname,
4828                     code.error_goto_if_null(self.item.result(), self.pos)))
4829             code.put_gotref(self.item.py_result())
4830             if coerced_item is None:
4831                 target.generate_assignment_code(self.item, code)
4832             else:
4833                 coerced_item.allocate_temp_result(code)
4834                 coerced_item.generate_result_code(code)
4835                 target.generate_assignment_code(coerced_item, code)
4836                 if self.item.result() != coerced_item.result():
4837                     code.put_decref_clear(self.item.result(), self.item.type)
4838         self.module.generate_disposal_code(code)
4839         self.module.free_temps(code)
4840
4841
4842
4843 #------------------------------------------------------------------------------------
4844 #
4845 #  Runtime support code
4846 #
4847 #------------------------------------------------------------------------------------
4848
4849 utility_function_predeclarations = \
4850 """
4851 #ifdef __GNUC__
4852 #define INLINE __inline__
4853 #elif _WIN32
4854 #define INLINE __inline
4855 #else
4856 #define INLINE 
4857 #endif
4858
4859 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4860
4861 """ + """
4862
4863 static int %(skip_dispatch_cname)s = 0;
4864
4865 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
4866
4867 if Options.gcc_branch_hints:
4868     branch_prediction_macros = \
4869     """
4870 #ifdef __GNUC__
4871 /* Test for GCC > 2.95 */
4872 #if __GNUC__ > 2 || \
4873               (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) 
4874 #define likely(x)   __builtin_expect(!!(x), 1)
4875 #define unlikely(x) __builtin_expect(!!(x), 0)
4876 #else /* __GNUC__ > 2 ... */
4877 #define likely(x)   (x)
4878 #define unlikely(x) (x)
4879 #endif /* __GNUC__ > 2 ... */
4880 #else /* __GNUC__ */
4881 #define likely(x)   (x)
4882 #define unlikely(x) (x)
4883 #endif /* __GNUC__ */
4884     """
4885 else:
4886     branch_prediction_macros = \
4887     """
4888 #define likely(x)   (x)
4889 #define unlikely(x) (x)
4890     """
4891
4892 #get_name_predeclaration = \
4893 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4894
4895 #get_name_interned_predeclaration = \
4896 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4897
4898 #------------------------------------------------------------------------------------
4899
4900 printing_utility_code = UtilityCode(
4901 proto = """
4902 static int __Pyx_Print(PyObject *, int); /*proto*/
4903 #if PY_MAJOR_VERSION >= 3
4904 static PyObject* %s = 0;
4905 static PyObject* %s = 0;
4906 #endif
4907 """ % (Naming.print_function, Naming.print_function_kwargs),
4908 impl = r"""
4909 #if PY_MAJOR_VERSION < 3
4910 static PyObject *__Pyx_GetStdout(void) {
4911     PyObject *f = PySys_GetObject((char *)"stdout");
4912     if (!f) {
4913         PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4914     }
4915     return f;
4916 }
4917
4918 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4919     PyObject *f;
4920     PyObject* v;
4921     int i;
4922
4923     if (!(f = __Pyx_GetStdout()))
4924         return -1;
4925     for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4926         if (PyFile_SoftSpace(f, 1)) {
4927             if (PyFile_WriteString(" ", f) < 0)
4928                 return -1;
4929         }
4930         v = PyTuple_GET_ITEM(arg_tuple, i);
4931         if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4932             return -1;
4933         if (PyString_Check(v)) {
4934             char *s = PyString_AsString(v);
4935             Py_ssize_t len = PyString_Size(v);
4936             if (len > 0 &&
4937                 isspace(Py_CHARMASK(s[len-1])) &&
4938                 s[len-1] != ' ')
4939                     PyFile_SoftSpace(f, 0);
4940         }
4941     }
4942     if (newline) {
4943         if (PyFile_WriteString("\n", f) < 0)
4944             return -1;
4945         PyFile_SoftSpace(f, 0);
4946     }
4947     return 0;
4948 }
4949
4950 #else /* Python 3 has a print function */
4951
4952 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4953     PyObject* kwargs = 0;
4954     PyObject* result = 0;
4955     PyObject* end_string;
4956     if (!%(PRINT_FUNCTION)s) {
4957         %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4958         if (!%(PRINT_FUNCTION)s)
4959             return -1;
4960     }
4961     if (!newline) {
4962         if (!%(PRINT_KWARGS)s) {
4963             %(PRINT_KWARGS)s = PyDict_New();
4964             if (!%(PRINT_KWARGS)s)
4965                 return -1;
4966             end_string = PyUnicode_FromStringAndSize(" ", 1);
4967             if (!end_string)
4968                 return -1;
4969             if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4970                 Py_DECREF(end_string);
4971                 return -1;
4972             }
4973             Py_DECREF(end_string);
4974         }
4975         kwargs = %(PRINT_KWARGS)s;
4976     }
4977     result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4978     if (!result)
4979         return -1;
4980     Py_DECREF(result);
4981     return 0;
4982 }
4983
4984 #endif
4985 """ % {'BUILTINS'       : Naming.builtins_cname,
4986        'PRINT_FUNCTION' : Naming.print_function,
4987        'PRINT_KWARGS'   : Naming.print_function_kwargs}
4988 )
4989
4990
4991 printing_one_utility_code = UtilityCode(
4992 proto = """
4993 static int __Pyx_PrintOne(PyObject *o); /*proto*/
4994 """,
4995 impl = r"""
4996 #if PY_MAJOR_VERSION < 3
4997
4998 static int __Pyx_PrintOne(PyObject *o) {
4999     PyObject *f;
5000     if (!(f = __Pyx_GetStdout()))
5001         return -1;
5002     if (PyFile_SoftSpace(f, 0)) {
5003         if (PyFile_WriteString(" ", f) < 0)
5004             return -1;
5005     }
5006     if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
5007         return -1;
5008     if (PyFile_WriteString("\n", f) < 0)
5009         return -1;
5010     return 0;
5011     /* the line below is just to avoid compiler
5012      * compiler warnings about unused functions */
5013     return __Pyx_Print(NULL, 0);
5014 }
5015
5016 #else /* Python 3 has a print function */
5017
5018 static int __Pyx_PrintOne(PyObject *o) {
5019     int res;
5020     PyObject* arg_tuple = PyTuple_New(1);
5021     if (unlikely(!arg_tuple))
5022         return -1;
5023     Py_INCREF(o);
5024     PyTuple_SET_ITEM(arg_tuple, 0, o);
5025     res = __Pyx_Print(arg_tuple, 1);
5026     Py_DECREF(arg_tuple);
5027     return res;
5028 }
5029
5030 #endif
5031 """,
5032 requires=[printing_utility_code])
5033
5034
5035
5036 #------------------------------------------------------------------------------------
5037
5038 # The following function is based on do_raise() from ceval.c.
5039
5040 raise_utility_code = UtilityCode(
5041 proto = """
5042 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5043 """,
5044 impl = """
5045 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5046     Py_XINCREF(type);
5047     Py_XINCREF(value);
5048     Py_XINCREF(tb);
5049     /* First, check the traceback argument, replacing None with NULL. */
5050     if (tb == Py_None) {
5051         Py_DECREF(tb);
5052         tb = 0;
5053     }
5054     else if (tb != NULL && !PyTraceBack_Check(tb)) {
5055         PyErr_SetString(PyExc_TypeError,
5056             "raise: arg 3 must be a traceback or None");
5057         goto raise_error;
5058     }
5059     /* Next, replace a missing value with None */
5060     if (value == NULL) {
5061         value = Py_None;
5062         Py_INCREF(value);
5063     }
5064     #if PY_VERSION_HEX < 0x02050000
5065     if (!PyClass_Check(type))
5066     #else
5067     if (!PyType_Check(type))
5068     #endif
5069     {
5070         /* Raising an instance.  The value should be a dummy. */
5071         if (value != Py_None) {
5072             PyErr_SetString(PyExc_TypeError,
5073                 "instance exception may not have a separate value");
5074             goto raise_error;
5075         }
5076         /* Normalize to raise <class>, <instance> */
5077         Py_DECREF(value);
5078         value = type;
5079         #if PY_VERSION_HEX < 0x02050000
5080             if (PyInstance_Check(type)) {
5081                 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
5082                 Py_INCREF(type);
5083             }
5084             else {
5085                 type = 0;
5086                 PyErr_SetString(PyExc_TypeError,
5087                     "raise: exception must be an old-style class or instance");
5088                 goto raise_error;
5089             }
5090         #else
5091             type = (PyObject*) Py_TYPE(type);
5092             Py_INCREF(type);
5093             if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
5094                 PyErr_SetString(PyExc_TypeError,
5095                     "raise: exception class must be a subclass of BaseException");
5096                 goto raise_error;
5097             }
5098         #endif
5099     }
5100     __Pyx_ErrRestore(type, value, tb);
5101     return;
5102 raise_error:
5103     Py_XDECREF(value);
5104     Py_XDECREF(type);
5105     Py_XDECREF(tb);
5106     return;
5107 }
5108 """)
5109
5110 #------------------------------------------------------------------------------------
5111
5112 reraise_utility_code = UtilityCode(
5113 proto = """
5114 static void __Pyx_ReRaise(void); /*proto*/
5115 """,
5116 impl = """
5117 static void __Pyx_ReRaise(void) {
5118     PyThreadState *tstate = PyThreadState_GET();
5119     PyObject* tmp_type = tstate->curexc_type;
5120     PyObject* tmp_value = tstate->curexc_value;
5121     PyObject* tmp_tb = tstate->curexc_traceback;
5122     tstate->curexc_type = tstate->exc_type;
5123     tstate->curexc_value = tstate->exc_value;
5124     tstate->curexc_traceback = tstate->exc_traceback;
5125     tstate->exc_type = 0;
5126     tstate->exc_value = 0;
5127     tstate->exc_traceback = 0;
5128     Py_XDECREF(tmp_type);
5129     Py_XDECREF(tmp_value);
5130     Py_XDECREF(tmp_tb);
5131 }
5132 """)
5133
5134 #------------------------------------------------------------------------------------
5135
5136 arg_type_test_utility_code = UtilityCode(
5137 proto = """
5138 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5139     const char *name, int exact); /*proto*/
5140 """,
5141 impl = """
5142 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5143     const char *name, int exact)
5144 {
5145     if (!type) {
5146         PyErr_Format(PyExc_SystemError, "Missing type object");
5147         return 0;
5148     }
5149     if (none_allowed && obj == Py_None) return 1;
5150     else if (exact) {
5151         if (Py_TYPE(obj) == type) return 1;
5152     }
5153     else {
5154         if (PyObject_TypeCheck(obj, type)) return 1;
5155     }
5156     PyErr_Format(PyExc_TypeError,
5157         "Argument '%s' has incorrect type (expected %s, got %s)",
5158         name, type->tp_name, Py_TYPE(obj)->tp_name);
5159     return 0;
5160 }
5161 """)
5162
5163 #------------------------------------------------------------------------------------
5164 #
5165 #  __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5166 #  many or too few positional arguments were found.  This handles
5167 #  Py_ssize_t formatting correctly.
5168
5169 raise_argtuple_invalid_utility_code = UtilityCode(
5170 proto = """
5171 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5172     Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5173 """,
5174 impl = """
5175 static void __Pyx_RaiseArgtupleInvalid(
5176     const char* func_name,
5177     int exact,
5178     Py_ssize_t num_min,
5179     Py_ssize_t num_max,
5180     Py_ssize_t num_found)
5181 {
5182     Py_ssize_t num_expected;
5183     const char *number, *more_or_less;
5184
5185     if (num_found < num_min) {
5186         num_expected = num_min;
5187         more_or_less = "at least";
5188     } else {
5189         num_expected = num_max;
5190         more_or_less = "at most";
5191     }
5192     if (exact) {
5193         more_or_less = "exactly";
5194     }
5195     number = (num_expected == 1) ? "" : "s";
5196     PyErr_Format(PyExc_TypeError,
5197         #if PY_VERSION_HEX < 0x02050000
5198             "%s() takes %s %d positional argument%s (%d given)",
5199         #else
5200             "%s() takes %s %zd positional argument%s (%zd given)",
5201         #endif
5202         func_name, more_or_less, num_expected, number, num_found);
5203 }
5204 """)
5205
5206 raise_keyword_required_utility_code = UtilityCode(
5207 proto = """
5208 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5209 """,
5210 impl = """
5211 static INLINE void __Pyx_RaiseKeywordRequired(
5212     const char* func_name,
5213     PyObject* kw_name)
5214 {
5215     PyErr_Format(PyExc_TypeError,
5216         #if PY_MAJOR_VERSION >= 3
5217         "%s() needs keyword-only argument %U", func_name, kw_name);
5218         #else
5219         "%s() needs keyword-only argument %s", func_name,
5220         PyString_AS_STRING(kw_name));
5221         #endif
5222 }
5223 """)
5224
5225 raise_double_keywords_utility_code = UtilityCode(
5226 proto = """
5227 static void __Pyx_RaiseDoubleKeywordsError(
5228     const char* func_name, PyObject* kw_name); /*proto*/
5229 """,
5230 impl = """
5231 static void __Pyx_RaiseDoubleKeywordsError(
5232     const char* func_name,
5233     PyObject* kw_name)
5234 {
5235     PyErr_Format(PyExc_TypeError,
5236         #if PY_MAJOR_VERSION >= 3
5237         "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5238         #else
5239         "%s() got multiple values for keyword argument '%s'", func_name,
5240         PyString_AS_STRING(kw_name));
5241         #endif
5242 }
5243 """)
5244
5245 #------------------------------------------------------------------------------------
5246 #
5247 #  __Pyx_CheckKeywordStrings raises an error if non-string keywords
5248 #  were passed to a function, or if any keywords were passed to a
5249 #  function that does not accept them.
5250
5251 keyword_string_check_utility_code = UtilityCode(
5252 proto = """
5253 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5254     const char* function_name, int kw_allowed); /*proto*/
5255 """,
5256 impl = """
5257 static INLINE int __Pyx_CheckKeywordStrings(
5258     PyObject *kwdict,
5259     const char* function_name,
5260     int kw_allowed)
5261 {
5262     PyObject* key = 0;
5263     Py_ssize_t pos = 0;
5264     while (PyDict_Next(kwdict, &pos, &key, 0)) {
5265         #if PY_MAJOR_VERSION < 3
5266         if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5267         #else
5268         if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5269         #endif
5270             goto invalid_keyword_type;
5271     }
5272     if ((!kw_allowed) && unlikely(key))
5273         goto invalid_keyword;
5274     return 1;
5275 invalid_keyword_type:
5276     PyErr_Format(PyExc_TypeError,
5277         "%s() keywords must be strings", function_name);
5278     return 0;
5279 invalid_keyword:
5280     PyErr_Format(PyExc_TypeError,
5281     #if PY_MAJOR_VERSION < 3
5282         "%s() got an unexpected keyword argument '%s'",
5283         function_name, PyString_AsString(key));
5284     #else
5285         "%s() got an unexpected keyword argument '%U'",
5286         function_name, key);
5287     #endif
5288     return 0;
5289 }
5290 """)
5291
5292 #------------------------------------------------------------------------------------
5293 #
5294 #  __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5295 #  arguments from the kwds dict into kwds2.  If kwds2 is NULL, unknown
5296 #  keywords will raise an invalid keyword error.
5297 #
5298 #  Three kinds of errors are checked: 1) non-string keywords, 2)
5299 #  unexpected keywords and 3) overlap with positional arguments.
5300 #
5301 #  If num_posargs is greater 0, it denotes the number of positional
5302 #  arguments that were passed and that must therefore not appear
5303 #  amongst the keywords as well.
5304 #
5305 #  This method does not check for required keyword arguments.
5306 #
5307
5308 parse_keywords_utility_code = UtilityCode(
5309 proto = """
5310 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5311     PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5312     const char* function_name); /*proto*/
5313 """,
5314 impl = """
5315 static int __Pyx_ParseOptionalKeywords(
5316     PyObject *kwds,
5317     PyObject **argnames[],
5318     PyObject *kwds2,
5319     PyObject *values[],
5320     Py_ssize_t num_pos_args,
5321     const char* function_name)
5322 {
5323     PyObject *key = 0, *value = 0;
5324     Py_ssize_t pos = 0;
5325     PyObject*** name;
5326     PyObject*** first_kw_arg = argnames + num_pos_args;
5327
5328     while (PyDict_Next(kwds, &pos, &key, &value)) {
5329         name = first_kw_arg;
5330         while (*name && (**name != key)) name++;
5331         if (*name) {
5332             values[name-argnames] = value;
5333         } else {
5334             #if PY_MAJOR_VERSION < 3
5335             if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5336             #else
5337             if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5338             #endif
5339                 goto invalid_keyword_type;
5340             } else {
5341                 for (name = first_kw_arg; *name; name++) {
5342                     #if PY_MAJOR_VERSION >= 3
5343                     if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5344                         PyUnicode_Compare(**name, key) == 0) break;
5345                     #else
5346                     if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5347                         _PyString_Eq(**name, key)) break;
5348                     #endif
5349                 }
5350                 if (*name) {
5351                     values[name-argnames] = value;
5352                 } else {
5353                     /* unexpected keyword found */
5354                     for (name=argnames; name != first_kw_arg; name++) {
5355                         if (**name == key) goto arg_passed_twice;
5356                         #if PY_MAJOR_VERSION >= 3
5357                         if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5358                             PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5359                         #else
5360                         if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5361                             _PyString_Eq(**name, key)) goto arg_passed_twice;
5362                         #endif
5363                     }
5364                     if (kwds2) {
5365                         if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5366                     } else {
5367                         goto invalid_keyword;
5368                     }
5369                 }
5370             }
5371         }
5372     }
5373     return 0;
5374 arg_passed_twice:
5375     __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5376     goto bad;
5377 invalid_keyword_type:
5378     PyErr_Format(PyExc_TypeError,
5379         "%s() keywords must be strings", function_name);
5380     goto bad;
5381 invalid_keyword:
5382     PyErr_Format(PyExc_TypeError,
5383     #if PY_MAJOR_VERSION < 3
5384         "%s() got an unexpected keyword argument '%s'",
5385         function_name, PyString_AsString(key));
5386     #else
5387         "%s() got an unexpected keyword argument '%U'",
5388         function_name, key);
5389     #endif
5390 bad:
5391     return -1;
5392 }
5393 """)
5394
5395 #------------------------------------------------------------------------------------
5396
5397 traceback_utility_code = UtilityCode(
5398 proto = """
5399 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5400 """,
5401 impl = """
5402 #include "compile.h"
5403 #include "frameobject.h"
5404 #include "traceback.h"
5405
5406 static void __Pyx_AddTraceback(const char *funcname) {
5407     PyObject *py_srcfile = 0;
5408     PyObject *py_funcname = 0;
5409     PyObject *py_globals = 0;
5410     PyObject *empty_string = 0;
5411     PyCodeObject *py_code = 0;
5412     PyFrameObject *py_frame = 0;
5413
5414     #if PY_MAJOR_VERSION < 3
5415     py_srcfile = PyString_FromString(%(FILENAME)s);
5416     #else
5417     py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5418     #endif
5419     if (!py_srcfile) goto bad;
5420     if (%(CLINENO)s) {
5421         #if PY_MAJOR_VERSION < 3
5422         py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5423         #else
5424         py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5425         #endif
5426     }
5427     else {
5428         #if PY_MAJOR_VERSION < 3
5429         py_funcname = PyString_FromString(funcname);
5430         #else
5431         py_funcname = PyUnicode_FromString(funcname);
5432         #endif
5433     }
5434     if (!py_funcname) goto bad;
5435     py_globals = PyModule_GetDict(%(GLOBALS)s);
5436     if (!py_globals) goto bad;
5437     #if PY_MAJOR_VERSION < 3
5438     empty_string = PyString_FromStringAndSize("", 0);
5439     #else
5440     empty_string = PyBytes_FromStringAndSize("", 0);
5441     #endif
5442     if (!empty_string) goto bad;
5443     py_code = PyCode_New(
5444         0,            /*int argcount,*/
5445         #if PY_MAJOR_VERSION >= 3
5446         0,            /*int kwonlyargcount,*/
5447         #endif
5448         0,            /*int nlocals,*/
5449         0,            /*int stacksize,*/
5450         0,            /*int flags,*/
5451         empty_string, /*PyObject *code,*/
5452         %(EMPTY_TUPLE)s,  /*PyObject *consts,*/
5453         %(EMPTY_TUPLE)s,  /*PyObject *names,*/
5454         %(EMPTY_TUPLE)s,  /*PyObject *varnames,*/
5455         %(EMPTY_TUPLE)s,  /*PyObject *freevars,*/
5456         %(EMPTY_TUPLE)s,  /*PyObject *cellvars,*/
5457         py_srcfile,   /*PyObject *filename,*/
5458         py_funcname,  /*PyObject *name,*/
5459         %(LINENO)s,   /*int firstlineno,*/
5460         empty_string  /*PyObject *lnotab*/
5461     );
5462     if (!py_code) goto bad;
5463     py_frame = PyFrame_New(
5464         PyThreadState_GET(), /*PyThreadState *tstate,*/
5465         py_code,             /*PyCodeObject *code,*/
5466         py_globals,          /*PyObject *globals,*/
5467         0                    /*PyObject *locals*/
5468     );
5469     if (!py_frame) goto bad;
5470     py_frame->f_lineno = %(LINENO)s;
5471     PyTraceBack_Here(py_frame);
5472 bad:
5473     Py_XDECREF(py_srcfile);
5474     Py_XDECREF(py_funcname);
5475     Py_XDECREF(empty_string);
5476     Py_XDECREF(py_code);
5477     Py_XDECREF(py_frame);
5478 }
5479 """ % {
5480     'FILENAME': Naming.filename_cname,
5481     'LINENO':  Naming.lineno_cname,
5482     'CFILENAME': Naming.cfilenm_cname,
5483     'CLINENO':  Naming.clineno_cname,
5484     'GLOBALS': Naming.module_cname,
5485     'EMPTY_TUPLE' : Naming.empty_tuple,
5486 })
5487
5488 restore_exception_utility_code = UtilityCode(
5489 proto = """
5490 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5491 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5492 """,
5493 impl = """
5494 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5495     PyObject *tmp_type, *tmp_value, *tmp_tb;
5496     PyThreadState *tstate = PyThreadState_GET();
5497
5498 #if PY_MAJOR_VERSION >= 3
5499     /* Note: this is a temporary work-around to prevent crashes in Python 3.0 */
5500     if ((tstate->exc_type != NULL) & (tstate->exc_type != Py_None)) {
5501         tmp_type = tstate->exc_type;
5502         tmp_value = tstate->exc_value;
5503         tmp_tb = tstate->exc_traceback;
5504         PyErr_NormalizeException(&type, &value, &tb);
5505         PyErr_NormalizeException(&tmp_type, &tmp_value, &tmp_tb);
5506         tstate->exc_type = 0;
5507         tstate->exc_value = 0;
5508         tstate->exc_traceback = 0;
5509         PyException_SetContext(value, tmp_value);
5510         Py_DECREF(tmp_type);
5511         Py_XDECREF(tmp_tb);
5512     }
5513 #endif
5514
5515     tmp_type = tstate->curexc_type;
5516     tmp_value = tstate->curexc_value;
5517     tmp_tb = tstate->curexc_traceback;
5518     tstate->curexc_type = type;
5519     tstate->curexc_value = value;
5520     tstate->curexc_traceback = tb;
5521     Py_XDECREF(tmp_type);
5522     Py_XDECREF(tmp_value);
5523     Py_XDECREF(tmp_tb);
5524 }
5525
5526 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5527     PyThreadState *tstate = PyThreadState_GET();
5528     *type = tstate->curexc_type;
5529     *value = tstate->curexc_value;
5530     *tb = tstate->curexc_traceback;
5531
5532     tstate->curexc_type = 0;
5533     tstate->curexc_value = 0;
5534     tstate->curexc_traceback = 0;
5535 }
5536
5537 """)
5538
5539 #------------------------------------------------------------------------------------
5540
5541 unraisable_exception_utility_code = UtilityCode(
5542 proto = """
5543 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5544 """,
5545 impl = """
5546 static void __Pyx_WriteUnraisable(const char *name) {
5547     PyObject *old_exc, *old_val, *old_tb;
5548     PyObject *ctx;
5549     __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5550     #if PY_MAJOR_VERSION < 3
5551     ctx = PyString_FromString(name);
5552     #else
5553     ctx = PyUnicode_FromString(name);
5554     #endif
5555     __Pyx_ErrRestore(old_exc, old_val, old_tb);
5556     if (!ctx) {
5557         PyErr_WriteUnraisable(Py_None);
5558     } else {
5559         PyErr_WriteUnraisable(ctx);
5560         Py_DECREF(ctx);
5561     }
5562 }
5563 """,
5564 requires=[restore_exception_utility_code])
5565
5566 #------------------------------------------------------------------------------------
5567
5568 set_vtable_utility_code = UtilityCode(
5569 proto = """
5570 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5571 """,
5572 impl = """
5573 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5574     PyObject *pycobj = 0;
5575     int result;
5576     
5577     pycobj = PyCObject_FromVoidPtr(vtable, 0);
5578     if (!pycobj)
5579         goto bad;
5580     if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
5581         goto bad;
5582     result = 0;
5583     goto done;
5584
5585 bad:
5586     result = -1;
5587 done:
5588     Py_XDECREF(pycobj);
5589     return result;
5590 }
5591 """)
5592
5593 #------------------------------------------------------------------------------------
5594
5595 get_vtable_utility_code = UtilityCode(
5596 proto = """
5597 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5598 """,
5599 impl = r"""
5600 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5601     int result;
5602     PyObject *pycobj;
5603
5604     pycobj = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5605     if (!pycobj)
5606         goto bad;
5607     *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
5608     if (!*(void **)vtabptr)
5609         goto bad;
5610     result = 0;
5611     goto done;
5612
5613 bad:
5614     result = -1;
5615 done:
5616     Py_XDECREF(pycobj);
5617     return result;
5618 }
5619 """)
5620
5621 #------------------------------------------------------------------------------------
5622
5623 init_string_tab_utility_code = UtilityCode(
5624 proto = """
5625 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5626 """,
5627 impl = """
5628 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5629     while (t->p) {
5630         #if PY_MAJOR_VERSION < 3
5631         if (t->is_unicode && (!t->is_identifier)) {
5632             *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5633         } else if (t->intern) {
5634             *t->p = PyString_InternFromString(t->s);
5635         } else {
5636             *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5637         }
5638         #else  /* Python 3+ has unicode identifiers */
5639         if (t->is_identifier || (t->is_unicode && t->intern)) {
5640             *t->p = PyUnicode_InternFromString(t->s);
5641         } else if (t->is_unicode) {
5642             *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5643         } else {
5644             *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5645         }
5646         #endif
5647         if (!*t->p)
5648             return -1;
5649         ++t;
5650     }
5651     return 0;
5652 }
5653 """)
5654
5655 #------------------------------------------------------------------------------------
5656
5657 get_exception_utility_code = UtilityCode(
5658 proto = """
5659 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5660 """,
5661 impl = """
5662 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5663     PyObject *tmp_type, *tmp_value, *tmp_tb;
5664     PyThreadState *tstate = PyThreadState_GET();
5665     *type = tstate->curexc_type;
5666     *value = tstate->curexc_value;
5667     *tb = tstate->curexc_traceback;
5668     tstate->curexc_type = 0;
5669     tstate->curexc_value = 0;
5670     tstate->curexc_traceback = 0;
5671     PyErr_NormalizeException(type, value, tb);
5672     if (PyErr_Occurred())
5673         goto bad;
5674     Py_INCREF(*type);
5675     Py_INCREF(*value);
5676     Py_INCREF(*tb);
5677     tmp_type = tstate->exc_type;
5678     tmp_value = tstate->exc_value;
5679     tmp_tb = tstate->exc_traceback;
5680     tstate->exc_type = *type;
5681     tstate->exc_value = *value;
5682     tstate->exc_traceback = *tb;
5683     /* Make sure tstate is in a consistent state when we XDECREF
5684     these objects (XDECREF may run arbitrary code). */
5685     Py_XDECREF(tmp_type);
5686     Py_XDECREF(tmp_value);
5687     Py_XDECREF(tmp_tb);
5688     return 0;
5689 bad:
5690     Py_XDECREF(*type);
5691     Py_XDECREF(*value);
5692     Py_XDECREF(*tb);
5693     return -1;
5694 }
5695
5696 """)
5697
5698 #------------------------------------------------------------------------------------
5699
5700 reset_exception_utility_code = UtilityCode(
5701 proto = """
5702 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5703 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5704 """,
5705 impl = """
5706 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5707     PyThreadState *tstate = PyThreadState_GET();
5708     *type = tstate->exc_type;
5709     *value = tstate->exc_value;
5710     *tb = tstate->exc_traceback;
5711     Py_XINCREF(*type);
5712     Py_XINCREF(*value);
5713     Py_XINCREF(*tb);
5714 }
5715
5716 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5717     PyObject *tmp_type, *tmp_value, *tmp_tb;
5718     PyThreadState *tstate = PyThreadState_GET();
5719     tmp_type = tstate->exc_type;
5720     tmp_value = tstate->exc_value;
5721     tmp_tb = tstate->exc_traceback;
5722     tstate->exc_type = type;
5723     tstate->exc_value = value;
5724     tstate->exc_traceback = tb;
5725     Py_XDECREF(tmp_type);
5726     Py_XDECREF(tmp_value);
5727     Py_XDECREF(tmp_tb);
5728 }
5729 """)
5730
5731 #------------------------------------------------------------------------------------
5732
5733 force_init_threads_utility_code = UtilityCode(
5734 proto="""
5735 #ifndef __PYX_FORCE_INIT_THREADS
5736 #if PY_VERSION_HEX < 0x02040200
5737 #define __PYX_FORCE_INIT_THREADS 1
5738 #else
5739 #define __PYX_FORCE_INIT_THREADS 0
5740 #endif
5741 #endif
5742 """)
5743
5744 #------------------------------------------------------------------------------------