• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#
2#   Parse tree nodes
3#
4
5import cython
6cython.declare(sys=object, os=object, copy=object,
7               Builtin=object, error=object, warning=object, Naming=object, PyrexTypes=object,
8               py_object_type=object, ModuleScope=object, LocalScope=object, ClosureScope=object,
9               StructOrUnionScope=object, PyClassScope=object,
10               CppClassScope=object, UtilityCode=object, EncodedString=object,
11               absolute_path_length=cython.Py_ssize_t)
12
13import sys, os, copy
14from itertools import chain
15
16import Builtin
17from Errors import error, warning, InternalError, CompileError
18import Naming
19import PyrexTypes
20import TypeSlots
21from PyrexTypes import py_object_type, error_type
22from Symtab import (ModuleScope, LocalScope, ClosureScope,
23    StructOrUnionScope, PyClassScope, CppClassScope, TemplateScope)
24from Code import UtilityCode
25from StringEncoding import EncodedString, escape_byte_string, split_string_literal
26import Options
27import DebugFlags
28from Cython.Utils import cached_function
29
30absolute_path_length = 0
31
32def relative_position(pos):
33    """
34    We embed the relative filename in the generated C file, since we
35    don't want to have to regenerate and compile all the source code
36    whenever the Python install directory moves (which could happen,
37    e.g,. when distributing binaries.)
38
39    INPUT:
40        a position tuple -- (absolute filename, line number column position)
41
42    OUTPUT:
43        relative filename
44        line number
45
46    AUTHOR: William Stein
47    """
48    global absolute_path_length
49    if absolute_path_length==0:
50        absolute_path_length = len(os.path.abspath(os.getcwd()))
51    return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
52
53def embed_position(pos, docstring):
54    if not Options.embed_pos_in_docstring:
55        return docstring
56    pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
57    if docstring is None:
58        # unicode string
59        return EncodedString(pos_line)
60
61    # make sure we can encode the filename in the docstring encoding
62    # otherwise make the docstring a unicode string
63    encoding = docstring.encoding
64    if encoding is not None:
65        try:
66            pos_line.encode(encoding)
67        except UnicodeEncodeError:
68            encoding = None
69
70    if not docstring:
71        # reuse the string encoding of the original docstring
72        doc = EncodedString(pos_line)
73    else:
74        doc = EncodedString(pos_line + u'\n' + docstring)
75    doc.encoding = encoding
76    return doc
77
78
79def write_func_call(func, codewriter_class):
80    def f(*args, **kwds):
81        if len(args) > 1 and isinstance(args[1], codewriter_class):
82            # here we annotate the code with this function call
83            # but only if new code is generated
84            node, code = args[:2]
85            marker = '                    /* %s -> %s.%s %s */' % (
86                    ' ' * code.call_level,
87                    node.__class__.__name__,
88                    func.__name__,
89                    node.pos[1:])
90            pristine = code.buffer.stream.tell()
91            code.putln(marker)
92            start = code.buffer.stream.tell()
93            code.call_level += 4
94            res = func(*args, **kwds)
95            code.call_level -= 4
96            if start == code.buffer.stream.tell():
97                code.buffer.stream.seek(pristine)
98            else:
99                marker = marker.replace('->', '<-')
100                code.putln(marker)
101            return res
102        else:
103            return func(*args, **kwds)
104    return f
105
106class VerboseCodeWriter(type):
107    # Set this as a metaclass to trace function calls in code.
108    # This slows down code generation and makes much larger files.
109    def __new__(cls, name, bases, attrs):
110        from types import FunctionType
111        from Code import CCodeWriter
112        attrs = dict(attrs)
113        for mname, m in attrs.items():
114            if isinstance(m, FunctionType):
115                attrs[mname] = write_func_call(m, CCodeWriter)
116        return super(VerboseCodeWriter, cls).__new__(cls, name, bases, attrs)
117
118
119class CheckAnalysers(type):
120    """Metaclass to check that type analysis functions return a node.
121    """
122    methods = set(['analyse_types',
123                   'analyse_expressions',
124                   'analyse_target_types'])
125
126    def __new__(cls, name, bases, attrs):
127        from types import FunctionType
128        def check(name, func):
129            def call(*args, **kwargs):
130                retval = func(*args, **kwargs)
131                if retval is None:
132                    print name, args, kwargs
133                return retval
134            return call
135
136        attrs = dict(attrs)
137        for mname, m in attrs.items():
138            if isinstance(m, FunctionType) and mname in cls.methods:
139                attrs[mname] = check(mname, m)
140        return super(CheckAnalysers, cls).__new__(cls, name, bases, attrs)
141
142
143class Node(object):
144    #  pos         (string, int, int)   Source file position
145    #  is_name     boolean              Is a NameNode
146    #  is_literal  boolean              Is a ConstNode
147
148    #__metaclass__ = CheckAnalysers
149    if DebugFlags.debug_trace_code_generation:
150        __metaclass__ = VerboseCodeWriter
151
152    is_name = 0
153    is_none = 0
154    is_nonecheck = 0
155    is_literal = 0
156    is_terminator = 0
157    temps = None
158
159    # All descendants should set child_attrs to a list of the attributes
160    # containing nodes considered "children" in the tree. Each such attribute
161    # can either contain a single node or a list of nodes. See Visitor.py.
162    child_attrs = None
163
164    cf_state = None
165
166    # This may be an additional (or 'actual') type that will be checked when
167    # this node is coerced to another type. This could be useful to set when
168    # the actual type to which it can coerce is known, but you want to leave
169    # the type a py_object_type
170    coercion_type = None
171
172    def __init__(self, pos, **kw):
173        self.pos = pos
174        self.__dict__.update(kw)
175
176    gil_message = "Operation"
177
178    nogil_check = None
179
180    def gil_error(self, env=None):
181        error(self.pos, "%s not allowed without gil" % self.gil_message)
182
183    cpp_message = "Operation"
184
185    def cpp_check(self, env):
186        if not env.is_cpp():
187            self.cpp_error()
188
189    def cpp_error(self):
190        error(self.pos, "%s only allowed in c++" % self.cpp_message)
191
192    def clone_node(self):
193        """Clone the node. This is defined as a shallow copy, except for member lists
194           amongst the child attributes (from get_child_accessors) which are also
195           copied. Lists containing child nodes are thus seen as a way for the node
196           to hold multiple children directly; the list is not treated as a separate
197           level in the tree."""
198        result = copy.copy(self)
199        for attrname in result.child_attrs:
200            value = getattr(result, attrname)
201            if isinstance(value, list):
202                setattr(result, attrname, [x for x in value])
203        return result
204
205
206    #
207    #  There are 3 phases of parse tree processing, applied in order to
208    #  all the statements in a given scope-block:
209    #
210    #  (0) analyse_declarations
211    #        Make symbol table entries for all declarations at the current
212    #        level, both explicit (def, cdef, etc.) and implicit (assignment
213    #        to an otherwise undeclared name).
214    #
215    #  (1) analyse_expressions
216    #         Determine the result types of expressions and fill in the
217    #         'type' attribute of each ExprNode. Insert coercion nodes into the
218    #         tree where needed to convert to and from Python objects.
219    #         Allocate temporary locals for intermediate results. Fill
220    #         in the 'result_code' attribute of each ExprNode with a C code
221    #         fragment.
222    #
223    #  (2) generate_code
224    #         Emit C code for all declarations, statements and expressions.
225    #         Recursively applies the 3 processing phases to the bodies of
226    #         functions.
227    #
228
229    def analyse_declarations(self, env):
230        pass
231
232    def analyse_expressions(self, env):
233        raise InternalError("analyse_expressions not implemented for %s" % \
234            self.__class__.__name__)
235
236    def generate_code(self, code):
237        raise InternalError("generate_code not implemented for %s" % \
238            self.__class__.__name__)
239
240    def annotate(self, code):
241        # mro does the wrong thing
242        if isinstance(self, BlockNode):
243            self.body.annotate(code)
244
245    def end_pos(self):
246        try:
247            return self._end_pos
248        except AttributeError:
249            pos = self.pos
250            if not self.child_attrs:
251                self._end_pos = pos
252                return pos
253            for attr in self.child_attrs:
254                child = getattr(self, attr)
255                # Sometimes lists, sometimes nodes
256                if child is None:
257                    pass
258                elif isinstance(child, list):
259                    for c in child:
260                        pos = max(pos, c.end_pos())
261                else:
262                    pos = max(pos, child.end_pos())
263            self._end_pos = pos
264            return pos
265
266    def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
267        """Debug helper method that returns a recursive string representation of this node.
268        """
269        if cutoff == 0:
270            return "<...nesting level cutoff...>"
271        if encountered is None:
272            encountered = set()
273        if id(self) in encountered:
274            return "<%s (0x%x) -- already output>" % (self.__class__.__name__, id(self))
275        encountered.add(id(self))
276
277        def dump_child(x, level):
278            if isinstance(x, Node):
279                return x.dump(level, filter_out, cutoff-1, encountered)
280            elif isinstance(x, list):
281                return "[%s]" % ", ".join([dump_child(item, level) for item in x])
282            else:
283                return repr(x)
284
285
286        attrs = [(key, value) for key, value in self.__dict__.items() if key not in filter_out]
287        if len(attrs) == 0:
288            return "<%s (0x%x)>" % (self.__class__.__name__, id(self))
289        else:
290            indent = "  " * level
291            res = "<%s (0x%x)\n" % (self.__class__.__name__, id(self))
292            for key, value in attrs:
293                res += "%s  %s: %s\n" % (indent, key, dump_child(value, level + 1))
294            res += "%s>" % indent
295            return res
296
297    def dump_pos(self, mark_column=False, marker='(#)'):
298        """Debug helper method that returns the source code context of this node as a string.
299        """
300        if not self.pos:
301            return u''
302        source_desc, line, col = self.pos
303        contents = source_desc.get_lines(encoding='ASCII',
304                                         error_handling='ignore')
305        # line numbers start at 1
306        lines = contents[max(0,line-3):line]
307        current = lines[-1]
308        if mark_column:
309            current = current[:col] + marker + current[col:]
310        lines[-1] = current.rstrip() + u'             # <<<<<<<<<<<<<<\n'
311        lines += contents[line:line+2]
312        return u'"%s":%d:%d\n%s\n' % (
313            source_desc.get_escaped_description(), line, col, u''.join(lines))
314
315class CompilerDirectivesNode(Node):
316    """
317    Sets compiler directives for the children nodes
318    """
319    #  directives     {string:value}  A dictionary holding the right value for
320    #                                 *all* possible directives.
321    #  body           Node
322    child_attrs = ["body"]
323
324    def analyse_declarations(self, env):
325        old = env.directives
326        env.directives = self.directives
327        self.body.analyse_declarations(env)
328        env.directives = old
329
330    def analyse_expressions(self, env):
331        old = env.directives
332        env.directives = self.directives
333        self.body = self.body.analyse_expressions(env)
334        env.directives = old
335        return self
336
337    def generate_function_definitions(self, env, code):
338        env_old = env.directives
339        code_old = code.globalstate.directives
340        code.globalstate.directives = self.directives
341        self.body.generate_function_definitions(env, code)
342        env.directives = env_old
343        code.globalstate.directives = code_old
344
345    def generate_execution_code(self, code):
346        old = code.globalstate.directives
347        code.globalstate.directives = self.directives
348        self.body.generate_execution_code(code)
349        code.globalstate.directives = old
350
351    def annotate(self, code):
352        old = code.globalstate.directives
353        code.globalstate.directives = self.directives
354        self.body.annotate(code)
355        code.globalstate.directives = old
356
357class BlockNode(object):
358    #  Mixin class for nodes representing a declaration block.
359
360    def generate_cached_builtins_decls(self, env, code):
361        entries = env.global_scope().undeclared_cached_builtins
362        for entry in entries:
363            code.globalstate.add_cached_builtin_decl(entry)
364        del entries[:]
365
366    def generate_lambda_definitions(self, env, code):
367        for node in env.lambda_defs:
368            node.generate_function_definitions(env, code)
369
370class StatListNode(Node):
371    # stats     a list of StatNode
372
373    child_attrs = ["stats"]
374
375    def create_analysed(pos, env, *args, **kw):
376        node = StatListNode(pos, *args, **kw)
377        return node # No node-specific analysis necesarry
378    create_analysed = staticmethod(create_analysed)
379
380    def analyse_declarations(self, env):
381        #print "StatListNode.analyse_declarations" ###
382        for stat in self.stats:
383            stat.analyse_declarations(env)
384
385    def analyse_expressions(self, env):
386        #print "StatListNode.analyse_expressions" ###
387        self.stats = [ stat.analyse_expressions(env)
388                       for stat in self.stats ]
389        return self
390
391    def generate_function_definitions(self, env, code):
392        #print "StatListNode.generate_function_definitions" ###
393        for stat in self.stats:
394            stat.generate_function_definitions(env, code)
395
396    def generate_execution_code(self, code):
397        #print "StatListNode.generate_execution_code" ###
398        for stat in self.stats:
399            code.mark_pos(stat.pos)
400            stat.generate_execution_code(code)
401
402    def annotate(self, code):
403        for stat in self.stats:
404            stat.annotate(code)
405
406
407class StatNode(Node):
408    #
409    #  Code generation for statements is split into the following subphases:
410    #
411    #  (1) generate_function_definitions
412    #        Emit C code for the definitions of any structs,
413    #        unions, enums and functions defined in the current
414    #        scope-block.
415    #
416    #  (2) generate_execution_code
417    #        Emit C code for executable statements.
418    #
419
420    def generate_function_definitions(self, env, code):
421        pass
422
423    def generate_execution_code(self, code):
424        raise InternalError("generate_execution_code not implemented for %s" % \
425            self.__class__.__name__)
426
427
428class CDefExternNode(StatNode):
429    #  include_file   string or None
430    #  body           StatNode
431
432    child_attrs = ["body"]
433
434    def analyse_declarations(self, env):
435        if self.include_file:
436            env.add_include_file(self.include_file)
437        old_cinclude_flag = env.in_cinclude
438        env.in_cinclude = 1
439        self.body.analyse_declarations(env)
440        env.in_cinclude = old_cinclude_flag
441
442    def analyse_expressions(self, env):
443        return self
444
445    def generate_execution_code(self, code):
446        pass
447
448    def annotate(self, code):
449        self.body.annotate(code)
450
451
452class CDeclaratorNode(Node):
453    # Part of a C declaration.
454    #
455    # Processing during analyse_declarations phase:
456    #
457    #   analyse
458    #      Returns (name, type) pair where name is the
459    #      CNameDeclaratorNode of the name being declared
460    #      and type is the type it is being declared as.
461    #
462    #  calling_convention  string   Calling convention of CFuncDeclaratorNode
463    #                               for which this is a base
464
465    child_attrs = []
466
467    calling_convention = ""
468
469    def analyse_templates(self):
470        # Only C++ functions have templates.
471        return None
472
473class CNameDeclaratorNode(CDeclaratorNode):
474    #  name    string             The Cython name being declared
475    #  cname   string or None     C name, if specified
476    #  default ExprNode or None   the value assigned on declaration
477
478    child_attrs = ['default']
479
480    default = None
481
482    def analyse(self, base_type, env, nonempty = 0):
483        if nonempty and self.name == '':
484            # May have mistaken the name for the type.
485            if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
486                error(self.pos, "Missing argument name")
487            elif base_type.is_void:
488                error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
489            else:
490                self.name = base_type.declaration_code("", for_display=1, pyrex=1)
491                base_type = py_object_type
492
493        if base_type.is_fused and env.fused_to_specific:
494            base_type = base_type.specialize(env.fused_to_specific)
495
496        self.type = base_type
497        return self, base_type
498
499class CPtrDeclaratorNode(CDeclaratorNode):
500    # base     CDeclaratorNode
501
502    child_attrs = ["base"]
503
504    def analyse(self, base_type, env, nonempty = 0):
505        if base_type.is_pyobject:
506            error(self.pos,
507                "Pointer base type cannot be a Python object")
508        ptr_type = PyrexTypes.c_ptr_type(base_type)
509        return self.base.analyse(ptr_type, env, nonempty = nonempty)
510
511class CReferenceDeclaratorNode(CDeclaratorNode):
512    # base     CDeclaratorNode
513
514    child_attrs = ["base"]
515
516    def analyse(self, base_type, env, nonempty = 0):
517        if base_type.is_pyobject:
518            error(self.pos,
519                  "Reference base type cannot be a Python object")
520        ref_type = PyrexTypes.c_ref_type(base_type)
521        return self.base.analyse(ref_type, env, nonempty = nonempty)
522
523class CArrayDeclaratorNode(CDeclaratorNode):
524    # base        CDeclaratorNode
525    # dimension   ExprNode
526
527    child_attrs = ["base", "dimension"]
528
529    def analyse(self, base_type, env, nonempty = 0):
530        if base_type.is_cpp_class or base_type.is_cfunction:
531            from ExprNodes import TupleNode
532            if isinstance(self.dimension, TupleNode):
533                args = self.dimension.args
534            else:
535                args = self.dimension,
536            values = [v.analyse_as_type(env) for v in args]
537            if None in values:
538                ix = values.index(None)
539                error(args[ix].pos, "Template parameter not a type")
540                base_type = error_type
541            else:
542                base_type = base_type.specialize_here(self.pos, values)
543            return self.base.analyse(base_type, env, nonempty = nonempty)
544        if self.dimension:
545            self.dimension = self.dimension.analyse_const_expression(env)
546            if not self.dimension.type.is_int:
547                error(self.dimension.pos, "Array dimension not integer")
548            size = self.dimension.get_constant_c_result_code()
549            if size is not None:
550                try:
551                    size = int(size)
552                except ValueError:
553                    # runtime constant?
554                    pass
555        else:
556            size = None
557        if not base_type.is_complete():
558            error(self.pos,
559                "Array element type '%s' is incomplete" % base_type)
560        if base_type.is_pyobject:
561            error(self.pos,
562                "Array element cannot be a Python object")
563        if base_type.is_cfunction:
564            error(self.pos,
565                "Array element cannot be a function")
566        array_type = PyrexTypes.c_array_type(base_type, size)
567        return self.base.analyse(array_type, env, nonempty = nonempty)
568
569
570class CFuncDeclaratorNode(CDeclaratorNode):
571    # base             CDeclaratorNode
572    # args             [CArgDeclNode]
573    # templates        [TemplatePlaceholderType]
574    # has_varargs      boolean
575    # exception_value  ConstNode
576    # exception_check  boolean    True if PyErr_Occurred check needed
577    # nogil            boolean    Can be called without gil
578    # with_gil         boolean    Acquire gil around function body
579    # is_const_method  boolean    Whether this is a const method
580
581    child_attrs = ["base", "args", "exception_value"]
582
583    overridable = 0
584    optional_arg_count = 0
585    is_const_method = 0
586    templates = None
587
588    def analyse_templates(self):
589        if isinstance(self.base, CArrayDeclaratorNode):
590            from ExprNodes import TupleNode, NameNode
591            template_node = self.base.dimension
592            if isinstance(template_node, TupleNode):
593                template_nodes = template_node.args
594            elif isinstance(template_node, NameNode):
595                template_nodes = [template_node]
596            else:
597                error(template_node.pos, "Template arguments must be a list of names")
598                return None
599            self.templates = []
600            for template in template_nodes:
601                if isinstance(template, NameNode):
602                    self.templates.append(PyrexTypes.TemplatePlaceholderType(template.name))
603                else:
604                    error(template.pos, "Template arguments must be a list of names")
605            self.base = self.base.base
606            return self.templates
607        else:
608            return None
609
610    def analyse(self, return_type, env, nonempty = 0, directive_locals = {}):
611        if nonempty:
612            nonempty -= 1
613        func_type_args = []
614        for i, arg_node in enumerate(self.args):
615            name_declarator, type = arg_node.analyse(env, nonempty = nonempty,
616                                                     is_self_arg = (i == 0 and env.is_c_class_scope))
617            name = name_declarator.name
618            if name in directive_locals:
619                type_node = directive_locals[name]
620                other_type = type_node.analyse_as_type(env)
621                if other_type is None:
622                    error(type_node.pos, "Not a type")
623                elif (type is not PyrexTypes.py_object_type
624                      and not type.same_as(other_type)):
625                    error(self.base.pos, "Signature does not agree with previous declaration")
626                    error(type_node.pos, "Previous declaration here")
627                else:
628                    type = other_type
629            if name_declarator.cname:
630                error(self.pos,
631                    "Function argument cannot have C name specification")
632            if i==0 and env.is_c_class_scope and type.is_unspecified:
633                # fix the type of self
634                type = env.parent_type
635            # Turn *[] argument into **
636            if type.is_array:
637                type = PyrexTypes.c_ptr_type(type.base_type)
638            # Catch attempted C-style func(void) decl
639            if type.is_void:
640                error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
641            func_type_args.append(
642                PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
643            if arg_node.default:
644                self.optional_arg_count += 1
645            elif self.optional_arg_count:
646                error(self.pos, "Non-default argument follows default argument")
647
648        exc_val = None
649        exc_check = 0
650        if self.exception_check == '+':
651            env.add_include_file('ios')         # for std::ios_base::failure
652            env.add_include_file('new')         # for std::bad_alloc
653            env.add_include_file('stdexcept')
654            env.add_include_file('typeinfo')    # for std::bad_cast
655        if (return_type.is_pyobject
656                and (self.exception_value or self.exception_check)
657                and self.exception_check != '+'):
658            error(self.pos,
659                "Exception clause not allowed for function returning Python object")
660        else:
661            if self.exception_value:
662                self.exception_value = self.exception_value.analyse_const_expression(env)
663                if self.exception_check == '+':
664                    exc_val_type = self.exception_value.type
665                    if (not exc_val_type.is_error
666                            and not exc_val_type.is_pyobject
667                            and not (exc_val_type.is_cfunction
668                                     and not exc_val_type.return_type.is_pyobject
669                                     and not exc_val_type.args)):
670                        error(self.exception_value.pos,
671                              "Exception value must be a Python exception or cdef function with no arguments.")
672                    exc_val = self.exception_value
673                else:
674                    self.exception_value = self.exception_value.coerce_to(
675                        return_type, env).analyse_const_expression(env)
676                    exc_val = self.exception_value.get_constant_c_result_code()
677                    if exc_val is None:
678                        raise InternalError(
679                            "get_constant_c_result_code not implemented for %s" %
680                            self.exception_value.__class__.__name__)
681                    if not return_type.assignable_from(self.exception_value.type):
682                        error(self.exception_value.pos,
683                              "Exception value incompatible with function return type")
684            exc_check = self.exception_check
685        if return_type.is_cfunction:
686            error(self.pos,
687                "Function cannot return a function")
688        func_type = PyrexTypes.CFuncType(
689            return_type, func_type_args, self.has_varargs,
690            optional_arg_count = self.optional_arg_count,
691            exception_value = exc_val, exception_check = exc_check,
692            calling_convention = self.base.calling_convention,
693            nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable,
694            is_const_method = self.is_const_method,
695            templates = self.templates)
696
697        if self.optional_arg_count:
698            if func_type.is_fused:
699                # This is a bit of a hack... When we need to create specialized CFuncTypes
700                # on the fly because the cdef is defined in a pxd, we need to declare the specialized optional arg
701                # struct
702                def declare_opt_arg_struct(func_type, fused_cname):
703                    self.declare_optional_arg_struct(func_type, env, fused_cname)
704
705                func_type.declare_opt_arg_struct = declare_opt_arg_struct
706            else:
707                self.declare_optional_arg_struct(func_type, env)
708
709        callspec = env.directives['callspec']
710        if callspec:
711            current = func_type.calling_convention
712            if current and current != callspec:
713                error(self.pos, "cannot have both '%s' and '%s' "
714                      "calling conventions" % (current, callspec))
715            func_type.calling_convention = callspec
716        return self.base.analyse(func_type, env)
717
718    def declare_optional_arg_struct(self, func_type, env, fused_cname=None):
719        """
720        Declares the optional argument struct (the struct used to hold the
721        values for optional arguments). For fused cdef functions, this is
722        deferred as analyse_declarations is called only once (on the fused
723        cdef function).
724        """
725        scope = StructOrUnionScope()
726        arg_count_member = '%sn' % Naming.pyrex_prefix
727        scope.declare_var(arg_count_member, PyrexTypes.c_int_type, self.pos)
728
729        for arg in func_type.args[len(func_type.args)-self.optional_arg_count:]:
730            scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
731
732        struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
733
734        if fused_cname is not None:
735            struct_cname = PyrexTypes.get_fused_cname(fused_cname, struct_cname)
736
737        op_args_struct = env.global_scope().declare_struct_or_union(
738                name = struct_cname,
739                kind = 'struct',
740                scope = scope,
741                typedef_flag = 0,
742                pos = self.pos,
743                cname = struct_cname)
744
745        op_args_struct.defined_in_pxd = 1
746        op_args_struct.used = 1
747
748        func_type.op_arg_struct = PyrexTypes.c_ptr_type(op_args_struct.type)
749
750
751class CConstDeclaratorNode(CDeclaratorNode):
752    # base     CDeclaratorNode
753
754    child_attrs = ["base"]
755
756    def analyse(self, base_type, env, nonempty = 0):
757        if base_type.is_pyobject:
758            error(self.pos,
759                  "Const base type cannot be a Python object")
760        const = PyrexTypes.c_const_type(base_type)
761        return self.base.analyse(const, env, nonempty = nonempty)
762
763
764class CArgDeclNode(Node):
765    # Item in a function declaration argument list.
766    #
767    # base_type      CBaseTypeNode
768    # declarator     CDeclaratorNode
769    # not_none       boolean            Tagged with 'not None'
770    # or_none        boolean            Tagged with 'or None'
771    # accept_none    boolean            Resolved boolean for not_none/or_none
772    # default        ExprNode or None
773    # default_value  PyObjectConst      constant for default value
774    # annotation     ExprNode or None   Py3 function arg annotation
775    # is_self_arg    boolean            Is the "self" arg of an extension type method
776    # is_type_arg    boolean            Is the "class" arg of an extension type classmethod
777    # is_kw_only     boolean            Is a keyword-only argument
778    # is_dynamic     boolean            Non-literal arg stored inside CyFunction
779
780    child_attrs = ["base_type", "declarator", "default", "annotation"]
781
782    is_self_arg = 0
783    is_type_arg = 0
784    is_generic = 1
785    kw_only = 0
786    not_none = 0
787    or_none = 0
788    type = None
789    name_declarator = None
790    default_value = None
791    annotation = None
792    is_dynamic = 0
793
794    def analyse(self, env, nonempty = 0, is_self_arg = False):
795        if is_self_arg:
796            self.base_type.is_self_arg = self.is_self_arg = True
797        if self.type is None:
798            # The parser may misinterpret names as types. We fix that here.
799            if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
800                if nonempty:
801                    if self.base_type.is_basic_c_type:
802                        # char, short, long called "int"
803                        type = self.base_type.analyse(env, could_be_name = True)
804                        arg_name = type.declaration_code("")
805                    else:
806                        arg_name = self.base_type.name
807                    self.declarator.name = EncodedString(arg_name)
808                    self.base_type.name = None
809                    self.base_type.is_basic_c_type = False
810                could_be_name = True
811            else:
812                could_be_name = False
813            self.base_type.is_arg = True
814            base_type = self.base_type.analyse(env, could_be_name = could_be_name)
815            if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
816                self.declarator.name = self.base_type.arg_name
817            # The parser is unable to resolve the ambiguity of [] as part of the
818            # type (e.g. in buffers) or empty declarator (as with arrays).
819            # This is only arises for empty multi-dimensional arrays.
820            if (base_type.is_array
821                    and isinstance(self.base_type, TemplatedTypeNode)
822                    and isinstance(self.declarator, CArrayDeclaratorNode)):
823                declarator = self.declarator
824                while isinstance(declarator.base, CArrayDeclaratorNode):
825                    declarator = declarator.base
826                declarator.base = self.base_type.array_declarator
827                base_type = base_type.base_type
828            return self.declarator.analyse(base_type, env, nonempty = nonempty)
829        else:
830            return self.name_declarator, self.type
831
832    def calculate_default_value_code(self, code):
833        if self.default_value is None:
834            if self.default:
835                if self.default.is_literal:
836                    # will not output any code, just assign the result_code
837                    self.default.generate_evaluation_code(code)
838                    return self.type.cast_code(self.default.result())
839                self.default_value = code.get_argument_default_const(self.type)
840        return self.default_value
841
842    def annotate(self, code):
843        if self.default:
844            self.default.annotate(code)
845
846    def generate_assignment_code(self, code, target=None):
847        default = self.default
848        if default is None or default.is_literal:
849            return
850        if target is None:
851            target = self.calculate_default_value_code(code)
852        default.generate_evaluation_code(code)
853        default.make_owned_reference(code)
854        result = default.result_as(self.type)
855        code.putln("%s = %s;" % (target, result))
856        if self.type.is_pyobject:
857            code.put_giveref(default.result())
858        default.generate_post_assignment_code(code)
859        default.free_temps(code)
860
861
862class CBaseTypeNode(Node):
863    # Abstract base class for C base type nodes.
864    #
865    # Processing during analyse_declarations phase:
866    #
867    #   analyse
868    #     Returns the type.
869
870    pass
871
872    def analyse_as_type(self, env):
873        return self.analyse(env)
874
875class CAnalysedBaseTypeNode(Node):
876    # type            type
877
878    child_attrs = []
879
880    def analyse(self, env, could_be_name = False):
881        return self.type
882
883class CSimpleBaseTypeNode(CBaseTypeNode):
884    # name             string
885    # module_path      [string]     Qualifying name components
886    # is_basic_c_type  boolean
887    # signed           boolean
888    # longness         integer
889    # complex          boolean
890    # is_self_arg      boolean      Is self argument of C method
891    # ##is_type_arg      boolean      Is type argument of class method
892
893    child_attrs = []
894    arg_name = None   # in case the argument name was interpreted as a type
895    module_path = []
896    is_basic_c_type = False
897    complex = False
898
899    def analyse(self, env, could_be_name = False):
900        # Return type descriptor.
901        #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
902        type = None
903        if self.is_basic_c_type:
904            type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
905            if not type:
906                error(self.pos, "Unrecognised type modifier combination")
907        elif self.name == "object" and not self.module_path:
908            type = py_object_type
909        elif self.name is None:
910            if self.is_self_arg and env.is_c_class_scope:
911                #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
912                type = env.parent_type
913            ## elif self.is_type_arg and env.is_c_class_scope:
914            ##     type = Builtin.type_type
915            else:
916                type = py_object_type
917        else:
918            if self.module_path:
919                # Maybe it's a nested C++ class.
920                scope = env
921                for item in self.module_path:
922                    entry = scope.lookup(item)
923                    if entry is not None and entry.is_cpp_class:
924                        scope = entry.type.scope
925                    else:
926                        scope = None
927                        break
928
929                if scope is None:
930                    # Maybe it's a cimport.
931                    scope = env.find_imported_module(self.module_path, self.pos)
932                    if scope:
933                        scope.fused_to_specific = env.fused_to_specific
934            else:
935                scope = env
936
937            if scope:
938                if scope.is_c_class_scope:
939                    scope = scope.global_scope()
940
941                type = scope.lookup_type(self.name)
942                if type is not None:
943                    pass
944                elif could_be_name:
945                    if self.is_self_arg and env.is_c_class_scope:
946                        type = env.parent_type
947                    ## elif self.is_type_arg and env.is_c_class_scope:
948                    ##     type = Builtin.type_type
949                    else:
950                        type = py_object_type
951                    self.arg_name = EncodedString(self.name)
952                else:
953                    if self.templates:
954                        if not self.name in self.templates:
955                            error(self.pos, "'%s' is not a type identifier" % self.name)
956                        type = PyrexTypes.TemplatePlaceholderType(self.name)
957                    else:
958                        error(self.pos, "'%s' is not a type identifier" % self.name)
959        if self.complex:
960            if not type.is_numeric or type.is_complex:
961                error(self.pos, "can only complexify c numeric types")
962            type = PyrexTypes.CComplexType(type)
963            type.create_declaration_utility_code(env)
964        elif type is Builtin.complex_type:
965            # Special case: optimise builtin complex type into C's
966            # double complex.  The parser cannot do this (as for the
967            # normal scalar types) as the user may have redeclared the
968            # 'complex' type.  Testing for the exact type here works.
969            type = PyrexTypes.c_double_complex_type
970            type.create_declaration_utility_code(env)
971            self.complex = True
972        if type:
973            return type
974        else:
975            return PyrexTypes.error_type
976
977class MemoryViewSliceTypeNode(CBaseTypeNode):
978
979    name = 'memoryview'
980    child_attrs = ['base_type_node', 'axes']
981
982    def analyse(self, env, could_be_name = False):
983
984        base_type = self.base_type_node.analyse(env)
985        if base_type.is_error: return base_type
986
987        import MemoryView
988
989        try:
990            axes_specs = MemoryView.get_axes_specs(env, self.axes)
991        except CompileError, e:
992            error(e.position, e.message_only)
993            self.type = PyrexTypes.ErrorType()
994            return self.type
995
996        if not MemoryView.validate_axes(self.pos, axes_specs):
997            self.type = error_type
998        else:
999            MemoryView.validate_memslice_dtype(self.pos, base_type)
1000            self.type = PyrexTypes.MemoryViewSliceType(base_type, axes_specs)
1001            self.use_memview_utilities(env)
1002
1003        return self.type
1004
1005    def use_memview_utilities(self, env):
1006        import MemoryView
1007        env.use_utility_code(MemoryView.view_utility_code)
1008
1009
1010class CNestedBaseTypeNode(CBaseTypeNode):
1011    # For C++ classes that live inside other C++ classes.
1012
1013    # name             string
1014    # base_type        CBaseTypeNode
1015
1016    child_attrs = ['base_type']
1017
1018    def analyse(self, env, could_be_name = None):
1019        base_type = self.base_type.analyse(env)
1020        if base_type is PyrexTypes.error_type:
1021            return PyrexTypes.error_type
1022        if not base_type.is_cpp_class:
1023            error(self.pos, "'%s' is not a valid type scope" % base_type)
1024            return PyrexTypes.error_type
1025        type_entry = base_type.scope.lookup_here(self.name)
1026        if not type_entry or not type_entry.is_type:
1027            error(self.pos, "'%s.%s' is not a type identifier" % (base_type, self.name))
1028            return PyrexTypes.error_type
1029        return type_entry.type
1030
1031
1032class TemplatedTypeNode(CBaseTypeNode):
1033    #  After parsing:
1034    #  positional_args  [ExprNode]        List of positional arguments
1035    #  keyword_args     DictNode          Keyword arguments
1036    #  base_type_node   CBaseTypeNode
1037
1038    #  After analysis:
1039    #  type             PyrexTypes.BufferType or PyrexTypes.CppClassType  ...containing the right options
1040
1041    child_attrs = ["base_type_node", "positional_args",
1042                   "keyword_args", "dtype_node"]
1043
1044    dtype_node = None
1045
1046    name = None
1047
1048    def analyse(self, env, could_be_name = False, base_type = None):
1049        if base_type is None:
1050            base_type = self.base_type_node.analyse(env)
1051        if base_type.is_error: return base_type
1052
1053        if base_type.is_cpp_class:
1054            # Templated class
1055            if self.keyword_args and self.keyword_args.key_value_pairs:
1056                error(self.pos, "c++ templates cannot take keyword arguments")
1057                self.type = PyrexTypes.error_type
1058            else:
1059                template_types = []
1060                for template_node in self.positional_args:
1061                    type = template_node.analyse_as_type(env)
1062                    if type is None:
1063                        error(template_node.pos, "unknown type in template argument")
1064                        return error_type
1065                    template_types.append(type)
1066                self.type = base_type.specialize_here(self.pos, template_types)
1067
1068        elif base_type.is_pyobject:
1069            # Buffer
1070            import Buffer
1071
1072            options = Buffer.analyse_buffer_options(
1073                self.pos,
1074                env,
1075                self.positional_args,
1076                self.keyword_args,
1077                base_type.buffer_defaults)
1078
1079            if sys.version_info[0] < 3:
1080                # Py 2.x enforces byte strings as keyword arguments ...
1081                options = dict([ (name.encode('ASCII'), value)
1082                                 for name, value in options.items() ])
1083
1084            self.type = PyrexTypes.BufferType(base_type, **options)
1085
1086        else:
1087            # Array
1088            empty_declarator = CNameDeclaratorNode(self.pos, name="", cname=None)
1089            if len(self.positional_args) > 1 or self.keyword_args.key_value_pairs:
1090                error(self.pos, "invalid array declaration")
1091                self.type = PyrexTypes.error_type
1092            else:
1093                # It would be nice to merge this class with CArrayDeclaratorNode,
1094                # but arrays are part of the declaration, not the type...
1095                if not self.positional_args:
1096                    dimension = None
1097                else:
1098                    dimension = self.positional_args[0]
1099                self.array_declarator = CArrayDeclaratorNode(self.pos,
1100                    base = empty_declarator,
1101                    dimension = dimension)
1102                self.type = self.array_declarator.analyse(base_type, env)[1]
1103
1104        if self.type.is_fused and env.fused_to_specific:
1105            self.type = self.type.specialize(env.fused_to_specific)
1106
1107        return self.type
1108
1109class CComplexBaseTypeNode(CBaseTypeNode):
1110    # base_type   CBaseTypeNode
1111    # declarator  CDeclaratorNode
1112
1113    child_attrs = ["base_type", "declarator"]
1114
1115    def analyse(self, env, could_be_name = False):
1116        base = self.base_type.analyse(env, could_be_name)
1117        _, type = self.declarator.analyse(base, env)
1118        return type
1119
1120
1121class FusedTypeNode(CBaseTypeNode):
1122    """
1123    Represents a fused type in a ctypedef statement:
1124
1125        ctypedef cython.fused_type(int, long, long long) integral
1126
1127    name            str                     name of this fused type
1128    types           [CSimpleBaseTypeNode]   is the list of types to be fused
1129    """
1130
1131    child_attrs = []
1132
1133    def analyse_declarations(self, env):
1134        type = self.analyse(env)
1135        entry = env.declare_typedef(self.name, type, self.pos)
1136
1137        # Omit the typedef declaration that self.declarator would produce
1138        entry.in_cinclude = True
1139
1140    def analyse(self, env):
1141        types = []
1142        for type_node in self.types:
1143            type = type_node.analyse_as_type(env)
1144
1145            if not type:
1146                error(type_node.pos, "Not a type")
1147                continue
1148
1149            if type in types:
1150                error(type_node.pos, "Type specified multiple times")
1151            elif type.is_fused:
1152                error(type_node.pos, "Cannot fuse a fused type")
1153            else:
1154                types.append(type)
1155
1156        # if len(self.types) == 1:
1157        #     return types[0]
1158
1159        return PyrexTypes.FusedType(types, name=self.name)
1160
1161
1162class CConstTypeNode(CBaseTypeNode):
1163    # base_type     CBaseTypeNode
1164
1165    child_attrs = ["base_type"]
1166
1167    def analyse(self, env, could_be_name = False):
1168        base = self.base_type.analyse(env, could_be_name)
1169        if base.is_pyobject:
1170            error(self.pos,
1171                  "Const base type cannot be a Python object")
1172        return PyrexTypes.c_const_type(base)
1173
1174
1175class CVarDefNode(StatNode):
1176    #  C variable definition or forward/extern function declaration.
1177    #
1178    #  visibility    'private' or 'public' or 'extern'
1179    #  base_type     CBaseTypeNode
1180    #  declarators   [CDeclaratorNode]
1181    #  in_pxd        boolean
1182    #  api           boolean
1183    #  overridable   boolean        whether it is a cpdef
1184    #  modifiers     ['inline']
1185
1186    #  decorators    [cython.locals(...)] or None
1187    #  directive_locals { string : NameNode } locals defined by cython.locals(...)
1188
1189    child_attrs = ["base_type", "declarators"]
1190
1191    decorators = None
1192    directive_locals = None
1193
1194    def analyse_declarations(self, env, dest_scope = None):
1195        if self.directive_locals is None:
1196            self.directive_locals = {}
1197        if not dest_scope:
1198            dest_scope = env
1199        self.dest_scope = dest_scope
1200
1201        if self.declarators:
1202            templates = self.declarators[0].analyse_templates()
1203        else:
1204            templates = None
1205        if templates is not None:
1206            if self.visibility != 'extern':
1207                error(self.pos, "Only extern functions allowed")
1208            if len(self.declarators) > 1:
1209                error(self.declarators[1].pos, "Can't multiply declare template types")
1210            env = TemplateScope('func_template', env)
1211            env.directives = env.outer_scope.directives
1212            for template_param in templates:
1213                env.declare_type(template_param.name, template_param, self.pos)
1214
1215        base_type = self.base_type.analyse(env)
1216
1217        if base_type.is_fused and not self.in_pxd and (env.is_c_class_scope or
1218                                                       env.is_module_scope):
1219            error(self.pos, "Fused types not allowed here")
1220            return error_type
1221
1222        self.entry = None
1223        visibility = self.visibility
1224
1225        for declarator in self.declarators:
1226
1227            if (len(self.declarators) > 1
1228                and not isinstance(declarator, CNameDeclaratorNode)
1229                and env.directives['warn.multiple_declarators']):
1230                warning(declarator.pos,
1231                    "Non-trivial type declarators in shared declaration (e.g. mix of pointers and values). " +
1232                    "Each pointer declaration should be on its own line.", 1)
1233
1234            if isinstance(declarator, CFuncDeclaratorNode):
1235                name_declarator, type = declarator.analyse(base_type, env, directive_locals=self.directive_locals)
1236            else:
1237                name_declarator, type = declarator.analyse(base_type, env)
1238            if not type.is_complete():
1239                if not (self.visibility == 'extern' and type.is_array or type.is_memoryviewslice):
1240                    error(declarator.pos,
1241                        "Variable type '%s' is incomplete" % type)
1242            if self.visibility == 'extern' and type.is_pyobject:
1243                error(declarator.pos,
1244                    "Python object cannot be declared extern")
1245            name = name_declarator.name
1246            cname = name_declarator.cname
1247            if name == '':
1248                error(declarator.pos, "Missing name in declaration.")
1249                return
1250            if type.is_cfunction:
1251                self.entry = dest_scope.declare_cfunction(name, type, declarator.pos,
1252                    cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
1253                    api = self.api, modifiers = self.modifiers)
1254                if self.entry is not None:
1255                    self.entry.is_overridable = self.overridable
1256                    self.entry.directive_locals = copy.copy(self.directive_locals)
1257            else:
1258                if self.directive_locals:
1259                    error(self.pos, "Decorators can only be followed by functions")
1260                self.entry = dest_scope.declare_var(name, type, declarator.pos,
1261                            cname=cname, visibility=visibility, in_pxd=self.in_pxd,
1262                            api=self.api, is_cdef=1)
1263                if Options.docstrings:
1264                    self.entry.doc = embed_position(self.pos, self.doc)
1265
1266
1267class CStructOrUnionDefNode(StatNode):
1268    #  name          string
1269    #  cname         string or None
1270    #  kind          "struct" or "union"
1271    #  typedef_flag  boolean
1272    #  visibility    "public" or "private"
1273    #  api           boolean
1274    #  in_pxd        boolean
1275    #  attributes    [CVarDefNode] or None
1276    #  entry         Entry
1277    #  packed        boolean
1278
1279    child_attrs = ["attributes"]
1280
1281    def declare(self, env, scope=None):
1282        if self.visibility == 'extern' and self.packed and not scope:
1283            error(self.pos, "Cannot declare extern struct as 'packed'")
1284        self.entry = env.declare_struct_or_union(
1285            self.name, self.kind, scope, self.typedef_flag, self.pos,
1286            self.cname, visibility = self.visibility, api = self.api,
1287            packed = self.packed)
1288
1289    def analyse_declarations(self, env):
1290        scope = None
1291        if self.attributes is not None:
1292            scope = StructOrUnionScope(self.name)
1293        self.declare(env, scope)
1294        if self.attributes is not None:
1295            if self.in_pxd and not env.in_cinclude:
1296                self.entry.defined_in_pxd = 1
1297            for attr in self.attributes:
1298                attr.analyse_declarations(env, scope)
1299            if self.visibility != 'extern':
1300                for attr in scope.var_entries:
1301                    type = attr.type
1302                    while type.is_array:
1303                        type = type.base_type
1304                    if type == self.entry.type:
1305                        error(attr.pos, "Struct cannot contain itself as a member.")
1306
1307    def analyse_expressions(self, env):
1308        return self
1309
1310    def generate_execution_code(self, code):
1311        pass
1312
1313
1314class CppClassNode(CStructOrUnionDefNode, BlockNode):
1315
1316    #  name          string
1317    #  cname         string or None
1318    #  visibility    "extern"
1319    #  in_pxd        boolean
1320    #  attributes    [CVarDefNode] or None
1321    #  entry         Entry
1322    #  base_classes  [CBaseTypeNode]
1323    #  templates     [string] or None
1324
1325    def declare(self, env):
1326        if self.templates is None:
1327            template_types = None
1328        else:
1329            template_types = [PyrexTypes.TemplatePlaceholderType(template_name) for template_name in self.templates]
1330        self.entry = env.declare_cpp_class(
1331            self.name, None, self.pos,
1332            self.cname, base_classes = [], visibility = self.visibility, templates = template_types)
1333
1334    def analyse_declarations(self, env):
1335        scope = None
1336        if self.attributes is not None:
1337            scope = CppClassScope(self.name, env, templates = self.templates)
1338        def base_ok(base_class):
1339            if base_class.is_cpp_class or base_class.is_struct:
1340                return True
1341            else:
1342                error(self.pos, "Base class '%s' not a struct or class." % base_class)
1343        base_class_types = filter(base_ok, [b.analyse(scope or env) for b in self.base_classes])
1344        if self.templates is None:
1345            template_types = None
1346        else:
1347            template_types = [PyrexTypes.TemplatePlaceholderType(template_name) for template_name in self.templates]
1348        self.entry = env.declare_cpp_class(
1349            self.name, scope, self.pos,
1350            self.cname, base_class_types, visibility = self.visibility, templates = template_types)
1351        if self.entry is None:
1352            return
1353        self.entry.is_cpp_class = 1
1354        if scope is not None:
1355            scope.type = self.entry.type
1356        defined_funcs = []
1357        if self.attributes is not None:
1358            if self.in_pxd and not env.in_cinclude:
1359                self.entry.defined_in_pxd = 1
1360            for attr in self.attributes:
1361                attr.analyse_declarations(scope)
1362                if isinstance(attr, CFuncDefNode):
1363                    defined_funcs.append(attr)
1364                    if self.templates is not None:
1365                        attr.template_declaration = "template <typename %s>" % ", typename ".join(self.templates)
1366        self.body = StatListNode(self.pos, stats=defined_funcs)
1367        self.scope = scope
1368
1369    def analyse_expressions(self, env):
1370        self.body = self.body.analyse_expressions(self.entry.type.scope)
1371        return self
1372
1373    def generate_function_definitions(self, env, code):
1374        self.body.generate_function_definitions(self.entry.type.scope, code)
1375
1376    def generate_execution_code(self, code):
1377        self.body.generate_execution_code(code)
1378
1379    def annotate(self, code):
1380        self.body.annotate(code)
1381
1382
1383class CEnumDefNode(StatNode):
1384    #  name           string or None
1385    #  cname          string or None
1386    #  items          [CEnumDefItemNode]
1387    #  typedef_flag   boolean
1388    #  visibility     "public" or "private"
1389    #  api            boolean
1390    #  in_pxd         boolean
1391    #  entry          Entry
1392
1393    child_attrs = ["items"]
1394
1395    def declare(self, env):
1396         self.entry = env.declare_enum(self.name, self.pos,
1397             cname = self.cname, typedef_flag = self.typedef_flag,
1398             visibility = self.visibility, api = self.api)
1399
1400    def analyse_declarations(self, env):
1401        if self.items is not None:
1402            if self.in_pxd and not env.in_cinclude:
1403                self.entry.defined_in_pxd = 1
1404            for item in self.items:
1405                item.analyse_declarations(env, self.entry)
1406
1407    def analyse_expressions(self, env):
1408        return self
1409
1410    def generate_execution_code(self, code):
1411        if self.visibility == 'public' or self.api:
1412            temp = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
1413            for item in self.entry.enum_values:
1414                code.putln("%s = PyInt_FromLong(%s); %s" % (
1415                        temp,
1416                        item.cname,
1417                        code.error_goto_if_null(temp, item.pos)))
1418                code.put_gotref(temp)
1419                code.putln('if (PyDict_SetItemString(%s, "%s", %s) < 0) %s' % (
1420                        Naming.moddict_cname,
1421                        item.name,
1422                        temp,
1423                        code.error_goto(item.pos)))
1424                code.put_decref_clear(temp, PyrexTypes.py_object_type)
1425            code.funcstate.release_temp(temp)
1426
1427
1428class CEnumDefItemNode(StatNode):
1429    #  name     string
1430    #  cname    string or None
1431    #  value    ExprNode or None
1432
1433    child_attrs = ["value"]
1434
1435    def analyse_declarations(self, env, enum_entry):
1436        if self.value:
1437            self.value = self.value.analyse_const_expression(env)
1438            if not self.value.type.is_int:
1439                self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
1440                self.value = self.value.analyse_const_expression(env)
1441        entry = env.declare_const(self.name, enum_entry.type,
1442            self.value, self.pos, cname = self.cname,
1443            visibility = enum_entry.visibility, api = enum_entry.api)
1444        enum_entry.enum_values.append(entry)
1445
1446
1447class CTypeDefNode(StatNode):
1448    #  base_type    CBaseTypeNode
1449    #  declarator   CDeclaratorNode
1450    #  visibility   "public" or "private"
1451    #  api          boolean
1452    #  in_pxd       boolean
1453
1454    child_attrs = ["base_type", "declarator"]
1455
1456    def analyse_declarations(self, env):
1457        base = self.base_type.analyse(env)
1458        name_declarator, type = self.declarator.analyse(base, env)
1459        name = name_declarator.name
1460        cname = name_declarator.cname
1461
1462        entry = env.declare_typedef(name, type, self.pos,
1463            cname = cname, visibility = self.visibility, api = self.api)
1464
1465        if type.is_fused:
1466            entry.in_cinclude = True
1467
1468        if self.in_pxd and not env.in_cinclude:
1469            entry.defined_in_pxd = 1
1470
1471    def analyse_expressions(self, env):
1472        return self
1473
1474    def generate_execution_code(self, code):
1475        pass
1476
1477
1478class FuncDefNode(StatNode, BlockNode):
1479    #  Base class for function definition nodes.
1480    #
1481    #  return_type     PyrexType
1482    #  #filename        string        C name of filename string const
1483    #  entry           Symtab.Entry
1484    #  needs_closure   boolean        Whether or not this function has inner functions/classes/yield
1485    #  needs_outer_scope boolean      Whether or not this function requires outer scope
1486    #  pymethdef_required boolean     Force Python method struct generation
1487    #  directive_locals { string : ExprNode } locals defined by cython.locals(...)
1488    #  directive_returns [ExprNode] type defined by cython.returns(...)
1489    # star_arg      PyArgDeclNode or None  * argument
1490    # starstar_arg  PyArgDeclNode or None  ** argument
1491
1492    #  has_fused_arguments  boolean
1493    #       Whether this cdef function has fused parameters. This is needed
1494    #       by AnalyseDeclarationsTransform, so it can replace CFuncDefNodes
1495    #       with fused argument types with a FusedCFuncDefNode
1496
1497    py_func = None
1498    needs_closure = False
1499    needs_outer_scope = False
1500    pymethdef_required = False
1501    is_generator = False
1502    is_generator_body = False
1503    modifiers = []
1504    has_fused_arguments = False
1505    star_arg = None
1506    starstar_arg = None
1507    is_cyfunction = False
1508
1509    def analyse_default_values(self, env):
1510        default_seen = 0
1511        for arg in self.args:
1512            if arg.default:
1513                default_seen = 1
1514                if arg.is_generic:
1515                    arg.default = arg.default.analyse_types(env)
1516                    arg.default = arg.default.coerce_to(arg.type, env)
1517                else:
1518                    error(arg.pos,
1519                        "This argument cannot have a default value")
1520                    arg.default = None
1521            elif arg.kw_only:
1522                default_seen = 1
1523            elif default_seen:
1524                error(arg.pos, "Non-default argument following default argument")
1525
1526    def align_argument_type(self, env, arg):
1527        directive_locals = self.directive_locals
1528        type = arg.type
1529        if arg.name in directive_locals:
1530            type_node = directive_locals[arg.name]
1531            other_type = type_node.analyse_as_type(env)
1532            if other_type is None:
1533                error(type_node.pos, "Not a type")
1534            elif (type is not PyrexTypes.py_object_type
1535                    and not type.same_as(other_type)):
1536                error(arg.base_type.pos, "Signature does not agree with previous declaration")
1537                error(type_node.pos, "Previous declaration here")
1538            else:
1539                arg.type = other_type
1540        return arg
1541
1542    def need_gil_acquisition(self, lenv):
1543        return 0
1544
1545    def create_local_scope(self, env):
1546        genv = env
1547        while genv.is_py_class_scope or genv.is_c_class_scope:
1548            genv = genv.outer_scope
1549        if self.needs_closure:
1550            lenv = ClosureScope(name=self.entry.name,
1551                                outer_scope = genv,
1552                                parent_scope = env,
1553                                scope_name=self.entry.cname)
1554        else:
1555            lenv = LocalScope(name=self.entry.name,
1556                              outer_scope=genv,
1557                              parent_scope=env)
1558        lenv.return_type = self.return_type
1559        type = self.entry.type
1560        if type.is_cfunction:
1561            lenv.nogil = type.nogil and not type.with_gil
1562        self.local_scope = lenv
1563        lenv.directives = env.directives
1564        return lenv
1565
1566    def generate_function_body(self, env, code):
1567        self.body.generate_execution_code(code)
1568
1569    def generate_function_definitions(self, env, code):
1570        import Buffer
1571        if self.return_type.is_memoryviewslice:
1572            import MemoryView
1573
1574        lenv = self.local_scope
1575        if lenv.is_closure_scope and not lenv.is_passthrough:
1576            outer_scope_cname = "%s->%s" % (Naming.cur_scope_cname,
1577                                            Naming.outer_scope_cname)
1578        else:
1579            outer_scope_cname = Naming.outer_scope_cname
1580        lenv.mangle_closure_cnames(outer_scope_cname)
1581        # Generate closure function definitions
1582        self.body.generate_function_definitions(lenv, code)
1583        # generate lambda function definitions
1584        self.generate_lambda_definitions(lenv, code)
1585
1586        is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
1587                             self.entry.scope.is_c_class_scope)
1588        is_releasebuffer_slot = (self.entry.name == "__releasebuffer__" and
1589                                 self.entry.scope.is_c_class_scope)
1590        is_buffer_slot = is_getbuffer_slot or is_releasebuffer_slot
1591        if is_buffer_slot:
1592            if 'cython_unused' not in self.modifiers:
1593                self.modifiers = self.modifiers + ['cython_unused']
1594
1595        preprocessor_guard = self.get_preprocessor_guard()
1596
1597        profile = code.globalstate.directives['profile']
1598        linetrace = code.globalstate.directives['linetrace']
1599        if (linetrace or profile) and lenv.nogil:
1600            warning(self.pos, "Cannot profile nogil function.", 1)
1601            profile = linetrace = False
1602        if profile or linetrace:
1603            code.globalstate.use_utility_code(
1604                UtilityCode.load_cached("Profile", "Profile.c"))
1605
1606        # Generate C code for header and body of function
1607        code.enter_cfunc_scope()
1608        code.return_from_error_cleanup_label = code.new_label()
1609
1610        # ----- Top-level constants used by this function
1611        code.mark_pos(self.pos)
1612        self.generate_cached_builtins_decls(lenv, code)
1613        # ----- Function header
1614        code.putln("")
1615
1616        if preprocessor_guard:
1617            code.putln(preprocessor_guard)
1618
1619        with_pymethdef = (self.needs_assignment_synthesis(env, code) or
1620                          self.pymethdef_required)
1621        if self.py_func:
1622            self.py_func.generate_function_header(code,
1623                with_pymethdef = with_pymethdef,
1624                proto_only=True)
1625        self.generate_function_header(code,
1626            with_pymethdef = with_pymethdef)
1627        # ----- Local variable declarations
1628        # Find function scope
1629        cenv = env
1630        while cenv.is_py_class_scope or cenv.is_c_class_scope:
1631            cenv = cenv.outer_scope
1632        if self.needs_closure:
1633            code.put(lenv.scope_class.type.declaration_code(Naming.cur_scope_cname))
1634            code.putln(";")
1635        elif self.needs_outer_scope:
1636            if lenv.is_passthrough:
1637                code.put(lenv.scope_class.type.declaration_code(Naming.cur_scope_cname))
1638                code.putln(";")
1639            code.put(cenv.scope_class.type.declaration_code(Naming.outer_scope_cname))
1640            code.putln(";")
1641        self.generate_argument_declarations(lenv, code)
1642
1643        for entry in lenv.var_entries:
1644            if not (entry.in_closure or entry.is_arg):
1645                code.put_var_declaration(entry)
1646
1647        # Initialize the return variable __pyx_r
1648        init = ""
1649        if not self.return_type.is_void:
1650            if self.return_type.is_pyobject:
1651                init = " = NULL"
1652            elif self.return_type.is_memoryviewslice:
1653                init = ' = ' + MemoryView.memslice_entry_init
1654
1655            code.putln(
1656                "%s%s;" %
1657                    (self.return_type.declaration_code(Naming.retval_cname),
1658                     init))
1659
1660        tempvardecl_code = code.insertion_point()
1661        self.generate_keyword_list(code)
1662
1663        if profile or linetrace:
1664            code.put_trace_declarations()
1665
1666        # ----- Extern library function declarations
1667        lenv.generate_library_function_declarations(code)
1668
1669        # ----- GIL acquisition
1670        acquire_gil = self.acquire_gil
1671
1672        # See if we need to acquire the GIL for variable declarations, or for
1673        # refnanny only
1674
1675        # Profiling or closures are not currently possible for cdef nogil
1676        # functions, but check them anyway
1677        have_object_args = (self.needs_closure or self.needs_outer_scope or
1678                            profile or linetrace)
1679        for arg in lenv.arg_entries:
1680            if arg.type.is_pyobject:
1681                have_object_args = True
1682                break
1683
1684        acquire_gil_for_var_decls_only = (
1685                lenv.nogil and lenv.has_with_gil_block and
1686                (have_object_args or lenv.buffer_entries))
1687
1688        acquire_gil_for_refnanny_only = (
1689                lenv.nogil and lenv.has_with_gil_block and not
1690                acquire_gil_for_var_decls_only)
1691
1692        use_refnanny = not lenv.nogil or lenv.has_with_gil_block
1693
1694        if acquire_gil or acquire_gil_for_var_decls_only:
1695            code.put_ensure_gil()
1696        elif lenv.nogil and lenv.has_with_gil_block:
1697            code.declare_gilstate()
1698
1699        # ----- set up refnanny
1700        if use_refnanny:
1701            tempvardecl_code.put_declare_refcount_context()
1702            code.put_setup_refcount_context(
1703                self.entry.name, acquire_gil=acquire_gil_for_refnanny_only)
1704
1705        # ----- Automatic lead-ins for certain special functions
1706        if is_getbuffer_slot:
1707            self.getbuffer_init(code)
1708        # ----- Create closure scope object
1709        if self.needs_closure:
1710            tp_slot = TypeSlots.ConstructorSlot("tp_new", '__new__')
1711            slot_func_cname = TypeSlots.get_slot_function(lenv.scope_class.type.scope, tp_slot)
1712            if not slot_func_cname:
1713                slot_func_cname = '%s->tp_new' % lenv.scope_class.type.typeptr_cname
1714            code.putln("%s = (%s)%s(%s, %s, NULL);" % (
1715                Naming.cur_scope_cname,
1716                lenv.scope_class.type.declaration_code(''),
1717                slot_func_cname,
1718                lenv.scope_class.type.typeptr_cname,
1719                Naming.empty_tuple))
1720            code.putln("if (unlikely(!%s)) {" % Naming.cur_scope_cname)
1721            if is_getbuffer_slot:
1722                self.getbuffer_error_cleanup(code)
1723
1724            if use_refnanny:
1725                code.put_finish_refcount_context()
1726                if acquire_gil or acquire_gil_for_var_decls_only:
1727                    code.put_release_ensured_gil()
1728
1729            # FIXME: what if the error return value is a Python value?
1730            code.putln("return %s;" % self.error_value())
1731            code.putln("}")
1732            code.put_gotref(Naming.cur_scope_cname)
1733            # Note that it is unsafe to decref the scope at this point.
1734        if self.needs_outer_scope:
1735            if self.is_cyfunction:
1736                code.putln("%s = (%s) __Pyx_CyFunction_GetClosure(%s);" % (
1737                    outer_scope_cname,
1738                    cenv.scope_class.type.declaration_code(''),
1739                    Naming.self_cname))
1740            else:
1741                code.putln("%s = (%s) %s;" % (
1742                    outer_scope_cname,
1743                    cenv.scope_class.type.declaration_code(''),
1744                    Naming.self_cname))
1745            if lenv.is_passthrough:
1746                code.putln("%s = %s;" % (Naming.cur_scope_cname, outer_scope_cname))
1747            elif self.needs_closure:
1748                # inner closures own a reference to their outer parent
1749                code.put_incref(outer_scope_cname, cenv.scope_class.type)
1750                code.put_giveref(outer_scope_cname)
1751        # ----- Trace function call
1752        if profile or linetrace:
1753            # this looks a bit late, but if we don't get here due to a
1754            # fatal error before hand, it's not really worth tracing
1755            code.put_trace_call(self.entry.name, self.pos)
1756            code.funcstate.can_trace = True
1757        # ----- Fetch arguments
1758        self.generate_argument_parsing_code(env, code)
1759        # If an argument is assigned to in the body, we must
1760        # incref it to properly keep track of refcounts.
1761        is_cdef = isinstance(self, CFuncDefNode)
1762        for entry in lenv.arg_entries:
1763            if entry.type.is_pyobject:
1764                if ((acquire_gil or len(entry.cf_assignments) > 1) and
1765                    not entry.in_closure):
1766                    code.put_var_incref(entry)
1767
1768            # Note: defaults are always incref-ed. For def functions, we
1769            #       we aquire arguments from object converstion, so we have
1770            #       new references. If we are a cdef function, we need to
1771            #       incref our arguments
1772            elif (is_cdef and entry.type.is_memoryviewslice and
1773                  len(entry.cf_assignments) > 1):
1774                code.put_incref_memoryviewslice(entry.cname,
1775                                                have_gil=not lenv.nogil)
1776        for entry in lenv.var_entries:
1777            if entry.is_arg and len(entry.cf_assignments) > 1:
1778                code.put_var_incref(entry)
1779
1780        # ----- Initialise local buffer auxiliary variables
1781        for entry in lenv.var_entries + lenv.arg_entries:
1782            if entry.type.is_buffer and entry.buffer_aux.buflocal_nd_var.used:
1783                Buffer.put_init_vars(entry, code)
1784
1785        # ----- Check and convert arguments
1786        self.generate_argument_type_tests(code)
1787        # ----- Acquire buffer arguments
1788        for entry in lenv.arg_entries:
1789            if entry.type.is_buffer:
1790                Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1791
1792        if acquire_gil_for_var_decls_only:
1793            code.put_release_ensured_gil()
1794
1795        # -------------------------
1796        # ----- Function body -----
1797        # -------------------------
1798        self.generate_function_body(env, code)
1799
1800        code.mark_pos(self.pos)
1801        code.putln("")
1802        code.putln("/* function exit code */")
1803
1804        # ----- Default return value
1805        if not self.body.is_terminator:
1806            if self.return_type.is_pyobject:
1807                #if self.return_type.is_extension_type:
1808                #    lhs = "(PyObject *)%s" % Naming.retval_cname
1809                #else:
1810                lhs = Naming.retval_cname
1811                code.put_init_to_py_none(lhs, self.return_type)
1812            else:
1813                val = self.return_type.default_value
1814                if val:
1815                    code.putln("%s = %s;" % (Naming.retval_cname, val))
1816        # ----- Error cleanup
1817        if code.error_label in code.labels_used:
1818            if not self.body.is_terminator:
1819                code.put_goto(code.return_label)
1820            code.put_label(code.error_label)
1821            for cname, type in code.funcstate.all_managed_temps():
1822                code.put_xdecref(cname, type, have_gil=not lenv.nogil)
1823
1824            # Clean up buffers -- this calls a Python function
1825            # so need to save and restore error state
1826            buffers_present = len(lenv.buffer_entries) > 0
1827            memslice_entries = [e for e in lenv.entries.itervalues()
1828                                      if e.type.is_memoryviewslice]
1829            if buffers_present:
1830                code.globalstate.use_utility_code(restore_exception_utility_code)
1831                code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1832                code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1833                for entry in lenv.buffer_entries:
1834                    Buffer.put_release_buffer_code(code, entry)
1835                    #code.putln("%s = 0;" % entry.cname)
1836                code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1837
1838            if self.return_type.is_memoryviewslice:
1839                MemoryView.put_init_entry(Naming.retval_cname, code)
1840                err_val = Naming.retval_cname
1841            else:
1842                err_val = self.error_value()
1843
1844            exc_check = self.caller_will_check_exceptions()
1845            if err_val is not None or exc_check:
1846                # TODO: Fix exception tracing (though currently unused by cProfile).
1847                # code.globalstate.use_utility_code(get_exception_tuple_utility_code)
1848                # code.put_trace_exception()
1849
1850                if lenv.nogil and not lenv.has_with_gil_block:
1851                    code.putln("{")
1852                    code.put_ensure_gil()
1853
1854                code.put_add_traceback(self.entry.qualified_name)
1855
1856                if lenv.nogil and not lenv.has_with_gil_block:
1857                    code.put_release_ensured_gil()
1858                    code.putln("}")
1859            else:
1860                warning(self.entry.pos,
1861                        "Unraisable exception in function '%s'." %
1862                        self.entry.qualified_name, 0)
1863                code.put_unraisable(self.entry.qualified_name)
1864            default_retval = self.return_type.default_value
1865            if err_val is None and default_retval:
1866                err_val = default_retval
1867            if err_val is not None:
1868                code.putln("%s = %s;" % (Naming.retval_cname, err_val))
1869
1870            if is_getbuffer_slot:
1871                self.getbuffer_error_cleanup(code)
1872
1873            # If we are using the non-error cleanup section we should
1874            # jump past it if we have an error. The if-test below determine
1875            # whether this section is used.
1876            if buffers_present or is_getbuffer_slot or self.return_type.is_memoryviewslice:
1877                code.put_goto(code.return_from_error_cleanup_label)
1878
1879        # ----- Non-error return cleanup
1880        code.put_label(code.return_label)
1881        for entry in lenv.buffer_entries:
1882            if entry.used:
1883                Buffer.put_release_buffer_code(code, entry)
1884        if is_getbuffer_slot:
1885            self.getbuffer_normal_cleanup(code)
1886
1887        if self.return_type.is_memoryviewslice:
1888            # See if our return value is uninitialized on non-error return
1889            # import MemoryView
1890            # MemoryView.err_if_nogil_initialized_check(self.pos, env)
1891            cond = code.unlikely(self.return_type.error_condition(
1892                                                    Naming.retval_cname))
1893            code.putln(
1894                'if (%s) {' % cond)
1895            if env.nogil:
1896                code.put_ensure_gil()
1897            code.putln(
1898                    'PyErr_SetString('
1899                        'PyExc_TypeError,'
1900                        '"Memoryview return value is not initialized");')
1901            if env.nogil:
1902                code.put_release_ensured_gil()
1903            code.putln(
1904                '}')
1905
1906        # ----- Return cleanup for both error and no-error return
1907        code.put_label(code.return_from_error_cleanup_label)
1908
1909        for entry in lenv.var_entries:
1910            if not entry.used or entry.in_closure:
1911                continue
1912
1913            if entry.type.is_memoryviewslice:
1914                code.put_xdecref_memoryviewslice(entry.cname,
1915                                                 have_gil=not lenv.nogil)
1916            elif entry.type.is_pyobject:
1917                if not entry.is_arg or len(entry.cf_assignments) > 1:
1918                    code.put_var_decref(entry)
1919
1920        # Decref any increfed args
1921        for entry in lenv.arg_entries:
1922            if entry.type.is_pyobject:
1923                if ((acquire_gil or len(entry.cf_assignments) > 1) and
1924                    not entry.in_closure):
1925                    code.put_var_decref(entry)
1926            elif (entry.type.is_memoryviewslice and
1927                  (not is_cdef or len(entry.cf_assignments) > 1)):
1928                # decref slices of def functions and acquired slices from cdef
1929                # functions, but not borrowed slices from cdef functions.
1930                code.put_xdecref_memoryviewslice(entry.cname,
1931                                                 have_gil=not lenv.nogil)
1932        if self.needs_closure:
1933            code.put_decref(Naming.cur_scope_cname, lenv.scope_class.type)
1934
1935        # ----- Return
1936        # This code is duplicated in ModuleNode.generate_module_init_func
1937        if not lenv.nogil:
1938            default_retval = self.return_type.default_value
1939            err_val = self.error_value()
1940            if err_val is None and default_retval:
1941                err_val = default_retval  # FIXME: why is err_val not used?
1942            if self.return_type.is_pyobject:
1943                code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1944
1945        if self.entry.is_special and self.entry.name == "__hash__":
1946            # Returning -1 for __hash__ is supposed to signal an error
1947            # We do as Python instances and coerce -1 into -2.
1948            code.putln("if (unlikely(%s == -1) && !PyErr_Occurred()) %s = -2;" % (
1949                    Naming.retval_cname, Naming.retval_cname))
1950
1951        if profile or linetrace:
1952            code.funcstate.can_trace = False
1953            if self.return_type.is_pyobject:
1954                code.put_trace_return(Naming.retval_cname)
1955            else:
1956                code.put_trace_return("Py_None")
1957
1958        if not lenv.nogil:
1959            # GIL holding function
1960            code.put_finish_refcount_context()
1961
1962        if acquire_gil or (lenv.nogil and lenv.has_with_gil_block):
1963            # release the GIL (note that with-gil blocks acquire it on exit in their EnsureGILNode)
1964            code.put_release_ensured_gil()
1965
1966        if not self.return_type.is_void:
1967            code.putln("return %s;" % Naming.retval_cname)
1968
1969        code.putln("}")
1970
1971        if preprocessor_guard:
1972            code.putln("#endif /*!(%s)*/" % preprocessor_guard)
1973
1974        # ----- Go back and insert temp variable declarations
1975        tempvardecl_code.put_temp_declarations(code.funcstate)
1976
1977        # ----- Python version
1978        code.exit_cfunc_scope()
1979        if self.py_func:
1980            self.py_func.generate_function_definitions(env, code)
1981        self.generate_wrapper_functions(code)
1982
1983    def declare_argument(self, env, arg):
1984        if arg.type.is_void:
1985            error(arg.pos, "Invalid use of 'void'")
1986        elif not arg.type.is_complete() and not (arg.type.is_array or arg.type.is_memoryviewslice):
1987            error(arg.pos,
1988                "Argument type '%s' is incomplete" % arg.type)
1989        return env.declare_arg(arg.name, arg.type, arg.pos)
1990
1991    def generate_arg_type_test(self, arg, code):
1992        # Generate type test for one argument.
1993        if arg.type.typeobj_is_available():
1994            code.globalstate.use_utility_code(
1995                UtilityCode.load_cached("ArgTypeTest", "FunctionArguments.c"))
1996            typeptr_cname = arg.type.typeptr_cname
1997            arg_code = "((PyObject *)%s)" % arg.entry.cname
1998            code.putln(
1999                'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2000                    arg_code,
2001                    typeptr_cname,
2002                    arg.accept_none,
2003                    arg.name,
2004                    arg.type.is_builtin_type,
2005                    code.error_goto(arg.pos)))
2006        else:
2007            error(arg.pos, "Cannot test type of extern C class "
2008                "without type object name specification")
2009
2010    def generate_arg_none_check(self, arg, code):
2011        # Generate None check for one argument.
2012        if arg.type.is_memoryviewslice:
2013            cname = "%s.memview" % arg.entry.cname
2014        else:
2015            cname = arg.entry.cname
2016
2017        code.putln('if (unlikely(((PyObject *)%s) == Py_None)) {' % cname)
2018        code.putln('''PyErr_Format(PyExc_TypeError, "Argument '%%.%ds' must not be None", "%s"); %s''' % (
2019            max(200, len(arg.name)), arg.name,
2020            code.error_goto(arg.pos)))
2021        code.putln('}')
2022
2023    def generate_wrapper_functions(self, code):
2024        pass
2025
2026    def generate_execution_code(self, code):
2027        # Evaluate and store argument default values
2028        for arg in self.args:
2029            if not arg.is_dynamic:
2030                arg.generate_assignment_code(code)
2031
2032    #
2033    # Special code for the __getbuffer__ function
2034    #
2035    def getbuffer_init(self, code):
2036        info = self.local_scope.arg_entries[1].cname
2037        # Python 3.0 betas have a bug in memoryview which makes it call
2038        # getbuffer with a NULL parameter. For now we work around this;
2039        # the following block should be removed when this bug is fixed.
2040        code.putln("if (%s != NULL) {" % info)
2041        code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
2042        code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
2043        code.putln("}")
2044
2045    def getbuffer_error_cleanup(self, code):
2046        info = self.local_scope.arg_entries[1].cname
2047        code.putln("if (%s != NULL && %s->obj != NULL) {"
2048                   % (info, info))
2049        code.put_gotref("%s->obj" % info)
2050        code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;"
2051                   % (info, info))
2052        code.putln("}")
2053
2054    def getbuffer_normal_cleanup(self, code):
2055        info = self.local_scope.arg_entries[1].cname
2056        code.putln("if (%s != NULL && %s->obj == Py_None) {" % (info, info))
2057        code.put_gotref("Py_None")
2058        code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
2059        code.putln("}")
2060
2061    def get_preprocessor_guard(self):
2062        if not self.entry.is_special:
2063            return None
2064        name = self.entry.name
2065        slot = TypeSlots.method_name_to_slot.get(name)
2066        if not slot:
2067            return None
2068        if name == '__long__' and not self.entry.scope.lookup_here('__int__'):
2069            return None
2070        if name in ("__getbuffer__", "__releasebuffer__") and self.entry.scope.is_c_class_scope:
2071            return None
2072        return slot.preprocessor_guard_code()
2073
2074
2075class CFuncDefNode(FuncDefNode):
2076    #  C function definition.
2077    #
2078    #  modifiers     ['inline']
2079    #  visibility    'private' or 'public' or 'extern'
2080    #  base_type     CBaseTypeNode
2081    #  declarator    CDeclaratorNode
2082    #  cfunc_declarator  the CFuncDeclarator of this function
2083    #                    (this is also available through declarator or a
2084    #                     base thereof)
2085    #  body          StatListNode
2086    #  api           boolean
2087    #  decorators    [DecoratorNode]        list of decorators
2088    #
2089    #  with_gil      boolean    Acquire GIL around body
2090    #  type          CFuncType
2091    #  py_func       wrapper for calling from Python
2092    #  overridable   whether or not this is a cpdef function
2093    #  inline_in_pxd whether this is an inline function in a pxd file
2094    #  template_declaration  String or None   Used for c++ class methods
2095    #  is_const_method whether this is a const method
2096
2097    child_attrs = ["base_type", "declarator", "body", "py_func"]
2098
2099    inline_in_pxd = False
2100    decorators = None
2101    directive_locals = None
2102    directive_returns = None
2103    override = None
2104    template_declaration = None
2105    is_const_method = False
2106
2107    def unqualified_name(self):
2108        return self.entry.name
2109
2110    def analyse_declarations(self, env):
2111        if self.directive_locals is None:
2112            self.directive_locals = {}
2113        self.directive_locals.update(env.directives['locals'])
2114        if self.directive_returns is not None:
2115            base_type = self.directive_returns.analyse_as_type(env)
2116            if base_type is None:
2117                error(self.directive_returns.pos, "Not a type")
2118                base_type = PyrexTypes.error_type
2119        else:
2120            base_type = self.base_type.analyse(env)
2121        # The 2 here is because we need both function and argument names.
2122        if isinstance(self.declarator, CFuncDeclaratorNode):
2123            name_declarator, type = self.declarator.analyse(base_type, env,
2124                                                            nonempty = 2 * (self.body is not None),
2125                                                            directive_locals = self.directive_locals)
2126        else:
2127            name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
2128        if not type.is_cfunction:
2129            error(self.pos,
2130                "Suite attached to non-function declaration")
2131        # Remember the actual type according to the function header
2132        # written here, because the type in the symbol table entry
2133        # may be different if we're overriding a C method inherited
2134        # from the base type of an extension type.
2135        self.type = type
2136        type.is_overridable = self.overridable
2137        declarator = self.declarator
2138        while not hasattr(declarator, 'args'):
2139            declarator = declarator.base
2140
2141        self.cfunc_declarator = declarator
2142        self.args = declarator.args
2143
2144        opt_arg_count = self.cfunc_declarator.optional_arg_count
2145        if (self.visibility == 'public' or self.api) and opt_arg_count:
2146            error(self.cfunc_declarator.pos,
2147                  "Function with optional arguments may not be declared "
2148                  "public or api")
2149
2150        if (type.exception_check == '+' and self.visibility != 'extern'):
2151            warning(self.cfunc_declarator.pos,
2152                    "Only extern functions can throw C++ exceptions.")
2153
2154        for formal_arg, type_arg in zip(self.args, type.args):
2155            self.align_argument_type(env, type_arg)
2156            formal_arg.type = type_arg.type
2157            formal_arg.name = type_arg.name
2158            formal_arg.cname = type_arg.cname
2159
2160            self._validate_type_visibility(type_arg.type, type_arg.pos, env)
2161
2162            if type_arg.type.is_fused:
2163                self.has_fused_arguments = True
2164
2165            if type_arg.type.is_buffer and 'inline' in self.modifiers:
2166                warning(formal_arg.pos, "Buffer unpacking not optimized away.", 1)
2167
2168            if type_arg.type.is_buffer:
2169                if self.type.nogil:
2170                    error(formal_arg.pos,
2171                          "Buffer may not be acquired without the GIL. "
2172                          "Consider using memoryview slices instead.")
2173                elif 'inline' in self.modifiers:
2174                    warning(formal_arg.pos, "Buffer unpacking not optimized away.", 1)
2175
2176        self._validate_type_visibility(type.return_type, self.pos, env)
2177
2178        name = name_declarator.name
2179        cname = name_declarator.cname
2180
2181        type.is_const_method = self.is_const_method
2182        self.entry = env.declare_cfunction(
2183            name, type, self.pos,
2184            cname = cname, visibility = self.visibility, api = self.api,
2185            defining = self.body is not None, modifiers = self.modifiers)
2186        self.entry.inline_func_in_pxd = self.inline_in_pxd
2187        self.return_type = type.return_type
2188        if self.return_type.is_array and self.visibility != 'extern':
2189            error(self.pos,
2190                "Function cannot return an array")
2191        if self.return_type.is_cpp_class:
2192            self.return_type.check_nullary_constructor(self.pos, "used as a return value")
2193
2194        if self.overridable and not env.is_module_scope:
2195            if len(self.args) < 1 or not self.args[0].type.is_pyobject:
2196                # An error will be produced in the cdef function
2197                self.overridable = False
2198
2199        self.declare_cpdef_wrapper(env)
2200        self.create_local_scope(env)
2201
2202    def declare_cpdef_wrapper(self, env):
2203        if self.overridable:
2204            name = self.entry.name
2205            py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
2206            self.py_func = DefNode(pos = self.pos,
2207                                   name = self.entry.name,
2208                                   args = self.args,
2209                                   star_arg = None,
2210                                   starstar_arg = None,
2211                                   doc = self.doc,
2212                                   body = py_func_body,
2213                                   is_wrapper = 1)
2214            self.py_func.is_module_scope = env.is_module_scope
2215            self.py_func.analyse_declarations(env)
2216            self.entry.as_variable = self.py_func.entry
2217            self.entry.used = self.entry.as_variable.used = True
2218            # Reset scope entry the above cfunction
2219            env.entries[name] = self.entry
2220            if (not self.entry.is_final_cmethod and
2221                (not env.is_module_scope or Options.lookup_module_cpdef)):
2222                self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
2223                self.body = StatListNode(self.pos, stats=[self.override, self.body])
2224
2225    def _validate_type_visibility(self, type, pos, env):
2226        """
2227        Ensure that types used in cdef functions are public or api, or
2228        defined in a C header.
2229        """
2230        public_or_api = (self.visibility == 'public' or self.api)
2231        entry = getattr(type, 'entry', None)
2232        if public_or_api and entry and env.is_module_scope:
2233            if not (entry.visibility in ('public', 'extern') or
2234                    entry.api or entry.in_cinclude):
2235                error(pos, "Function declared public or api may not have "
2236                           "private types")
2237
2238    def call_self_node(self, omit_optional_args=0, is_module_scope=0):
2239        import ExprNodes
2240        args = self.type.args
2241        if omit_optional_args:
2242            args = args[:len(args) - self.type.optional_arg_count]
2243        arg_names = [arg.name for arg in args]
2244        if is_module_scope:
2245            cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
2246        else:
2247            self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
2248            cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
2249        skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
2250        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)
2251        return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
2252
2253    def declare_arguments(self, env):
2254        for arg in self.type.args:
2255            if not arg.name:
2256                error(arg.pos, "Missing argument name")
2257            self.declare_argument(env, arg)
2258
2259    def need_gil_acquisition(self, lenv):
2260        return self.type.with_gil
2261
2262    def nogil_check(self, env):
2263        type = self.type
2264        with_gil = type.with_gil
2265        if type.nogil and not with_gil:
2266            if type.return_type.is_pyobject:
2267                error(self.pos,
2268                      "Function with Python return type cannot be declared nogil")
2269            for entry in self.local_scope.var_entries:
2270                if entry.type.is_pyobject and not entry.in_with_gil_block:
2271                    error(self.pos, "Function declared nogil has Python locals or temporaries")
2272
2273    def analyse_expressions(self, env):
2274        self.local_scope.directives = env.directives
2275        if self.py_func is not None:
2276            # this will also analyse the default values
2277            self.py_func = self.py_func.analyse_expressions(env)
2278        else:
2279            self.analyse_default_values(env)
2280        self.acquire_gil = self.need_gil_acquisition(self.local_scope)
2281        return self
2282
2283    def needs_assignment_synthesis(self, env, code=None):
2284        return False
2285
2286    def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
2287        scope = self.local_scope
2288        arg_decls = []
2289        type = self.type
2290        for arg in type.args[:len(type.args)-type.optional_arg_count]:
2291            arg_decl = arg.declaration_code()
2292            entry = scope.lookup(arg.name)
2293            if not entry.cf_used:
2294                arg_decl = 'CYTHON_UNUSED %s' % arg_decl
2295            arg_decls.append(arg_decl)
2296        if with_dispatch and self.overridable:
2297            dispatch_arg = PyrexTypes.c_int_type.declaration_code(
2298                Naming.skip_dispatch_cname)
2299            if self.override:
2300                arg_decls.append(dispatch_arg)
2301            else:
2302                arg_decls.append('CYTHON_UNUSED %s' % dispatch_arg)
2303        if type.optional_arg_count and with_opt_args:
2304            arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
2305        if type.has_varargs:
2306            arg_decls.append("...")
2307        if not arg_decls:
2308            arg_decls = ["void"]
2309        if cname is None:
2310            cname = self.entry.func_cname
2311        entity = type.function_header_code(cname, ', '.join(arg_decls))
2312        if self.entry.visibility == 'private' and '::' not in cname:
2313            storage_class = "static "
2314        else:
2315            storage_class = ""
2316        dll_linkage = None
2317        modifiers = code.build_function_modifiers(self.entry.func_modifiers)
2318
2319        header = self.return_type.declaration_code(entity, dll_linkage=dll_linkage)
2320        #print (storage_class, modifiers, header)
2321        if self.template_declaration:
2322            code.putln(self.template_declaration)
2323        code.putln("%s%s%s {" % (storage_class, modifiers, header))
2324
2325    def generate_argument_declarations(self, env, code):
2326        scope = self.local_scope
2327        for arg in self.args:
2328            if arg.default:
2329                entry = scope.lookup(arg.name)
2330                if self.override or entry.cf_used:
2331                    result = arg.calculate_default_value_code(code)
2332                    code.putln('%s = %s;' % (
2333                        arg.type.declaration_code(arg.cname), result))
2334
2335    def generate_keyword_list(self, code):
2336        pass
2337
2338    def generate_argument_parsing_code(self, env, code):
2339        i = 0
2340        used = 0
2341        if self.type.optional_arg_count:
2342            scope = self.local_scope
2343            code.putln('if (%s) {' % Naming.optional_args_cname)
2344            for arg in self.args:
2345                if arg.default:
2346                    entry = scope.lookup(arg.name)
2347                    if self.override or entry.cf_used:
2348                        code.putln('if (%s->%sn > %s) {' %
2349                                   (Naming.optional_args_cname,
2350                                    Naming.pyrex_prefix, i))
2351                        declarator = arg.declarator
2352                        while not hasattr(declarator, 'name'):
2353                            declarator = declarator.base
2354                        code.putln('%s = %s->%s;' %
2355                                   (arg.cname, Naming.optional_args_cname,
2356                                    self.type.opt_arg_cname(declarator.name)))
2357                        used += 1
2358                    i += 1
2359            for _ in range(used):
2360                code.putln('}')
2361            code.putln('}')
2362
2363    def generate_argument_conversion_code(self, code):
2364        pass
2365
2366    def generate_argument_type_tests(self, code):
2367        # Generate type tests for args whose type in a parent
2368        # class is a supertype of the declared type.
2369        for arg in self.type.args:
2370            if arg.needs_type_test:
2371                self.generate_arg_type_test(arg, code)
2372            elif arg.type.is_pyobject and not arg.accept_none:
2373                self.generate_arg_none_check(arg, code)
2374
2375    def error_value(self):
2376        if self.return_type.is_pyobject:
2377            return "0"
2378        else:
2379            #return None
2380            return self.entry.type.exception_value
2381
2382    def caller_will_check_exceptions(self):
2383        return self.entry.type.exception_check
2384
2385    def generate_wrapper_functions(self, code):
2386        # If the C signature of a function has changed, we need to generate
2387        # wrappers to put in the slots here.
2388        k = 0
2389        entry = self.entry
2390        func_type = entry.type
2391        while entry.prev_entry is not None:
2392            k += 1
2393            entry = entry.prev_entry
2394            entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
2395            code.putln()
2396            self.generate_function_header(code,
2397                                          0,
2398                                          with_dispatch = entry.type.is_overridable,
2399                                          with_opt_args = entry.type.optional_arg_count,
2400                                          cname = entry.func_cname)
2401            if not self.return_type.is_void:
2402                code.put('return ')
2403            args = self.type.args
2404            arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
2405            if entry.type.is_overridable:
2406                arglist.append(Naming.skip_dispatch_cname)
2407            elif func_type.is_overridable:
2408                arglist.append('0')
2409            if entry.type.optional_arg_count:
2410                arglist.append(Naming.optional_args_cname)
2411            elif func_type.optional_arg_count:
2412                arglist.append('NULL')
2413            code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
2414            code.putln('}')
2415
2416
2417class PyArgDeclNode(Node):
2418    # Argument which must be a Python object (used
2419    # for * and ** arguments).
2420    #
2421    # name        string
2422    # entry       Symtab.Entry
2423    # annotation  ExprNode or None   Py3 argument annotation
2424    child_attrs = []
2425    is_self_arg = False
2426    is_type_arg = False
2427
2428    def generate_function_definitions(self, env, code):
2429        self.entry.generate_function_definitions(env, code)
2430
2431class DecoratorNode(Node):
2432    # A decorator
2433    #
2434    # decorator    NameNode or CallNode or AttributeNode
2435    child_attrs = ['decorator']
2436
2437
2438class DefNode(FuncDefNode):
2439    # A Python function definition.
2440    #
2441    # name          string                 the Python name of the function
2442    # lambda_name   string                 the internal name of a lambda 'function'
2443    # decorators    [DecoratorNode]        list of decorators
2444    # args          [CArgDeclNode]         formal arguments
2445    # doc           EncodedString or None
2446    # body          StatListNode
2447    # return_type_annotation
2448    #               ExprNode or None       the Py3 return type annotation
2449    #
2450    #  The following subnode is constructed internally
2451    #  when the def statement is inside a Python class definition.
2452    #
2453    #  fused_py_func        DefNode     The original fused cpdef DefNode
2454    #                                   (in case this is a specialization)
2455    #  specialized_cpdefs   [DefNode]   list of specialized cpdef DefNodes
2456    #  py_cfunc_node  PyCFunctionNode/InnerFunctionNode   The PyCFunction to create and assign
2457    #
2458    # decorator_indirection IndirectionNode Used to remove __Pyx_Method_ClassMethod for fused functions
2459
2460    child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
2461
2462    lambda_name = None
2463    reqd_kw_flags_cname = "0"
2464    is_wrapper = 0
2465    no_assignment_synthesis = 0
2466    decorators = None
2467    return_type_annotation = None
2468    entry = None
2469    acquire_gil = 0
2470    self_in_stararg = 0
2471    py_cfunc_node = None
2472    requires_classobj = False
2473    defaults_struct = None # Dynamic kwrds structure name
2474    doc = None
2475
2476    fused_py_func = False
2477    specialized_cpdefs = None
2478    py_wrapper = None
2479    py_wrapper_required = True
2480    func_cname = None
2481
2482    defaults_getter = None
2483
2484    def __init__(self, pos, **kwds):
2485        FuncDefNode.__init__(self, pos, **kwds)
2486        k = rk = r = 0
2487        for arg in self.args:
2488            if arg.kw_only:
2489                k += 1
2490                if not arg.default:
2491                    rk += 1
2492            if not arg.default:
2493                r += 1
2494        self.num_kwonly_args = k
2495        self.num_required_kw_args = rk
2496        self.num_required_args = r
2497
2498    def as_cfunction(self, cfunc=None, scope=None, overridable=True, returns=None):
2499        if self.star_arg:
2500            error(self.star_arg.pos, "cdef function cannot have star argument")
2501        if self.starstar_arg:
2502            error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
2503        if cfunc is None:
2504            cfunc_args = []
2505            for formal_arg in self.args:
2506                name_declarator, type = formal_arg.analyse(scope, nonempty=1)
2507                cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
2508                                                          cname = None,
2509                                                          type = py_object_type,
2510                                                          pos = formal_arg.pos))
2511            cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
2512                                              args = cfunc_args,
2513                                              has_varargs = False,
2514                                              exception_value = None,
2515                                              exception_check = False,
2516                                              nogil = False,
2517                                              with_gil = False,
2518                                              is_overridable = overridable)
2519            cfunc = CVarDefNode(self.pos, type=cfunc_type)
2520        else:
2521            if scope is None:
2522                scope = cfunc.scope
2523            cfunc_type = cfunc.type
2524            if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
2525                error(self.pos, "wrong number of arguments")
2526                error(cfunc.pos, "previous declaration here")
2527            for i, (formal_arg, type_arg) in enumerate(zip(self.args, cfunc_type.args)):
2528                name_declarator, type = formal_arg.analyse(scope, nonempty=1,
2529                                                           is_self_arg = (i == 0 and scope.is_c_class_scope))
2530                if type is None or type is PyrexTypes.py_object_type:
2531                    formal_arg.type = type_arg.type
2532                    formal_arg.name_declarator = name_declarator
2533        import ExprNodes
2534        if cfunc_type.exception_value is None:
2535            exception_value = None
2536        else:
2537            exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
2538        declarator = CFuncDeclaratorNode(self.pos,
2539                                         base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
2540                                         args = self.args,
2541                                         has_varargs = False,
2542                                         exception_check = cfunc_type.exception_check,
2543                                         exception_value = exception_value,
2544                                         with_gil = cfunc_type.with_gil,
2545                                         nogil = cfunc_type.nogil)
2546        return CFuncDefNode(self.pos,
2547                            modifiers = [],
2548                            base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
2549                            declarator = declarator,
2550                            body = self.body,
2551                            doc = self.doc,
2552                            overridable = cfunc_type.is_overridable,
2553                            type = cfunc_type,
2554                            with_gil = cfunc_type.with_gil,
2555                            nogil = cfunc_type.nogil,
2556                            visibility = 'private',
2557                            api = False,
2558                            directive_locals = getattr(cfunc, 'directive_locals', {}),
2559                            directive_returns = returns)
2560
2561    def is_cdef_func_compatible(self):
2562        """Determines if the function's signature is compatible with a
2563        cdef function.  This can be used before calling
2564        .as_cfunction() to see if that will be successful.
2565        """
2566        if self.needs_closure:
2567            return False
2568        if self.star_arg or self.starstar_arg:
2569            return False
2570        return True
2571
2572    def analyse_declarations(self, env):
2573        self.is_classmethod = self.is_staticmethod = False
2574        if self.decorators:
2575            for decorator in self.decorators:
2576                func = decorator.decorator
2577                if func.is_name:
2578                    self.is_classmethod |= func.name == 'classmethod'
2579                    self.is_staticmethod |= func.name == 'staticmethod'
2580
2581        if self.is_classmethod and env.lookup_here('classmethod'):
2582            # classmethod() was overridden - not much we can do here ...
2583            self.is_classmethod = False
2584        if self.is_staticmethod and env.lookup_here('staticmethod'):
2585            # staticmethod() was overridden - not much we can do here ...
2586            self.is_staticmethod = False
2587
2588        if self.name == '__new__' and env.is_py_class_scope:
2589            self.is_staticmethod = 1
2590
2591        self.analyse_argument_types(env)
2592        if self.name == '<lambda>':
2593            self.declare_lambda_function(env)
2594        else:
2595            self.declare_pyfunction(env)
2596
2597        self.analyse_signature(env)
2598        self.return_type = self.entry.signature.return_type()
2599        self.create_local_scope(env)
2600
2601        self.py_wrapper = DefNodeWrapper(
2602            self.pos,
2603            target=self,
2604            name=self.entry.name,
2605            args=self.args,
2606            star_arg=self.star_arg,
2607            starstar_arg=self.starstar_arg,
2608            return_type=self.return_type)
2609        self.py_wrapper.analyse_declarations(env)
2610
2611    def analyse_argument_types(self, env):
2612        self.directive_locals = env.directives['locals']
2613        allow_none_for_extension_args = env.directives['allow_none_for_extension_args']
2614
2615        f2s = env.fused_to_specific
2616        env.fused_to_specific = None
2617
2618        for arg in self.args:
2619            if hasattr(arg, 'name'):
2620                name_declarator = None
2621            else:
2622                base_type = arg.base_type.analyse(env)
2623                name_declarator, type = \
2624                    arg.declarator.analyse(base_type, env)
2625                arg.name = name_declarator.name
2626                arg.type = type
2627
2628                if type.is_fused:
2629                    self.has_fused_arguments = True
2630
2631            self.align_argument_type(env, arg)
2632            if name_declarator and name_declarator.cname:
2633                error(self.pos,
2634                    "Python function argument cannot have C name specification")
2635            arg.type = arg.type.as_argument_type()
2636            arg.hdr_type = None
2637            arg.needs_conversion = 0
2638            arg.needs_type_test = 0
2639            arg.is_generic = 1
2640            if arg.type.is_pyobject or arg.type.is_buffer or arg.type.is_memoryviewslice:
2641                if arg.or_none:
2642                    arg.accept_none = True
2643                elif arg.not_none:
2644                    arg.accept_none = False
2645                elif (arg.type.is_extension_type or arg.type.is_builtin_type
2646                      or arg.type.is_buffer or arg.type.is_memoryviewslice):
2647                    if arg.default and arg.default.constant_result is None:
2648                        # special case: def func(MyType obj = None)
2649                        arg.accept_none = True
2650                    else:
2651                        # default depends on compiler directive
2652                        arg.accept_none = allow_none_for_extension_args
2653                else:
2654                    # probably just a plain 'object'
2655                    arg.accept_none = True
2656            else:
2657                arg.accept_none = True # won't be used, but must be there
2658                if arg.not_none:
2659                    error(arg.pos, "Only Python type arguments can have 'not None'")
2660                if arg.or_none:
2661                    error(arg.pos, "Only Python type arguments can have 'or None'")
2662
2663        env.fused_to_specific = f2s
2664
2665    def analyse_signature(self, env):
2666        if self.entry.is_special:
2667            if self.decorators:
2668                error(self.pos, "special functions of cdef classes cannot have decorators")
2669            self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
2670        elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
2671            # Use the simpler calling signature for zero- and one-argument functions.
2672            if self.entry.signature is TypeSlots.pyfunction_signature:
2673                if len(self.args) == 0:
2674                    self.entry.signature = TypeSlots.pyfunction_noargs
2675                elif len(self.args) == 1:
2676                    if self.args[0].default is None and not self.args[0].kw_only:
2677                        self.entry.signature = TypeSlots.pyfunction_onearg
2678            elif self.entry.signature is TypeSlots.pymethod_signature:
2679                if len(self.args) == 1:
2680                    self.entry.signature = TypeSlots.unaryfunc
2681                elif len(self.args) == 2:
2682                    if self.args[1].default is None and not self.args[1].kw_only:
2683                        self.entry.signature = TypeSlots.ibinaryfunc
2684
2685        sig = self.entry.signature
2686        nfixed = sig.num_fixed_args()
2687        if sig is TypeSlots.pymethod_signature and nfixed == 1 \
2688               and len(self.args) == 0 and self.star_arg:
2689            # this is the only case where a diverging number of
2690            # arguments is not an error - when we have no explicit
2691            # 'self' parameter as in method(*args)
2692            sig = self.entry.signature = TypeSlots.pyfunction_signature # self is not 'really' used
2693            self.self_in_stararg = 1
2694            nfixed = 0
2695
2696        if self.is_staticmethod and env.is_c_class_scope:
2697            nfixed = 0
2698            self.self_in_stararg = True  # FIXME: why for staticmethods?
2699
2700            self.entry.signature = sig = copy.copy(sig)
2701            sig.fixed_arg_format = "*"
2702            sig.is_staticmethod = True
2703            sig.has_generic_args = True
2704
2705        if ((self.is_classmethod or self.is_staticmethod) and
2706            self.has_fused_arguments and env.is_c_class_scope):
2707            del self.decorator_indirection.stats[:]
2708
2709        for i in range(min(nfixed, len(self.args))):
2710            arg = self.args[i]
2711            arg.is_generic = 0
2712            if sig.is_self_arg(i) and not self.is_staticmethod:
2713                if self.is_classmethod:
2714                    arg.is_type_arg = 1
2715                    arg.hdr_type = arg.type = Builtin.type_type
2716                else:
2717                    arg.is_self_arg = 1
2718                    arg.hdr_type = arg.type = env.parent_type
2719                arg.needs_conversion = 0
2720            else:
2721                arg.hdr_type = sig.fixed_arg_type(i)
2722                if not arg.type.same_as(arg.hdr_type):
2723                    if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
2724                        arg.needs_type_test = 1
2725                    else:
2726                        arg.needs_conversion = 1
2727            if arg.needs_conversion:
2728                arg.hdr_cname = Naming.arg_prefix + arg.name
2729            else:
2730                arg.hdr_cname = Naming.var_prefix + arg.name
2731
2732        if nfixed > len(self.args):
2733            self.bad_signature()
2734            return
2735        elif nfixed < len(self.args):
2736            if not sig.has_generic_args:
2737                self.bad_signature()
2738            for arg in self.args:
2739                if arg.is_generic and \
2740                        (arg.type.is_extension_type or arg.type.is_builtin_type):
2741                    arg.needs_type_test = 1
2742
2743    def bad_signature(self):
2744        sig = self.entry.signature
2745        expected_str = "%d" % sig.num_fixed_args()
2746        if sig.has_generic_args:
2747            expected_str += " or more"
2748        name = self.name
2749        if name.startswith("__") and name.endswith("__"):
2750            desc = "Special method"
2751        else:
2752            desc = "Method"
2753        error(self.pos,
2754            "%s %s has wrong number of arguments "
2755            "(%d declared, %s expected)" % (
2756                desc, self.name, len(self.args), expected_str))
2757
2758    def declare_pyfunction(self, env):
2759        #print "DefNode.declare_pyfunction:", self.name, "in", env ###
2760        name = self.name
2761        entry = env.lookup_here(name)
2762        if entry:
2763            if entry.is_final_cmethod and not env.parent_type.is_final_type:
2764                error(self.pos, "Only final types can have final Python (def/cpdef) methods")
2765            if (entry.type.is_cfunction and not entry.is_builtin_cmethod
2766                and not self.is_wrapper):
2767                warning(self.pos, "Overriding cdef method with def method.", 5)
2768        entry = env.declare_pyfunction(name, self.pos, allow_redefine=not self.is_wrapper)
2769        self.entry = entry
2770        prefix = env.next_id(env.scope_prefix)
2771        self.entry.pyfunc_cname = Naming.pyfunc_prefix + prefix + name
2772        if Options.docstrings:
2773            entry.doc = embed_position(self.pos, self.doc)
2774            entry.doc_cname = Naming.funcdoc_prefix + prefix + name
2775            if entry.is_special:
2776                if entry.name in TypeSlots.invisible or not entry.doc or (entry.name in '__getattr__' and env.directives['fast_getattr']):
2777                    entry.wrapperbase_cname = None
2778                else:
2779                    entry.wrapperbase_cname = Naming.wrapperbase_prefix + prefix + name
2780        else:
2781            entry.doc = None
2782
2783    def declare_lambda_function(self, env):
2784        entry = env.declare_lambda_function(self.lambda_name, self.pos)
2785        entry.doc = None
2786        self.entry = entry
2787        self.entry.pyfunc_cname = entry.cname
2788
2789    def declare_arguments(self, env):
2790        for arg in self.args:
2791            if not arg.name:
2792                error(arg.pos, "Missing argument name")
2793            if arg.needs_conversion:
2794                arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
2795                if arg.type.is_pyobject:
2796                    arg.entry.init = "0"
2797            else:
2798                arg.entry = self.declare_argument(env, arg)
2799            arg.entry.is_arg = 1
2800            arg.entry.used = 1
2801            arg.entry.is_self_arg = arg.is_self_arg
2802        self.declare_python_arg(env, self.star_arg)
2803        self.declare_python_arg(env, self.starstar_arg)
2804
2805    def declare_python_arg(self, env, arg):
2806        if arg:
2807            if env.directives['infer_types'] != False:
2808                type = PyrexTypes.unspecified_type
2809            else:
2810                type = py_object_type
2811            entry = env.declare_var(arg.name, type, arg.pos)
2812            entry.is_arg = 1
2813            entry.used = 1
2814            entry.init = "0"
2815            entry.xdecref_cleanup = 1
2816            arg.entry = entry
2817
2818    def analyse_expressions(self, env):
2819        self.local_scope.directives = env.directives
2820        self.analyse_default_values(env)
2821
2822        if not self.needs_assignment_synthesis(env) and self.decorators:
2823            for decorator in self.decorators[::-1]:
2824                decorator.decorator = decorator.decorator.analyse_expressions(env)
2825
2826        self.py_wrapper.prepare_argument_coercion(env)
2827        return self
2828
2829    def needs_assignment_synthesis(self, env, code=None):
2830        if self.is_wrapper or self.specialized_cpdefs or self.entry.is_fused_specialized:
2831            return False
2832        if self.is_staticmethod:
2833            return True
2834        if self.no_assignment_synthesis:
2835            return False
2836        # Should enable for module level as well, that will require more testing...
2837        if self.entry.is_anonymous:
2838            return True
2839        if env.is_module_scope:
2840            if code is None:
2841                return env.directives['binding']
2842            else:
2843                return code.globalstate.directives['binding']
2844        return env.is_py_class_scope or env.is_closure_scope
2845
2846    def error_value(self):
2847        return self.entry.signature.error_value
2848
2849    def caller_will_check_exceptions(self):
2850        return self.entry.signature.exception_check
2851
2852    def generate_function_definitions(self, env, code):
2853        if self.defaults_getter:
2854            self.defaults_getter.generate_function_definitions(env, code)
2855
2856        # Before closure cnames are mangled
2857        if self.py_wrapper_required:
2858            # func_cname might be modified by @cname
2859            self.py_wrapper.func_cname = self.entry.func_cname
2860            self.py_wrapper.generate_function_definitions(env, code)
2861        FuncDefNode.generate_function_definitions(self, env, code)
2862
2863    def generate_function_header(self, code, with_pymethdef, proto_only=0):
2864        if proto_only:
2865            if self.py_wrapper_required:
2866                self.py_wrapper.generate_function_header(
2867                    code, with_pymethdef, True)
2868            return
2869        arg_code_list = []
2870        if self.entry.signature.has_dummy_arg:
2871            self_arg = 'PyObject *%s' % Naming.self_cname
2872            if not self.needs_outer_scope:
2873                self_arg = 'CYTHON_UNUSED ' + self_arg
2874            arg_code_list.append(self_arg)
2875
2876        def arg_decl_code(arg):
2877            entry = arg.entry
2878            if entry.in_closure:
2879                cname = entry.original_cname
2880            else:
2881                cname = entry.cname
2882            decl = entry.type.declaration_code(cname)
2883            if not entry.cf_used:
2884                decl = 'CYTHON_UNUSED ' + decl
2885            return decl
2886
2887        for arg in self.args:
2888            arg_code_list.append(arg_decl_code(arg))
2889        if self.star_arg:
2890            arg_code_list.append(arg_decl_code(self.star_arg))
2891        if self.starstar_arg:
2892            arg_code_list.append(arg_decl_code(self.starstar_arg))
2893        arg_code = ', '.join(arg_code_list)
2894        dc = self.return_type.declaration_code(self.entry.pyfunc_cname)
2895
2896        decls_code = code.globalstate['decls']
2897        preprocessor_guard = self.get_preprocessor_guard()
2898        if preprocessor_guard:
2899            decls_code.putln(preprocessor_guard)
2900        decls_code.putln(
2901            "static %s(%s); /* proto */" % (dc, arg_code))
2902        if preprocessor_guard:
2903            decls_code.putln("#endif")
2904        code.putln("static %s(%s) {" % (dc, arg_code))
2905
2906    def generate_argument_declarations(self, env, code):
2907        pass
2908
2909    def generate_keyword_list(self, code):
2910        pass
2911
2912    def generate_argument_parsing_code(self, env, code):
2913        # Move arguments into closure if required
2914        def put_into_closure(entry):
2915            if entry.in_closure:
2916                code.putln('%s = %s;' % (entry.cname, entry.original_cname))
2917                code.put_var_incref(entry)
2918                code.put_var_giveref(entry)
2919        for arg in self.args:
2920            put_into_closure(arg.entry)
2921        for arg in self.star_arg, self.starstar_arg:
2922            if arg:
2923                put_into_closure(arg.entry)
2924
2925    def generate_argument_type_tests(self, code):
2926        pass
2927
2928
2929class DefNodeWrapper(FuncDefNode):
2930    # DefNode python wrapper code generator
2931
2932    defnode = None
2933    target = None # Target DefNode
2934
2935    def __init__(self, *args, **kwargs):
2936        FuncDefNode.__init__(self, *args, **kwargs)
2937        self.num_kwonly_args = self.target.num_kwonly_args
2938        self.num_required_kw_args = self.target.num_required_kw_args
2939        self.num_required_args = self.target.num_required_args
2940        self.self_in_stararg = self.target.self_in_stararg
2941        self.signature = None
2942
2943    def analyse_declarations(self, env):
2944        target_entry = self.target.entry
2945        name = self.name
2946        prefix = env.next_id(env.scope_prefix)
2947        target_entry.func_cname = Naming.pywrap_prefix + prefix + name
2948        target_entry.pymethdef_cname = Naming.pymethdef_prefix + prefix + name
2949
2950        self.signature = target_entry.signature
2951
2952    def prepare_argument_coercion(self, env):
2953        # This is only really required for Cython utility code at this time,
2954        # everything else can be done during code generation.  But we expand
2955        # all utility code here, simply because we cannot easily distinguish
2956        # different code types.
2957        for arg in self.args:
2958            if not arg.type.is_pyobject:
2959                if not arg.type.create_from_py_utility_code(env):
2960                    pass # will fail later
2961            elif arg.hdr_type and not arg.hdr_type.is_pyobject:
2962                if not arg.hdr_type.create_to_py_utility_code(env):
2963                    pass # will fail later
2964
2965    def signature_has_nongeneric_args(self):
2966        argcount = len(self.args)
2967        if argcount == 0 or (
2968                argcount == 1 and (self.args[0].is_self_arg or
2969                                   self.args[0].is_type_arg)):
2970            return 0
2971        return 1
2972
2973    def signature_has_generic_args(self):
2974        return self.signature.has_generic_args
2975
2976    def generate_function_body(self, code):
2977        args = []
2978        if self.signature.has_dummy_arg:
2979            args.append(Naming.self_cname)
2980        for arg in self.args:
2981            if arg.hdr_type and not (arg.type.is_memoryviewslice or
2982                                     arg.type.is_struct or
2983                                     arg.type.is_complex):
2984                args.append(arg.type.cast_code(arg.entry.cname))
2985            else:
2986                args.append(arg.entry.cname)
2987        if self.star_arg:
2988            args.append(self.star_arg.entry.cname)
2989        if self.starstar_arg:
2990            args.append(self.starstar_arg.entry.cname)
2991        args = ', '.join(args)
2992        if not self.return_type.is_void:
2993            code.put('%s = ' % Naming.retval_cname)
2994        code.putln('%s(%s);' % (
2995            self.target.entry.pyfunc_cname, args))
2996
2997    def generate_function_definitions(self, env, code):
2998        lenv = self.target.local_scope
2999        # Generate C code for header and body of function
3000        code.mark_pos(self.pos)
3001        code.putln("")
3002        code.putln("/* Python wrapper */")
3003        preprocessor_guard = self.target.get_preprocessor_guard()
3004        if preprocessor_guard:
3005            code.putln(preprocessor_guard)
3006
3007        code.enter_cfunc_scope()
3008        code.return_from_error_cleanup_label = code.new_label()
3009
3010        with_pymethdef = (self.target.needs_assignment_synthesis(env, code) or
3011                          self.target.pymethdef_required)
3012        self.generate_function_header(code, with_pymethdef)
3013        self.generate_argument_declarations(lenv, code)
3014        tempvardecl_code = code.insertion_point()
3015
3016        if self.return_type.is_pyobject:
3017            retval_init = ' = 0'
3018        else:
3019            retval_init = ''
3020        if not self.return_type.is_void:
3021            code.putln('%s%s;' % (
3022                self.return_type.declaration_code(Naming.retval_cname),
3023                retval_init))
3024        code.put_declare_refcount_context()
3025        code.put_setup_refcount_context('%s (wrapper)' % self.name)
3026
3027        self.generate_argument_parsing_code(lenv, code)
3028        self.generate_argument_type_tests(code)
3029        self.generate_function_body(code)
3030
3031        # ----- Go back and insert temp variable declarations
3032        tempvardecl_code.put_temp_declarations(code.funcstate)
3033
3034        code.mark_pos(self.pos)
3035        code.putln("")
3036        code.putln("/* function exit code */")
3037
3038        # ----- Error cleanup
3039        if code.error_label in code.labels_used:
3040            code.put_goto(code.return_label)
3041            code.put_label(code.error_label)
3042            for cname, type in code.funcstate.all_managed_temps():
3043                code.put_xdecref(cname, type)
3044            err_val = self.error_value()
3045            if err_val is not None:
3046                code.putln("%s = %s;" % (Naming.retval_cname, err_val))
3047
3048        # ----- Non-error return cleanup
3049        code.put_label(code.return_label)
3050        for entry in lenv.var_entries:
3051            if entry.is_arg and entry.type.is_pyobject:
3052                code.put_var_decref(entry)
3053
3054        code.put_finish_refcount_context()
3055        if not self.return_type.is_void:
3056            code.putln("return %s;" % Naming.retval_cname)
3057        code.putln('}')
3058        code.exit_cfunc_scope()
3059        if preprocessor_guard:
3060            code.putln("#endif /*!(%s)*/" % preprocessor_guard)
3061
3062    def generate_function_header(self, code, with_pymethdef, proto_only=0):
3063        arg_code_list = []
3064        sig = self.signature
3065
3066        if sig.has_dummy_arg or self.self_in_stararg:
3067            arg_code = "PyObject *%s" % Naming.self_cname
3068            if not sig.has_dummy_arg:
3069                arg_code = 'CYTHON_UNUSED ' + arg_code
3070            arg_code_list.append(arg_code)
3071
3072        for arg in self.args:
3073            if not arg.is_generic:
3074                if arg.is_self_arg or arg.is_type_arg:
3075                    arg_code_list.append("PyObject *%s" % arg.hdr_cname)
3076                else:
3077                    arg_code_list.append(
3078                        arg.hdr_type.declaration_code(arg.hdr_cname))
3079        entry = self.target.entry
3080        if not entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
3081            arg_code_list.append("CYTHON_UNUSED PyObject *unused")
3082        if entry.scope.is_c_class_scope and entry.name == "__ipow__":
3083            arg_code_list.append("CYTHON_UNUSED PyObject *unused")
3084        if sig.has_generic_args:
3085            arg_code_list.append(
3086                "PyObject *%s, PyObject *%s"
3087                    % (Naming.args_cname, Naming.kwds_cname))
3088        arg_code = ", ".join(arg_code_list)
3089
3090        # Prevent warning: unused function '__pyx_pw_5numpy_7ndarray_1__getbuffer__'
3091        mf = ""
3092        if (entry.name in ("__getbuffer__", "__releasebuffer__")
3093            and entry.scope.is_c_class_scope):
3094            mf = "CYTHON_UNUSED "
3095            with_pymethdef = False
3096
3097        dc = self.return_type.declaration_code(entry.func_cname)
3098        header = "static %s%s(%s)" % (mf, dc, arg_code)
3099        code.putln("%s; /*proto*/" % header)
3100
3101        if proto_only:
3102            if self.target.fused_py_func:
3103                # If we are the specialized version of the cpdef, we still
3104                # want the prototype for the "fused cpdef", in case we're
3105                # checking to see if our method was overridden in Python
3106                self.target.fused_py_func.generate_function_header(
3107                                    code, with_pymethdef, proto_only=True)
3108            return
3109
3110        if (Options.docstrings and entry.doc and
3111                not self.target.fused_py_func and
3112                not entry.scope.is_property_scope and
3113                (not entry.is_special or entry.wrapperbase_cname)):
3114            # h_code = code.globalstate['h_code']
3115            docstr = entry.doc
3116
3117            if docstr.is_unicode:
3118                docstr = docstr.utf8encode()
3119
3120            code.putln(
3121                'static char %s[] = "%s";' % (
3122                    entry.doc_cname,
3123                    split_string_literal(escape_byte_string(docstr))))
3124
3125            if entry.is_special:
3126                code.putln('#if CYTHON_COMPILING_IN_CPYTHON')
3127                code.putln(
3128                    "struct wrapperbase %s;" % entry.wrapperbase_cname)
3129                code.putln('#endif')
3130
3131        if with_pymethdef or self.target.fused_py_func:
3132            code.put(
3133                "static PyMethodDef %s = " %
3134                    entry.pymethdef_cname)
3135            code.put_pymethoddef(self.target.entry, ";", allow_skip=False)
3136        code.putln("%s {" % header)
3137
3138    def generate_argument_declarations(self, env, code):
3139        for arg in self.args:
3140            if arg.is_generic:
3141                if arg.needs_conversion:
3142                    code.putln("PyObject *%s = 0;" % arg.hdr_cname)
3143                else:
3144                    code.put_var_declaration(arg.entry)
3145        for entry in env.var_entries:
3146            if entry.is_arg:
3147                code.put_var_declaration(entry)
3148
3149    def generate_argument_parsing_code(self, env, code):
3150        # Generate fast equivalent of PyArg_ParseTuple call for
3151        # generic arguments, if any, including args/kwargs
3152        old_error_label = code.new_error_label()
3153        our_error_label = code.error_label
3154        end_label = code.new_label("argument_unpacking_done")
3155
3156        has_kwonly_args = self.num_kwonly_args > 0
3157        has_star_or_kw_args = self.star_arg is not None \
3158            or self.starstar_arg is not None or has_kwonly_args
3159
3160        for arg in self.args:
3161            if not arg.type.is_pyobject:
3162                if not arg.type.create_from_py_utility_code(env):
3163                    pass # will fail later
3164
3165        if not self.signature_has_generic_args():
3166            if has_star_or_kw_args:
3167                error(self.pos, "This method cannot have * or keyword arguments")
3168            self.generate_argument_conversion_code(code)
3169
3170        elif not self.signature_has_nongeneric_args():
3171            # func(*args) or func(**kw) or func(*args, **kw)
3172            self.generate_stararg_copy_code(code)
3173
3174        else:
3175            self.generate_tuple_and_keyword_parsing_code(self.args, end_label, code)
3176
3177        code.error_label = old_error_label
3178        if code.label_used(our_error_label):
3179            if not code.label_used(end_label):
3180                code.put_goto(end_label)
3181            code.put_label(our_error_label)
3182            if has_star_or_kw_args:
3183                self.generate_arg_decref(self.star_arg, code)
3184                if self.starstar_arg:
3185                    if self.starstar_arg.entry.xdecref_cleanup:
3186                        code.put_var_xdecref_clear(self.starstar_arg.entry)
3187                    else:
3188                        code.put_var_decref_clear(self.starstar_arg.entry)
3189            code.put_add_traceback(self.target.entry.qualified_name)
3190            code.put_finish_refcount_context()
3191            code.putln("return %s;" % self.error_value())
3192        if code.label_used(end_label):
3193            code.put_label(end_label)
3194
3195    def generate_arg_xdecref(self, arg, code):
3196        if arg:
3197            code.put_var_xdecref_clear(arg.entry)
3198
3199    def generate_arg_decref(self, arg, code):
3200        if arg:
3201            code.put_var_decref_clear(arg.entry)
3202
3203    def generate_stararg_copy_code(self, code):
3204        if not self.star_arg:
3205            code.globalstate.use_utility_code(
3206                UtilityCode.load_cached("RaiseArgTupleInvalid", "FunctionArguments.c"))
3207            code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
3208                       Naming.args_cname)
3209            code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
3210                    self.name, Naming.args_cname, self.error_value()))
3211            code.putln("}")
3212
3213        if self.starstar_arg:
3214            if self.star_arg:
3215                kwarg_check = "unlikely(%s)" % Naming.kwds_cname
3216            else:
3217                kwarg_check = "%s" % Naming.kwds_cname
3218        else:
3219            kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
3220                Naming.kwds_cname, Naming.kwds_cname)
3221        code.globalstate.use_utility_code(
3222            UtilityCode.load_cached("KeywordStringCheck", "FunctionArguments.c"))
3223        code.putln(
3224            "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
3225                kwarg_check, Naming.kwds_cname, self.name,
3226                bool(self.starstar_arg), self.error_value()))
3227
3228        if self.starstar_arg:
3229            code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
3230                    self.starstar_arg.entry.cname,
3231                    Naming.kwds_cname,
3232                    Naming.kwds_cname))
3233            code.putln("if (unlikely(!%s)) return %s;" % (
3234                    self.starstar_arg.entry.cname, self.error_value()))
3235            self.starstar_arg.entry.xdecref_cleanup = 0
3236            code.put_gotref(self.starstar_arg.entry.cname)
3237
3238        if self.self_in_stararg and not self.target.is_staticmethod:
3239            # need to create a new tuple with 'self' inserted as first item
3240            code.put("%s = PyTuple_New(PyTuple_GET_SIZE(%s)+1); if (unlikely(!%s)) " % (
3241                    self.star_arg.entry.cname,
3242                    Naming.args_cname,
3243                    self.star_arg.entry.cname))
3244            if self.starstar_arg:
3245                code.putln("{")
3246                code.put_decref_clear(self.starstar_arg.entry.cname, py_object_type)
3247                code.putln("return %s;" % self.error_value())
3248                code.putln("}")
3249            else:
3250                code.putln("return %s;" % self.error_value())
3251            code.put_gotref(self.star_arg.entry.cname)
3252            code.put_incref(Naming.self_cname, py_object_type)
3253            code.put_giveref(Naming.self_cname)
3254            code.putln("PyTuple_SET_ITEM(%s, 0, %s);" % (
3255                self.star_arg.entry.cname, Naming.self_cname))
3256            temp = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False)
3257            code.putln("for (%s=0; %s < PyTuple_GET_SIZE(%s); %s++) {" % (
3258                temp, temp, Naming.args_cname, temp))
3259            code.putln("PyObject* item = PyTuple_GET_ITEM(%s, %s);" % (
3260                Naming.args_cname, temp))
3261            code.put_incref("item", py_object_type)
3262            code.put_giveref("item")
3263            code.putln("PyTuple_SET_ITEM(%s, %s+1, item);" % (
3264                self.star_arg.entry.cname, temp))
3265            code.putln("}")
3266            code.funcstate.release_temp(temp)
3267            self.star_arg.entry.xdecref_cleanup = 0
3268        elif self.star_arg:
3269            code.put_incref(Naming.args_cname, py_object_type)
3270            code.putln("%s = %s;" % (
3271                    self.star_arg.entry.cname,
3272                    Naming.args_cname))
3273            self.star_arg.entry.xdecref_cleanup = 0
3274
3275    def generate_tuple_and_keyword_parsing_code(self, args, success_label, code):
3276        argtuple_error_label = code.new_label("argtuple_error")
3277
3278        positional_args = []
3279        required_kw_only_args = []
3280        optional_kw_only_args = []
3281        for arg in args:
3282            if arg.is_generic:
3283                if arg.default:
3284                    if not arg.is_self_arg and not arg.is_type_arg:
3285                        if arg.kw_only:
3286                            optional_kw_only_args.append(arg)
3287                        else:
3288                            positional_args.append(arg)
3289                elif arg.kw_only:
3290                    required_kw_only_args.append(arg)
3291                elif not arg.is_self_arg and not arg.is_type_arg:
3292                    positional_args.append(arg)
3293
3294        # sort required kw-only args before optional ones to avoid special
3295        # cases in the unpacking code
3296        kw_only_args = required_kw_only_args + optional_kw_only_args
3297
3298        min_positional_args = self.num_required_args - self.num_required_kw_args
3299        if len(args) > 0 and (args[0].is_self_arg or args[0].is_type_arg):
3300            min_positional_args -= 1
3301        max_positional_args = len(positional_args)
3302        has_fixed_positional_count = not self.star_arg and \
3303            min_positional_args == max_positional_args
3304        has_kw_only_args = bool(kw_only_args)
3305
3306        if self.num_required_kw_args:
3307            code.globalstate.use_utility_code(
3308                UtilityCode.load_cached("RaiseKeywordRequired", "FunctionArguments.c"))
3309
3310        if self.starstar_arg or self.star_arg:
3311            self.generate_stararg_init_code(max_positional_args, code)
3312
3313        code.putln('{')
3314        all_args = tuple(positional_args) + tuple(kw_only_args)
3315        code.putln("static PyObject **%s[] = {%s,0};" % (
3316            Naming.pykwdlist_cname,
3317            ','.join([ '&%s' % code.intern_identifier(arg.name)
3318                        for arg in all_args ])))
3319
3320        # Before being converted and assigned to the target variables,
3321        # borrowed references to all unpacked argument values are
3322        # collected into a local PyObject* array called "values",
3323        # regardless if they were taken from default arguments,
3324        # positional arguments or keyword arguments.  Note that
3325        # C-typed default arguments are handled at conversion time,
3326        # so their array value is NULL in the end if no argument
3327        # was passed for them.
3328        self.generate_argument_values_setup_code(all_args, code)
3329
3330        # --- optimised code when we receive keyword arguments
3331        code.putln("if (%s(%s)) {" % (
3332            (self.num_required_kw_args > 0) and "likely" or "unlikely",
3333            Naming.kwds_cname))
3334        self.generate_keyword_unpacking_code(
3335            min_positional_args, max_positional_args,
3336            has_fixed_positional_count, has_kw_only_args,
3337            all_args, argtuple_error_label, code)
3338
3339        # --- optimised code when we do not receive any keyword arguments
3340        if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
3341            # Python raises arg tuple related errors first, so we must
3342            # check the length here
3343            if min_positional_args == max_positional_args and not self.star_arg:
3344                compare = '!='
3345            else:
3346                compare = '<'
3347            code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
3348                    Naming.args_cname, compare, min_positional_args))
3349            code.put_goto(argtuple_error_label)
3350
3351        if self.num_required_kw_args:
3352            # pure error case: keywords required but not passed
3353            if max_positional_args > min_positional_args and not self.star_arg:
3354                code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
3355                        Naming.args_cname, max_positional_args))
3356                code.put_goto(argtuple_error_label)
3357            code.putln('} else {')
3358            for i, arg in enumerate(kw_only_args):
3359                if not arg.default:
3360                    pystring_cname = code.intern_identifier(arg.name)
3361                    # required keyword-only argument missing
3362                    code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
3363                            self.name,
3364                            pystring_cname))
3365                    code.putln(code.error_goto(self.pos))
3366                    break
3367
3368        else:
3369            # optimised tuple unpacking code
3370            code.putln('} else {')
3371            if min_positional_args == max_positional_args:
3372                # parse the exact number of positional arguments from
3373                # the args tuple
3374                for i, arg in enumerate(positional_args):
3375                    code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (i, Naming.args_cname, i))
3376            else:
3377                # parse the positional arguments from the variable length
3378                # args tuple and reject illegal argument tuple sizes
3379                code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
3380                if self.star_arg:
3381                    code.putln('default:')
3382                reversed_args = list(enumerate(positional_args))[::-1]
3383                for i, arg in reversed_args:
3384                    if i >= min_positional_args-1:
3385                        code.put('case %2d: ' % (i+1))
3386                    code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (i, Naming.args_cname, i))
3387                if min_positional_args == 0:
3388                    code.put('case  0: ')
3389                code.putln('break;')
3390                if self.star_arg:
3391                    if min_positional_args:
3392                        for i in range(min_positional_args-1, -1, -1):
3393                            code.putln('case %2d:' % i)
3394                        code.put_goto(argtuple_error_label)
3395                else:
3396                    code.put('default: ')
3397                    code.put_goto(argtuple_error_label)
3398                code.putln('}')
3399
3400        code.putln('}') # end of the conditional unpacking blocks
3401
3402        # Convert arg values to their final type and assign them.
3403        # Also inject non-Python default arguments, which do cannot
3404        # live in the values[] array.
3405        for i, arg in enumerate(all_args):
3406            self.generate_arg_assignment(arg, "values[%d]" % i, code)
3407
3408        code.putln('}') # end of the whole argument unpacking block
3409
3410        if code.label_used(argtuple_error_label):
3411            code.put_goto(success_label)
3412            code.put_label(argtuple_error_label)
3413            code.globalstate.use_utility_code(
3414                UtilityCode.load_cached("RaiseArgTupleInvalid", "FunctionArguments.c"))
3415            code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
3416                    self.name, has_fixed_positional_count,
3417                    min_positional_args, max_positional_args,
3418                    Naming.args_cname))
3419            code.putln(code.error_goto(self.pos))
3420
3421    def generate_arg_assignment(self, arg, item, code):
3422        if arg.type.is_pyobject:
3423            # Python default arguments were already stored in 'item' at the very beginning
3424            if arg.is_generic:
3425                item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
3426            entry = arg.entry
3427            code.putln("%s = %s;" % (entry.cname, item))
3428        else:
3429            func = arg.type.from_py_function
3430            if func:
3431                if arg.default:
3432                    # C-typed default arguments must be handled here
3433                    code.putln('if (%s) {' % item)
3434                rhs = "%s(%s)" % (func, item)
3435                if arg.type.is_enum:
3436                    rhs = arg.type.cast_code(rhs)
3437                code.putln("%s = %s; %s" % (
3438                    arg.entry.cname,
3439                    rhs,
3440                    code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
3441                if arg.default:
3442                    code.putln('} else {')
3443                    code.putln(
3444                        "%s = %s;" % (
3445                            arg.entry.cname,
3446                            arg.calculate_default_value_code(code)))
3447                    if arg.type.is_memoryviewslice:
3448                        code.put_incref_memoryviewslice(arg.entry.cname,
3449                                                        have_gil=True)
3450                    code.putln('}')
3451            else:
3452                error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
3453
3454    def generate_stararg_init_code(self, max_positional_args, code):
3455        if self.starstar_arg:
3456            self.starstar_arg.entry.xdecref_cleanup = 0
3457            code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
3458                    self.starstar_arg.entry.cname,
3459                    self.starstar_arg.entry.cname,
3460                    self.error_value()))
3461            code.put_gotref(self.starstar_arg.entry.cname)
3462        if self.star_arg:
3463            self.star_arg.entry.xdecref_cleanup = 0
3464            code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
3465                    Naming.args_cname,
3466                    max_positional_args))
3467            code.putln('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s));' % (
3468                    self.star_arg.entry.cname, Naming.args_cname,
3469                    max_positional_args, Naming.args_cname))
3470            code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
3471            if self.starstar_arg:
3472                code.put_decref_clear(self.starstar_arg.entry.cname, py_object_type)
3473            code.put_finish_refcount_context()
3474            code.putln('return %s;' % self.error_value())
3475            code.putln('}')
3476            code.put_gotref(self.star_arg.entry.cname)
3477            code.putln('} else {')
3478            code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
3479            code.put_incref(Naming.empty_tuple, py_object_type)
3480            code.putln('}')
3481
3482    def generate_argument_values_setup_code(self, args, code):
3483        max_args = len(args)
3484        # the 'values' array collects borrowed references to arguments
3485        # before doing any type coercion etc.
3486        code.putln("PyObject* values[%d] = {%s};" % (
3487            max_args, ','.join('0'*max_args)))
3488
3489        if self.target.defaults_struct:
3490            code.putln('%s *%s = __Pyx_CyFunction_Defaults(%s, %s);' % (
3491                self.target.defaults_struct, Naming.dynamic_args_cname,
3492                self.target.defaults_struct, Naming.self_cname))
3493
3494        # assign borrowed Python default values to the values array,
3495        # so that they can be overwritten by received arguments below
3496        for i, arg in enumerate(args):
3497            if arg.default and arg.type.is_pyobject:
3498                default_value = arg.calculate_default_value_code(code)
3499                code.putln('values[%d] = %s;' % (i, arg.type.as_pyobject(default_value)))
3500
3501    def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
3502                                        has_fixed_positional_count, has_kw_only_args,
3503                                        all_args, argtuple_error_label, code):
3504        code.putln('Py_ssize_t kw_args;')
3505        code.putln('const Py_ssize_t pos_args = PyTuple_GET_SIZE(%s);' % Naming.args_cname)
3506        # copy the values from the args tuple and check that it's not too long
3507        code.putln('switch (pos_args) {')
3508        if self.star_arg:
3509            code.putln('default:')
3510        for i in range(max_positional_args-1, -1, -1):
3511            code.put('case %2d: ' % (i+1))
3512            code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
3513                    i, Naming.args_cname, i))
3514        code.putln('case  0: break;')
3515        if not self.star_arg:
3516            code.put('default: ') # more arguments than allowed
3517            code.put_goto(argtuple_error_label)
3518        code.putln('}')
3519
3520        # The code above is very often (but not always) the same as
3521        # the optimised non-kwargs tuple unpacking code, so we keep
3522        # the code block above at the very top, before the following
3523        # 'external' PyDict_Size() call, to make it easy for the C
3524        # compiler to merge the two separate tuple unpacking
3525        # implementations into one when they turn out to be identical.
3526
3527        # If we received kwargs, fill up the positional/required
3528        # arguments with values from the kw dict
3529        code.putln('kw_args = PyDict_Size(%s);' % Naming.kwds_cname)
3530        if self.num_required_args or max_positional_args > 0:
3531            last_required_arg = -1
3532            for i, arg in enumerate(all_args):
3533                if not arg.default:
3534                    last_required_arg = i
3535            if last_required_arg < max_positional_args:
3536                last_required_arg = max_positional_args-1
3537            if max_positional_args > 0:
3538                code.putln('switch (pos_args) {')
3539            for i, arg in enumerate(all_args[:last_required_arg+1]):
3540                if max_positional_args > 0 and i <= max_positional_args:
3541                    if self.star_arg and i == max_positional_args:
3542                        code.putln('default:')
3543                    else:
3544                        code.putln('case %2d:' % i)
3545                pystring_cname = code.intern_identifier(arg.name)
3546                if arg.default:
3547                    if arg.kw_only:
3548                        # optional kw-only args are handled separately below
3549                        continue
3550                    code.putln('if (kw_args > 0) {')
3551                    # don't overwrite default argument
3552                    code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
3553                        Naming.kwds_cname, pystring_cname))
3554                    code.putln('if (value) { values[%d] = value; kw_args--; }' % i)
3555                    code.putln('}')
3556                else:
3557                    code.putln('if (likely((values[%d] = PyDict_GetItem(%s, %s)) != 0)) kw_args--;' % (
3558                        i, Naming.kwds_cname, pystring_cname))
3559                    if i < min_positional_args:
3560                        if i == 0:
3561                            # special case: we know arg 0 is missing
3562                            code.put('else ')
3563                            code.put_goto(argtuple_error_label)
3564                        else:
3565                            # print the correct number of values (args or
3566                            # kwargs) that were passed into positional
3567                            # arguments up to this point
3568                            code.putln('else {')
3569                            code.globalstate.use_utility_code(
3570                                UtilityCode.load_cached("RaiseArgTupleInvalid", "FunctionArguments.c"))
3571                            code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
3572                                    self.name, has_fixed_positional_count,
3573                                    min_positional_args, max_positional_args, i))
3574                            code.putln(code.error_goto(self.pos))
3575                            code.putln('}')
3576                    elif arg.kw_only:
3577                        code.putln('else {')
3578                        code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
3579                                self.name, pystring_cname))
3580                        code.putln(code.error_goto(self.pos))
3581                        code.putln('}')
3582            if max_positional_args > 0:
3583                code.putln('}')
3584
3585        if has_kw_only_args:
3586            # unpack optional keyword-only arguments separately because
3587            # checking for interned strings in a dict is faster than iterating
3588            self.generate_optional_kwonly_args_unpacking_code(all_args, code)
3589
3590        code.putln('if (unlikely(kw_args > 0)) {')
3591        # non-positional/-required kw args left in dict: default args,
3592        # kw-only args, **kwargs or error
3593        #
3594        # This is sort of a catch-all: except for checking required
3595        # arguments, this will always do the right thing for unpacking
3596        # keyword arguments, so that we can concentrate on optimising
3597        # common cases above.
3598        if max_positional_args == 0:
3599            pos_arg_count = "0"
3600        elif self.star_arg:
3601            code.putln("const Py_ssize_t used_pos_args = (pos_args < %d) ? pos_args : %d;" % (
3602                    max_positional_args, max_positional_args))
3603            pos_arg_count = "used_pos_args"
3604        else:
3605            pos_arg_count = "pos_args"
3606        code.globalstate.use_utility_code(
3607            UtilityCode.load_cached("ParseKeywords", "FunctionArguments.c"))
3608        code.putln(
3609            'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) %s' % (
3610                Naming.kwds_cname,
3611                Naming.pykwdlist_cname,
3612                self.starstar_arg and self.starstar_arg.entry.cname or '0',
3613                pos_arg_count,
3614                self.name,
3615                code.error_goto(self.pos)))
3616        code.putln('}')
3617
3618    def generate_optional_kwonly_args_unpacking_code(self, all_args, code):
3619        optional_args = []
3620        first_optional_arg = -1
3621        for i, arg in enumerate(all_args):
3622            if not arg.kw_only or not arg.default:
3623                continue
3624            if not optional_args:
3625                first_optional_arg = i
3626            optional_args.append(arg.name)
3627        if optional_args:
3628            if len(optional_args) > 1:
3629                # if we receive more than the named kwargs, we either have **kwargs
3630                # (in which case we must iterate anyway) or it's an error (which we
3631                # also handle during iteration) => skip this part if there are more
3632                code.putln('if (kw_args > 0 && %s(kw_args <= %d)) {' % (
3633                    not self.starstar_arg and 'likely' or '',
3634                    len(optional_args)))
3635                code.putln('Py_ssize_t index;')
3636                # not unrolling the loop here reduces the C code overhead
3637                code.putln('for (index = %d; index < %d && kw_args > 0; index++) {' % (
3638                    first_optional_arg, first_optional_arg + len(optional_args)))
3639            else:
3640                code.putln('if (kw_args == 1) {')
3641                code.putln('const Py_ssize_t index = %d;' % first_optional_arg)
3642            code.putln('PyObject* value = PyDict_GetItem(%s, *%s[index]);' % (
3643                Naming.kwds_cname, Naming.pykwdlist_cname))
3644            code.putln('if (value) { values[index] = value; kw_args--; }')
3645            if len(optional_args) > 1:
3646                code.putln('}')
3647            code.putln('}')
3648
3649    def generate_argument_conversion_code(self, code):
3650        # Generate code to convert arguments from signature type to
3651        # declared type, if needed.  Also copies signature arguments
3652        # into closure fields.
3653        for arg in self.args:
3654            if arg.needs_conversion:
3655                self.generate_arg_conversion(arg, code)
3656
3657    def generate_arg_conversion(self, arg, code):
3658        # Generate conversion code for one argument.
3659        old_type = arg.hdr_type
3660        new_type = arg.type
3661        if old_type.is_pyobject:
3662            if arg.default:
3663                code.putln("if (%s) {" % arg.hdr_cname)
3664            else:
3665                code.putln("assert(%s); {" % arg.hdr_cname)
3666            self.generate_arg_conversion_from_pyobject(arg, code)
3667            code.putln("}")
3668        elif new_type.is_pyobject:
3669            self.generate_arg_conversion_to_pyobject(arg, code)
3670        else:
3671            if new_type.assignable_from(old_type):
3672                code.putln(
3673                    "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
3674            else:
3675                error(arg.pos,
3676                    "Cannot convert 1 argument from '%s' to '%s'" %
3677                        (old_type, new_type))
3678
3679    def generate_arg_conversion_from_pyobject(self, arg, code):
3680        new_type = arg.type
3681        func = new_type.from_py_function
3682        # copied from CoerceFromPyTypeNode
3683        if func:
3684            lhs = arg.entry.cname
3685            rhs = "%s(%s)" % (func, arg.hdr_cname)
3686            if new_type.is_enum:
3687                rhs = PyrexTypes.typecast(new_type, PyrexTypes.c_long_type, rhs)
3688            code.putln("%s = %s; %s" % (
3689                lhs,
3690                rhs,
3691                code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
3692        else:
3693            error(arg.pos,
3694                "Cannot convert Python object argument to type '%s'"
3695                    % new_type)
3696
3697    def generate_arg_conversion_to_pyobject(self, arg, code):
3698        old_type = arg.hdr_type
3699        func = old_type.to_py_function
3700        if func:
3701            code.putln("%s = %s(%s); %s" % (
3702                arg.entry.cname,
3703                func,
3704                arg.hdr_cname,
3705                code.error_goto_if_null(arg.entry.cname, arg.pos)))
3706            code.put_var_gotref(arg.entry)
3707        else:
3708            error(arg.pos,
3709                "Cannot convert argument of type '%s' to Python object"
3710                    % old_type)
3711
3712    def generate_argument_type_tests(self, code):
3713        # Generate type tests for args whose signature
3714        # type is PyObject * and whose declared type is
3715        # a subtype thereof.
3716        for arg in self.args:
3717            if arg.needs_type_test:
3718                self.generate_arg_type_test(arg, code)
3719            elif not arg.accept_none and (arg.type.is_pyobject or
3720                                          arg.type.is_buffer or
3721                                          arg.type.is_memoryviewslice):
3722                self.generate_arg_none_check(arg, code)
3723
3724    def error_value(self):
3725        return self.signature.error_value
3726
3727
3728class GeneratorDefNode(DefNode):
3729    # Generator function node that creates a new generator instance when called.
3730    #
3731    # gbody          GeneratorBodyDefNode   the function implementing the generator
3732    #
3733
3734    is_generator = True
3735    needs_closure = True
3736
3737    child_attrs = DefNode.child_attrs + ["gbody"]
3738
3739    def __init__(self, **kwargs):
3740        # XXX: don't actually needs a body
3741        kwargs['body'] = StatListNode(kwargs['pos'], stats=[])
3742        super(GeneratorDefNode, self).__init__(**kwargs)
3743
3744    def analyse_declarations(self, env):
3745        super(GeneratorDefNode, self).analyse_declarations(env)
3746        self.gbody.local_scope = self.local_scope
3747        self.gbody.analyse_declarations(env)
3748
3749    def generate_function_body(self, env, code):
3750        body_cname = self.gbody.entry.func_cname
3751
3752        code.putln('{')
3753        code.putln('__pyx_GeneratorObject *gen = __Pyx_Generator_New('
3754                   '(__pyx_generator_body_t) %s, (PyObject *) %s); %s' % (
3755                       body_cname, Naming.cur_scope_cname,
3756                       code.error_goto_if_null('gen', self.pos)))
3757        code.put_decref(Naming.cur_scope_cname, py_object_type)
3758        if self.requires_classobj:
3759            classobj_cname = 'gen->classobj'
3760            code.putln('%s = __Pyx_CyFunction_GetClassObj(%s);' % (
3761                classobj_cname, Naming.self_cname))
3762            code.put_incref(classobj_cname, py_object_type)
3763            code.put_giveref(classobj_cname)
3764        code.put_finish_refcount_context()
3765        code.putln('return (PyObject *) gen;')
3766        code.putln('}')
3767
3768    def generate_function_definitions(self, env, code):
3769        env.use_utility_code(UtilityCode.load_cached("Generator", "Generator.c"))
3770
3771        self.gbody.generate_function_header(code, proto=True)
3772        super(GeneratorDefNode, self).generate_function_definitions(env, code)
3773        self.gbody.generate_function_definitions(env, code)
3774
3775
3776class GeneratorBodyDefNode(DefNode):
3777    # Main code body of a generator implemented as a DefNode.
3778    #
3779
3780    is_generator_body = True
3781
3782    def __init__(self, pos=None, name=None, body=None):
3783        super(GeneratorBodyDefNode, self).__init__(
3784            pos=pos, body=body, name=name, doc=None,
3785            args=[], star_arg=None, starstar_arg=None)
3786
3787    def declare_generator_body(self, env):
3788        prefix = env.next_id(env.scope_prefix)
3789        name = env.next_id('generator')
3790        cname = Naming.genbody_prefix + prefix + name
3791        entry = env.declare_var(None, py_object_type, self.pos,
3792                                cname=cname, visibility='private')
3793        entry.func_cname = cname
3794        entry.qualified_name = EncodedString(self.name)
3795        self.entry = entry
3796
3797    def analyse_declarations(self, env):
3798        self.analyse_argument_types(env)
3799        self.declare_generator_body(env)
3800
3801    def generate_function_header(self, code, proto=False):
3802        header = "static PyObject *%s(__pyx_GeneratorObject *%s, PyObject *%s)" % (
3803            self.entry.func_cname,
3804            Naming.generator_cname,
3805            Naming.sent_value_cname)
3806        if proto:
3807            code.putln('%s; /* proto */' % header)
3808        else:
3809            code.putln('%s /* generator body */\n{' % header)
3810
3811    def generate_function_definitions(self, env, code):
3812        lenv = self.local_scope
3813
3814        # Generate closure function definitions
3815        self.body.generate_function_definitions(lenv, code)
3816
3817        # Generate C code for header and body of function
3818        code.enter_cfunc_scope()
3819        code.return_from_error_cleanup_label = code.new_label()
3820
3821        # ----- Top-level constants used by this function
3822        code.mark_pos(self.pos)
3823        self.generate_cached_builtins_decls(lenv, code)
3824        # ----- Function header
3825        code.putln("")
3826        self.generate_function_header(code)
3827        closure_init_code = code.insertion_point()
3828        # ----- Local variables
3829        code.putln("PyObject *%s = NULL;" % Naming.retval_cname)
3830        tempvardecl_code = code.insertion_point()
3831        code.put_declare_refcount_context()
3832        code.put_setup_refcount_context(self.entry.name)
3833
3834        # ----- Resume switch point.
3835        code.funcstate.init_closure_temps(lenv.scope_class.type.scope)
3836        resume_code = code.insertion_point()
3837        first_run_label = code.new_label('first_run')
3838        code.use_label(first_run_label)
3839        code.put_label(first_run_label)
3840        code.putln('%s' %
3841                   (code.error_goto_if_null(Naming.sent_value_cname, self.pos)))
3842
3843        # ----- Function body
3844        self.generate_function_body(env, code)
3845        # ----- Closure initialization
3846        if lenv.scope_class.type.scope.entries:
3847            closure_init_code.putln('%s = %s;' % (
3848                lenv.scope_class.type.declaration_code(Naming.cur_scope_cname),
3849                lenv.scope_class.type.cast_code('%s->closure' %
3850                                                Naming.generator_cname)))
3851
3852        code.mark_pos(self.pos)
3853        code.putln("")
3854        code.putln("/* function exit code */")
3855
3856        # on normal generator termination, we do not take the exception propagation
3857        # path: no traceback info is required and not creating it is much faster
3858        if not self.body.is_terminator:
3859            code.putln('PyErr_SetNone(PyExc_StopIteration);')
3860        # ----- Error cleanup
3861        if code.error_label in code.labels_used:
3862            if not self.body.is_terminator:
3863                code.put_goto(code.return_label)
3864            code.put_label(code.error_label)
3865            for cname, type in code.funcstate.all_managed_temps():
3866                code.put_xdecref(cname, type)
3867            code.put_add_traceback(self.entry.qualified_name)
3868
3869        # ----- Non-error return cleanup
3870        code.put_label(code.return_label)
3871        code.put_xdecref(Naming.retval_cname, py_object_type)
3872        code.putln('%s->resume_label = -1;' % Naming.generator_cname)
3873        # clean up as early as possible to help breaking any reference cycles
3874        code.putln('__Pyx_Generator_clear((PyObject*)%s);' % Naming.generator_cname)
3875        code.put_finish_refcount_context()
3876        code.putln('return NULL;')
3877        code.putln("}")
3878
3879        # ----- Go back and insert temp variable declarations
3880        tempvardecl_code.put_temp_declarations(code.funcstate)
3881        # ----- Generator resume code
3882        resume_code.putln("switch (%s->resume_label) {" % (
3883                       Naming.generator_cname))
3884        resume_code.putln("case 0: goto %s;" % first_run_label)
3885
3886        for i, label in code.yield_labels:
3887            resume_code.putln("case %d: goto %s;" % (i, label))
3888        resume_code.putln("default: /* CPython raises the right error here */")
3889        resume_code.put_finish_refcount_context()
3890        resume_code.putln("return NULL;")
3891        resume_code.putln("}")
3892
3893        code.exit_cfunc_scope()
3894
3895
3896class OverrideCheckNode(StatNode):
3897    # A Node for dispatching to the def method if it
3898    # is overriden.
3899    #
3900    #  py_func
3901    #
3902    #  args
3903    #  func_temp
3904    #  body
3905
3906    child_attrs = ['body']
3907
3908    body = None
3909
3910    def analyse_expressions(self, env):
3911        self.args = env.arg_entries
3912        if self.py_func.is_module_scope:
3913            first_arg = 0
3914        else:
3915            first_arg = 1
3916        import ExprNodes
3917        self.func_node = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
3918        call_node = ExprNodes.SimpleCallNode(
3919            self.pos, function=self.func_node,
3920            args=[ ExprNodes.NameNode(self.pos, name=arg.name)
3921                   for arg in self.args[first_arg:] ])
3922        self.body = ReturnStatNode(self.pos, value=call_node)
3923        self.body = self.body.analyse_expressions(env)
3924        return self
3925
3926    def generate_execution_code(self, code):
3927        interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
3928        # Check to see if we are an extension type
3929        if self.py_func.is_module_scope:
3930            self_arg = "((PyObject *)%s)" % Naming.module_cname
3931        else:
3932            self_arg = "((PyObject *)%s)" % self.args[0].cname
3933        code.putln("/* Check if called by wrapper */")
3934        code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
3935        code.putln("/* Check if overridden in Python */")
3936        if self.py_func.is_module_scope:
3937            code.putln("else {")
3938        else:
3939            code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
3940        func_node_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
3941        self.func_node.set_cname(func_node_temp)
3942        # need to get attribute manually--scope would return cdef method
3943        code.globalstate.use_utility_code(
3944            UtilityCode.load_cached("PyObjectGetAttrStr", "ObjectHandling.c"))
3945        err = code.error_goto_if_null(func_node_temp, self.pos)
3946        code.putln("%s = __Pyx_PyObject_GetAttrStr(%s, %s); %s" % (
3947            func_node_temp, self_arg, interned_attr_cname, err))
3948        code.put_gotref(func_node_temp)
3949        is_builtin_function_or_method = "PyCFunction_Check(%s)" % func_node_temp
3950        is_overridden = "(PyCFunction_GET_FUNCTION(%s) != (PyCFunction)%s)" % (
3951            func_node_temp, self.py_func.entry.func_cname)
3952        code.putln("if (!%s || %s) {" % (is_builtin_function_or_method, is_overridden))
3953        self.body.generate_execution_code(code)
3954        code.putln("}")
3955        code.put_decref_clear(func_node_temp, PyrexTypes.py_object_type)
3956        code.funcstate.release_temp(func_node_temp)
3957        code.putln("}")
3958
3959class ClassDefNode(StatNode, BlockNode):
3960    pass
3961
3962class PyClassDefNode(ClassDefNode):
3963    #  A Python class definition.
3964    #
3965    #  name     EncodedString   Name of the class
3966    #  doc      string or None
3967    #  body     StatNode        Attribute definition code
3968    #  entry    Symtab.Entry
3969    #  scope    PyClassScope
3970    #  decorators    [DecoratorNode]        list of decorators or None
3971    #
3972    #  The following subnodes are constructed internally:
3973    #
3974    #  dict     DictNode   Class dictionary or Py3 namespace
3975    #  classobj ClassNode  Class object
3976    #  target   NameNode   Variable to assign class object to
3977
3978    child_attrs = ["body", "dict", "metaclass", "mkw", "bases", "class_result",
3979                   "target", "class_cell", "decorators"]
3980    decorators = None
3981    class_result = None
3982    is_py3_style_class = False  # Python3 style class (kwargs)
3983    metaclass = None
3984    mkw = None
3985
3986    def __init__(self, pos, name, bases, doc, body, decorators=None,
3987                 keyword_args=None, starstar_arg=None, force_py3_semantics=False):
3988        StatNode.__init__(self, pos)
3989        self.name = name
3990        self.doc = doc
3991        self.body = body
3992        self.decorators = decorators
3993        self.bases = bases
3994        import ExprNodes
3995        if self.doc and Options.docstrings:
3996            doc = embed_position(self.pos, self.doc)
3997            doc_node = ExprNodes.StringNode(pos, value=doc)
3998        else:
3999            doc_node = None
4000
4001        allow_py2_metaclass = not force_py3_semantics
4002        if keyword_args or starstar_arg:
4003            allow_py2_metaclass = False
4004            self.is_py3_style_class = True
4005            if keyword_args and not starstar_arg:
4006                for i, item in list(enumerate(keyword_args.key_value_pairs))[::-1]:
4007                    if item.key.value == 'metaclass':
4008                        if self.metaclass is not None:
4009                            error(item.pos, "keyword argument 'metaclass' passed multiple times")
4010                        # special case: we already know the metaclass,
4011                        # so we don't need to do the "build kwargs,
4012                        # find metaclass" dance at runtime
4013                        self.metaclass = item.value
4014                        del keyword_args.key_value_pairs[i]
4015            if starstar_arg:
4016                self.mkw = ExprNodes.KeywordArgsNode(
4017                    pos, keyword_args=keyword_args and keyword_args.key_value_pairs or [],
4018                    starstar_arg=starstar_arg)
4019            elif keyword_args.key_value_pairs:
4020                self.mkw = keyword_args
4021            else:
4022                assert self.metaclass is not None
4023
4024        if force_py3_semantics or self.bases or self.mkw or self.metaclass:
4025            if self.metaclass is None:
4026                if starstar_arg:
4027                    # **kwargs may contain 'metaclass' arg
4028                    mkdict = self.mkw
4029                else:
4030                    mkdict = None
4031                if (not mkdict and
4032                        self.bases.is_sequence_constructor and
4033                        not self.bases.args):
4034                    pass  # no base classes => no inherited metaclass
4035                else:
4036                    self.metaclass = ExprNodes.PyClassMetaclassNode(
4037                        pos, mkw=mkdict, bases=self.bases)
4038                needs_metaclass_calculation = False
4039            else:
4040                needs_metaclass_calculation = True
4041
4042            self.dict = ExprNodes.PyClassNamespaceNode(
4043                pos, name=name, doc=doc_node,
4044                metaclass=self.metaclass, bases=self.bases, mkw=self.mkw)
4045            self.classobj = ExprNodes.Py3ClassNode(
4046                pos, name=name,
4047                bases=self.bases, dict=self.dict, doc=doc_node,
4048                metaclass=self.metaclass, mkw=self.mkw,
4049                calculate_metaclass=needs_metaclass_calculation,
4050                allow_py2_metaclass=allow_py2_metaclass)
4051        else:
4052            # no bases, no metaclass => old style class creation
4053            self.dict = ExprNodes.DictNode(pos, key_value_pairs=[])
4054            self.classobj = ExprNodes.ClassNode(
4055                pos, name=name,
4056                bases=bases, dict=self.dict, doc=doc_node)
4057
4058        self.target = ExprNodes.NameNode(pos, name=name)
4059        self.class_cell = ExprNodes.ClassCellInjectorNode(self.pos)
4060
4061    def as_cclass(self):
4062        """
4063        Return this node as if it were declared as an extension class
4064        """
4065        if self.is_py3_style_class:
4066            error(self.classobj.pos, "Python3 style class could not be represented as C class")
4067            return
4068        bases = self.classobj.bases.args
4069        if len(bases) == 0:
4070            base_class_name = None
4071            base_class_module = None
4072        elif len(bases) == 1:
4073            base = bases[0]
4074            path = []
4075            from ExprNodes import AttributeNode, NameNode
4076            while isinstance(base, AttributeNode):
4077                path.insert(0, base.attribute)
4078                base = base.obj
4079            if isinstance(base, NameNode):
4080                path.insert(0, base.name)
4081                base_class_name = path[-1]
4082                if len(path) > 1:
4083                    base_class_module = u'.'.join(path[:-1])
4084                else:
4085                    base_class_module = None
4086            else:
4087                error(self.classobj.bases.args.pos, "Invalid base class")
4088        else:
4089            error(self.classobj.bases.args.pos, "C class may only have one base class")
4090            return None
4091
4092        return CClassDefNode(self.pos,
4093                             visibility = 'private',
4094                             module_name = None,
4095                             class_name = self.name,
4096                             base_class_module = base_class_module,
4097                             base_class_name = base_class_name,
4098                             decorators = self.decorators,
4099                             body = self.body,
4100                             in_pxd = False,
4101                             doc = self.doc)
4102
4103    def create_scope(self, env):
4104        genv = env
4105        while genv.is_py_class_scope or genv.is_c_class_scope:
4106            genv = genv.outer_scope
4107        cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
4108        return cenv
4109
4110    def analyse_declarations(self, env):
4111        class_result = self.classobj
4112        if self.decorators:
4113            from ExprNodes import SimpleCallNode
4114            for decorator in self.decorators[::-1]:
4115                class_result = SimpleCallNode(
4116                    decorator.pos,
4117                    function = decorator.decorator,
4118                    args = [class_result])
4119            self.decorators = None
4120        self.class_result = class_result
4121        self.class_result.analyse_declarations(env)
4122        self.target.analyse_target_declaration(env)
4123        cenv = self.create_scope(env)
4124        cenv.directives = env.directives
4125        cenv.class_obj_cname = self.target.entry.cname
4126        self.body.analyse_declarations(cenv)
4127
4128    def analyse_expressions(self, env):
4129        if self.bases:
4130            self.bases = self.bases.analyse_expressions(env)
4131        if self.metaclass:
4132            self.metaclass = self.metaclass.analyse_expressions(env)
4133        if self.mkw:
4134            self.mkw = self.mkw.analyse_expressions(env)
4135        self.dict = self.dict.analyse_expressions(env)
4136        self.class_result = self.class_result.analyse_expressions(env)
4137        genv = env.global_scope()
4138        cenv = self.scope
4139        self.body = self.body.analyse_expressions(cenv)
4140        self.target.analyse_target_expression(env, self.classobj)
4141        self.class_cell = self.class_cell.analyse_expressions(cenv)
4142        return self
4143
4144    def generate_function_definitions(self, env, code):
4145        self.generate_lambda_definitions(self.scope, code)
4146        self.body.generate_function_definitions(self.scope, code)
4147
4148    def generate_execution_code(self, code):
4149        code.pyclass_stack.append(self)
4150        cenv = self.scope
4151        if self.bases:
4152            self.bases.generate_evaluation_code(code)
4153        if self.mkw:
4154            self.mkw.generate_evaluation_code(code)
4155        if self.metaclass:
4156            self.metaclass.generate_evaluation_code(code)
4157        self.dict.generate_evaluation_code(code)
4158        cenv.namespace_cname = cenv.class_obj_cname = self.dict.result()
4159        self.class_cell.generate_evaluation_code(code)
4160        self.body.generate_execution_code(code)
4161        self.class_result.generate_evaluation_code(code)
4162        self.class_cell.generate_injection_code(
4163            code, self.class_result.result())
4164        self.class_cell.generate_disposal_code(code)
4165        cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
4166        self.target.generate_assignment_code(self.class_result, code)
4167        self.dict.generate_disposal_code(code)
4168        self.dict.free_temps(code)
4169        if self.metaclass:
4170            self.metaclass.generate_disposal_code(code)
4171            self.metaclass.free_temps(code)
4172        if self.mkw:
4173            self.mkw.generate_disposal_code(code)
4174            self.mkw.free_temps(code)
4175        if self.bases:
4176            self.bases.generate_disposal_code(code)
4177            self.bases.free_temps(code)
4178        code.pyclass_stack.pop()
4179
4180class CClassDefNode(ClassDefNode):
4181    #  An extension type definition.
4182    #
4183    #  visibility         'private' or 'public' or 'extern'
4184    #  typedef_flag       boolean
4185    #  api                boolean
4186    #  module_name        string or None    For import of extern type objects
4187    #  class_name         string            Unqualified name of class
4188    #  as_name            string or None    Name to declare as in this scope
4189    #  base_class_module  string or None    Module containing the base class
4190    #  base_class_name    string or None    Name of the base class
4191    #  objstruct_name     string or None    Specified C name of object struct
4192    #  typeobj_name       string or None    Specified C name of type object
4193    #  in_pxd             boolean           Is in a .pxd file
4194    #  decorators         [DecoratorNode]   list of decorators or None
4195    #  doc                string or None
4196    #  body               StatNode or None
4197    #  entry              Symtab.Entry
4198    #  base_type          PyExtensionType or None
4199    #  buffer_defaults_node DictNode or None Declares defaults for a buffer
4200    #  buffer_defaults_pos
4201
4202    child_attrs = ["body"]
4203    buffer_defaults_node = None
4204    buffer_defaults_pos = None
4205    typedef_flag = False
4206    api = False
4207    objstruct_name = None
4208    typeobj_name = None
4209    decorators = None
4210    shadow = False
4211
4212    def buffer_defaults(self, env):
4213        if not hasattr(self, '_buffer_defaults'):
4214            import Buffer
4215            if self.buffer_defaults_node:
4216                self._buffer_defaults = Buffer.analyse_buffer_options(
4217                    self.buffer_defaults_pos,
4218                    env, [], self.buffer_defaults_node,
4219                    need_complete=False)
4220            else:
4221                self._buffer_defaults = None
4222        return self._buffer_defaults
4223
4224    def declare(self, env):
4225        if self.module_name and self.visibility != 'extern':
4226            module_path = self.module_name.split(".")
4227            home_scope = env.find_imported_module(module_path, self.pos)
4228            if not home_scope:
4229                return None
4230        else:
4231            home_scope = env
4232
4233        self.entry = home_scope.declare_c_class(
4234            name = self.class_name,
4235            pos = self.pos,
4236            defining = 0,
4237            implementing = 0,
4238            module_name = self.module_name,
4239            base_type = None,
4240            objstruct_cname = self.objstruct_name,
4241            typeobj_cname = self.typeobj_name,
4242            visibility = self.visibility,
4243            typedef_flag = self.typedef_flag,
4244            api = self.api,
4245            buffer_defaults = self.buffer_defaults(env),
4246            shadow = self.shadow)
4247
4248    def analyse_declarations(self, env):
4249        #print "CClassDefNode.analyse_declarations:", self.class_name
4250        #print "...visibility =", self.visibility
4251        #print "...module_name =", self.module_name
4252
4253        if env.in_cinclude and not self.objstruct_name:
4254            error(self.pos, "Object struct name specification required for "
4255                "C class defined in 'extern from' block")
4256        if self.decorators:
4257            error(self.pos,
4258                  "Decorators not allowed on cdef classes (used on type '%s')" % self.class_name)
4259        self.base_type = None
4260        # Now that module imports are cached, we need to
4261        # import the modules for extern classes.
4262        if self.module_name:
4263            self.module = None
4264            for module in env.cimported_modules:
4265                if module.name == self.module_name:
4266                    self.module = module
4267            if self.module is None:
4268                self.module = ModuleScope(self.module_name, None, env.context)
4269                self.module.has_extern_class = 1
4270                env.add_imported_module(self.module)
4271
4272        if self.base_class_name:
4273            if self.base_class_module:
4274                base_class_scope = env.find_module(self.base_class_module, self.pos)
4275            else:
4276                base_class_scope = env
4277            if self.base_class_name == 'object':
4278                # extension classes are special and don't need to inherit from object
4279                if base_class_scope is None or base_class_scope.lookup('object') is None:
4280                    self.base_class_name = None
4281                    self.base_class_module = None
4282                    base_class_scope = None
4283            if base_class_scope:
4284                base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
4285                if base_class_entry:
4286                    if not base_class_entry.is_type:
4287                        error(self.pos, "'%s' is not a type name" % self.base_class_name)
4288                    elif not base_class_entry.type.is_extension_type and \
4289                             not (base_class_entry.type.is_builtin_type and
4290                                  base_class_entry.type.objstruct_cname):
4291                        error(self.pos, "'%s' is not an extension type" % self.base_class_name)
4292                    elif not base_class_entry.type.is_complete():
4293                        error(self.pos, "Base class '%s' of type '%s' is incomplete" % (
4294                            self.base_class_name, self.class_name))
4295                    elif base_class_entry.type.scope and base_class_entry.type.scope.directives and \
4296                             base_class_entry.type.is_final_type:
4297                        error(self.pos, "Base class '%s' of type '%s' is final" % (
4298                            self.base_class_name, self.class_name))
4299                    elif base_class_entry.type.is_builtin_type and \
4300                             base_class_entry.type.name in ('tuple', 'str', 'bytes'):
4301                        error(self.pos, "inheritance from PyVarObject types like '%s' is not currently supported"
4302                              % base_class_entry.type.name)
4303                    else:
4304                        self.base_type = base_class_entry.type
4305                if env.directives.get('freelist', 0) > 0:
4306                    warning(self.pos, "freelists cannot be used on subtypes, only the base class can manage them", 1)
4307
4308        has_body = self.body is not None
4309        if has_body and self.base_type and not self.base_type.scope:
4310            # To properly initialize inherited attributes, the base type must
4311            # be analysed before this type.
4312            self.base_type.defered_declarations.append(lambda : self.analyse_declarations(env))
4313            return
4314
4315        if self.module_name and self.visibility != 'extern':
4316            module_path = self.module_name.split(".")
4317            home_scope = env.find_imported_module(module_path, self.pos)
4318            if not home_scope:
4319                return
4320        else:
4321            home_scope = env
4322
4323        if self.visibility == 'extern':
4324            if (self.module_name == '__builtin__' and
4325                self.class_name in Builtin.builtin_types and
4326                env.qualified_name[:8] != 'cpython.'): # allow overloaded names for cimporting from cpython
4327                warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
4328
4329        self.entry = home_scope.declare_c_class(
4330            name = self.class_name,
4331            pos = self.pos,
4332            defining = has_body and self.in_pxd,
4333            implementing = has_body and not self.in_pxd,
4334            module_name = self.module_name,
4335            base_type = self.base_type,
4336            objstruct_cname = self.objstruct_name,
4337            typeobj_cname = self.typeobj_name,
4338            visibility = self.visibility,
4339            typedef_flag = self.typedef_flag,
4340            api = self.api,
4341            buffer_defaults = self.buffer_defaults(env),
4342            shadow = self.shadow)
4343
4344        if self.shadow:
4345            home_scope.lookup(self.class_name).as_variable = self.entry
4346        if home_scope is not env and self.visibility == 'extern':
4347            env.add_imported_entry(self.class_name, self.entry, self.pos)
4348        self.scope = scope = self.entry.type.scope
4349        if scope is not None:
4350            scope.directives = env.directives
4351
4352        if self.doc and Options.docstrings:
4353            scope.doc = embed_position(self.pos, self.doc)
4354
4355        if has_body:
4356            self.body.analyse_declarations(scope)
4357            if self.in_pxd:
4358                scope.defined = 1
4359            else:
4360                scope.implemented = 1
4361        env.allocate_vtable_names(self.entry)
4362
4363        for thunk in self.entry.type.defered_declarations:
4364            thunk()
4365
4366    def analyse_expressions(self, env):
4367        if self.body:
4368            scope = self.entry.type.scope
4369            self.body = self.body.analyse_expressions(scope)
4370        return self
4371
4372    def generate_function_definitions(self, env, code):
4373        if self.body:
4374            self.generate_lambda_definitions(self.scope, code)
4375            self.body.generate_function_definitions(self.scope, code)
4376
4377    def generate_execution_code(self, code):
4378        # This is needed to generate evaluation code for
4379        # default values of method arguments.
4380        if self.body:
4381            self.body.generate_execution_code(code)
4382
4383    def annotate(self, code):
4384        if self.body:
4385            self.body.annotate(code)
4386
4387
4388class PropertyNode(StatNode):
4389    #  Definition of a property in an extension type.
4390    #
4391    #  name   string
4392    #  doc    EncodedString or None    Doc string
4393    #  entry  Symtab.Entry
4394    #  body   StatListNode
4395
4396    child_attrs = ["body"]
4397
4398    def analyse_declarations(self, env):
4399        self.entry = env.declare_property(self.name, self.doc, self.pos)
4400        self.entry.scope.directives = env.directives
4401        self.body.analyse_declarations(self.entry.scope)
4402
4403    def analyse_expressions(self, env):
4404        self.body = self.body.analyse_expressions(env)
4405        return self
4406
4407    def generate_function_definitions(self, env, code):
4408        self.body.generate_function_definitions(env, code)
4409
4410    def generate_execution_code(self, code):
4411        pass
4412
4413    def annotate(self, code):
4414        self.body.annotate(code)
4415
4416
4417class GlobalNode(StatNode):
4418    # Global variable declaration.
4419    #
4420    # names    [string]
4421
4422    child_attrs = []
4423
4424    def analyse_declarations(self, env):
4425        for name in self.names:
4426            env.declare_global(name, self.pos)
4427
4428    def analyse_expressions(self, env):
4429        return self
4430
4431    def generate_execution_code(self, code):
4432        pass
4433
4434
4435class NonlocalNode(StatNode):
4436    # Nonlocal variable declaration via the 'nonlocal' keyword.
4437    #
4438    # names    [string]
4439
4440    child_attrs = []
4441
4442    def analyse_declarations(self, env):
4443        for name in self.names:
4444            env.declare_nonlocal(name, self.pos)
4445
4446    def analyse_expressions(self, env):
4447        return self
4448
4449    def generate_execution_code(self, code):
4450        pass
4451
4452
4453class ExprStatNode(StatNode):
4454    #  Expression used as a statement.
4455    #
4456    #  expr   ExprNode
4457
4458    child_attrs = ["expr"]
4459
4460    def analyse_declarations(self, env):
4461        import ExprNodes
4462        if isinstance(self.expr, ExprNodes.GeneralCallNode):
4463            func = self.expr.function.as_cython_attribute()
4464            if func == u'declare':
4465                args, kwds = self.expr.explicit_args_kwds()
4466                if len(args):
4467                    error(self.expr.pos, "Variable names must be specified.")
4468                for var, type_node in kwds.key_value_pairs:
4469                    type = type_node.analyse_as_type(env)
4470                    if type is None:
4471                        error(type_node.pos, "Unknown type")
4472                    else:
4473                        env.declare_var(var.value, type, var.pos, is_cdef = True)
4474                self.__class__ = PassStatNode
4475
4476    def analyse_expressions(self, env):
4477        self.expr.result_is_used = False # hint that .result() may safely be left empty
4478        self.expr = self.expr.analyse_expressions(env)
4479        return self
4480
4481    def nogil_check(self, env):
4482        if self.expr.type.is_pyobject and self.expr.is_temp:
4483            self.gil_error()
4484
4485    gil_message = "Discarding owned Python object"
4486
4487    def generate_execution_code(self, code):
4488        self.expr.generate_evaluation_code(code)
4489        if not self.expr.is_temp and self.expr.result():
4490            code.putln("%s;" % self.expr.result())
4491        self.expr.generate_disposal_code(code)
4492        self.expr.free_temps(code)
4493
4494    def generate_function_definitions(self, env, code):
4495        self.expr.generate_function_definitions(env, code)
4496
4497    def annotate(self, code):
4498        self.expr.annotate(code)
4499
4500
4501class AssignmentNode(StatNode):
4502    #  Abstract base class for assignment nodes.
4503    #
4504    #  The analyse_expressions and generate_execution_code
4505    #  phases of assignments are split into two sub-phases
4506    #  each, to enable all the right hand sides of a
4507    #  parallel assignment to be evaluated before assigning
4508    #  to any of the left hand sides.
4509
4510    def analyse_expressions(self, env):
4511        return self.analyse_types(env)
4512
4513#       def analyse_expressions(self, env):
4514#           self.analyse_expressions_1(env)
4515#           self.analyse_expressions_2(env)
4516
4517    def generate_execution_code(self, code):
4518        self.generate_rhs_evaluation_code(code)
4519        self.generate_assignment_code(code)
4520
4521
4522class SingleAssignmentNode(AssignmentNode):
4523    #  The simplest case:
4524    #
4525    #    a = b
4526    #
4527    #  lhs      ExprNode      Left hand side
4528    #  rhs      ExprNode      Right hand side
4529    #  first    bool          Is this guaranteed the first assignment to lhs?
4530
4531    child_attrs = ["lhs", "rhs"]
4532    first = False
4533    declaration_only = False
4534
4535    def analyse_declarations(self, env):
4536        import ExprNodes
4537
4538        # handle declarations of the form x = cython.foo()
4539        if isinstance(self.rhs, ExprNodes.CallNode):
4540            func_name = self.rhs.function.as_cython_attribute()
4541            if func_name:
4542                args, kwds = self.rhs.explicit_args_kwds()
4543
4544                if func_name in ['declare', 'typedef']:
4545                    if len(args) > 2 or kwds is not None:
4546                        error(self.rhs.pos, "Can only declare one type at a time.")
4547                        return
4548
4549                    type = args[0].analyse_as_type(env)
4550                    if type is None:
4551                        error(args[0].pos, "Unknown type")
4552                        return
4553                    lhs = self.lhs
4554                    if func_name == 'declare':
4555                        if isinstance(lhs, ExprNodes.NameNode):
4556                            vars = [(lhs.name, lhs.pos)]
4557                        elif isinstance(lhs, ExprNodes.TupleNode):
4558                            vars = [(var.name, var.pos) for var in lhs.args]
4559                        else:
4560                            error(lhs.pos, "Invalid declaration")
4561                            return
4562                        for var, pos in vars:
4563                            env.declare_var(var, type, pos, is_cdef = True)
4564                        if len(args) == 2:
4565                            # we have a value
4566                            self.rhs = args[1]
4567                        else:
4568                            self.declaration_only = True
4569                    else:
4570                        self.declaration_only = True
4571                        if not isinstance(lhs, ExprNodes.NameNode):
4572                            error(lhs.pos, "Invalid declaration.")
4573                        env.declare_typedef(lhs.name, type, self.pos, visibility='private')
4574
4575                elif func_name in ['struct', 'union']:
4576                    self.declaration_only = True
4577                    if len(args) > 0 or kwds is None:
4578                        error(self.rhs.pos, "Struct or union members must be given by name.")
4579                        return
4580                    members = []
4581                    for member, type_node in kwds.key_value_pairs:
4582                        type = type_node.analyse_as_type(env)
4583                        if type is None:
4584                            error(type_node.pos, "Unknown type")
4585                        else:
4586                            members.append((member.value, type, member.pos))
4587                    if len(members) < len(kwds.key_value_pairs):
4588                        return
4589                    if not isinstance(self.lhs, ExprNodes.NameNode):
4590                        error(self.lhs.pos, "Invalid declaration.")
4591                    name = self.lhs.name
4592                    scope = StructOrUnionScope(name)
4593                    env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
4594                    for member, type, pos in members:
4595                        scope.declare_var(member, type, pos)
4596
4597                elif func_name == 'fused_type':
4598                    # dtype = cython.fused_type(...)
4599                    self.declaration_only = True
4600                    if kwds:
4601                        error(self.rhs.function.pos,
4602                              "fused_type does not take keyword arguments")
4603
4604                    fusednode = FusedTypeNode(self.rhs.pos,
4605                                              name = self.lhs.name, types=args)
4606                    fusednode.analyse_declarations(env)
4607
4608        if self.declaration_only:
4609            return
4610        else:
4611            self.lhs.analyse_target_declaration(env)
4612
4613    def analyse_types(self, env, use_temp = 0):
4614        import ExprNodes
4615
4616        self.rhs = self.rhs.analyse_types(env)
4617        self.lhs = self.lhs.analyse_target_types(env)
4618        self.lhs.gil_assignment_check(env)
4619
4620        if self.lhs.memslice_broadcast or self.rhs.memslice_broadcast:
4621            self.lhs.memslice_broadcast = True
4622            self.rhs.memslice_broadcast = True
4623
4624        is_index_node = isinstance(self.lhs, ExprNodes.IndexNode)
4625        if (is_index_node and not self.rhs.type.is_memoryviewslice and
4626            (self.lhs.memslice_slice or self.lhs.is_memslice_copy) and
4627            (self.lhs.type.dtype.assignable_from(self.rhs.type) or
4628             self.rhs.type.is_pyobject)):
4629            # scalar slice assignment
4630            self.lhs.is_memslice_scalar_assignment = True
4631            dtype = self.lhs.type.dtype
4632        else:
4633            dtype = self.lhs.type
4634
4635        rhs = self.rhs.coerce_to(dtype, env)
4636        if use_temp or rhs.is_attribute or (
4637                not rhs.is_name and not rhs.is_literal and
4638                rhs.type.is_pyobject):
4639            # things like (cdef) attribute access are not safe (traverses pointers)
4640            rhs = rhs.coerce_to_temp(env)
4641        elif rhs.type.is_pyobject:
4642            rhs = rhs.coerce_to_simple(env)
4643        self.rhs = rhs
4644        return self
4645
4646    def generate_rhs_evaluation_code(self, code):
4647        self.rhs.generate_evaluation_code(code)
4648
4649    def generate_assignment_code(self, code):
4650        self.lhs.generate_assignment_code(self.rhs, code)
4651
4652    def generate_function_definitions(self, env, code):
4653        self.rhs.generate_function_definitions(env, code)
4654
4655    def annotate(self, code):
4656        self.lhs.annotate(code)
4657        self.rhs.annotate(code)
4658
4659
4660class CascadedAssignmentNode(AssignmentNode):
4661    #  An assignment with multiple left hand sides:
4662    #
4663    #    a = b = c
4664    #
4665    #  lhs_list   [ExprNode]   Left hand sides
4666    #  rhs        ExprNode     Right hand sides
4667    #
4668    #  Used internally:
4669    #
4670    #  coerced_rhs_list   [ExprNode]   RHS coerced to type of each LHS
4671
4672    child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
4673    coerced_rhs_list = None
4674
4675    def analyse_declarations(self, env):
4676        for lhs in self.lhs_list:
4677            lhs.analyse_target_declaration(env)
4678
4679    def analyse_types(self, env, use_temp = 0):
4680        from ExprNodes import CloneNode, ProxyNode
4681
4682        rhs = self.rhs.analyse_types(env)
4683        if use_temp or rhs.is_attribute or (
4684                not rhs.is_name and not rhs.is_literal and
4685                rhs.type.is_pyobject):
4686            rhs = rhs.coerce_to_temp(env)
4687        else:
4688            rhs = rhs.coerce_to_simple(env)
4689        self.rhs = ProxyNode(rhs)
4690
4691        self.coerced_rhs_list = []
4692        for lhs in self.lhs_list:
4693            lhs.analyse_target_types(env)
4694            lhs.gil_assignment_check(env)
4695            rhs = CloneNode(self.rhs)
4696            rhs = rhs.coerce_to(lhs.type, env)
4697            self.coerced_rhs_list.append(rhs)
4698        return self
4699
4700    def generate_rhs_evaluation_code(self, code):
4701        self.rhs.generate_evaluation_code(code)
4702
4703    def generate_assignment_code(self, code):
4704        for i in range(len(self.lhs_list)):
4705            lhs = self.lhs_list[i]
4706            rhs = self.coerced_rhs_list[i]
4707            rhs.generate_evaluation_code(code)
4708            lhs.generate_assignment_code(rhs, code)
4709            # Assignment has disposed of the cloned RHS
4710        self.rhs.generate_disposal_code(code)
4711        self.rhs.free_temps(code)
4712
4713    def generate_function_definitions(self, env, code):
4714        self.rhs.generate_function_definitions(env, code)
4715
4716    def annotate(self, code):
4717        for i in range(len(self.lhs_list)):
4718            self.lhs_list[i].annotate(code)
4719            self.coerced_rhs_list[i].annotate(code)
4720        self.rhs.annotate(code)
4721
4722
4723class ParallelAssignmentNode(AssignmentNode):
4724    #  A combined packing/unpacking assignment:
4725    #
4726    #    a, b, c =  d, e, f
4727    #
4728    #  This has been rearranged by the parser into
4729    #
4730    #    a = d ; b = e ; c = f
4731    #
4732    #  but we must evaluate all the right hand sides
4733    #  before assigning to any of the left hand sides.
4734    #
4735    #  stats     [AssignmentNode]   The constituent assignments
4736
4737    child_attrs = ["stats"]
4738
4739    def analyse_declarations(self, env):
4740        for stat in self.stats:
4741            stat.analyse_declarations(env)
4742
4743    def analyse_expressions(self, env):
4744        self.stats = [ stat.analyse_types(env, use_temp = 1)
4745                       for stat in self.stats ]
4746        return self
4747
4748#    def analyse_expressions(self, env):
4749#        for stat in self.stats:
4750#            stat.analyse_expressions_1(env, use_temp = 1)
4751#        for stat in self.stats:
4752#            stat.analyse_expressions_2(env)
4753
4754    def generate_execution_code(self, code):
4755        for stat in self.stats:
4756            stat.generate_rhs_evaluation_code(code)
4757        for stat in self.stats:
4758            stat.generate_assignment_code(code)
4759
4760    def generate_function_definitions(self, env, code):
4761        for stat in self.stats:
4762            stat.generate_function_definitions(env, code)
4763
4764    def annotate(self, code):
4765        for stat in self.stats:
4766            stat.annotate(code)
4767
4768
4769class InPlaceAssignmentNode(AssignmentNode):
4770    #  An in place arithmetic operand:
4771    #
4772    #    a += b
4773    #    a -= b
4774    #    ...
4775    #
4776    #  lhs      ExprNode      Left hand side
4777    #  rhs      ExprNode      Right hand side
4778    #  operator char          one of "+-*/%^&|"
4779    #
4780    #  This code is a bit tricky because in order to obey Python
4781    #  semantics the sub-expressions (e.g. indices) of the lhs must
4782    #  not be evaluated twice. So we must re-use the values calculated
4783    #  in evaluation phase for the assignment phase as well.
4784    #  Fortunately, the type of the lhs node is fairly constrained
4785    #  (it must be a NameNode, AttributeNode, or IndexNode).
4786
4787    child_attrs = ["lhs", "rhs"]
4788
4789    def analyse_declarations(self, env):
4790        self.lhs.analyse_target_declaration(env)
4791
4792    def analyse_types(self, env):
4793        self.rhs = self.rhs.analyse_types(env)
4794        self.lhs = self.lhs.analyse_target_types(env)
4795
4796        # When assigning to a fully indexed buffer or memoryview, coerce the rhs
4797        if (self.lhs.is_subscript and
4798                (self.lhs.memslice_index or self.lhs.is_buffer_access)):
4799            self.rhs = self.rhs.coerce_to(self.lhs.type, env)
4800        elif self.lhs.type.is_string and self.operator in '+-':
4801            # use pointer arithmetic for char* LHS instead of string concat
4802            self.rhs = self.rhs.coerce_to(PyrexTypes.c_py_ssize_t_type, env)
4803        return self
4804
4805    def generate_execution_code(self, code):
4806        self.rhs.generate_evaluation_code(code)
4807        self.lhs.generate_subexpr_evaluation_code(code)
4808        c_op = self.operator
4809        if c_op == "//":
4810            c_op = "/"
4811        elif c_op == "**":
4812            error(self.pos, "No C inplace power operator")
4813        if self.lhs.is_subscript and self.lhs.is_buffer_access:
4814            if self.lhs.type.is_pyobject:
4815                error(self.pos, "In-place operators not allowed on object buffers in this release.")
4816            if (c_op in ('/', '%') and self.lhs.type.is_int
4817                and not code.globalstate.directives['cdivision']):
4818                error(self.pos, "In-place non-c divide operators not allowed on int buffers.")
4819            self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
4820        else:
4821            # C++
4822            # TODO: make sure overload is declared
4823            code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()))
4824        self.lhs.generate_subexpr_disposal_code(code)
4825        self.lhs.free_subexpr_temps(code)
4826        self.rhs.generate_disposal_code(code)
4827        self.rhs.free_temps(code)
4828
4829    def annotate(self, code):
4830        self.lhs.annotate(code)
4831        self.rhs.annotate(code)
4832
4833    def create_binop_node(self):
4834        import ExprNodes
4835        return ExprNodes.binop_node(self.pos, self.operator, self.lhs, self.rhs)
4836
4837
4838class PrintStatNode(StatNode):
4839    #  print statement
4840    #
4841    #  arg_tuple         TupleNode
4842    #  stream            ExprNode or None (stdout)
4843    #  append_newline    boolean
4844
4845    child_attrs = ["arg_tuple", "stream"]
4846
4847    def analyse_expressions(self, env):
4848        if self.stream:
4849            stream = self.stream.analyse_expressions(env)
4850            self.stream = stream.coerce_to_pyobject(env)
4851        arg_tuple = self.arg_tuple.analyse_expressions(env)
4852        self.arg_tuple = arg_tuple.coerce_to_pyobject(env)
4853        env.use_utility_code(printing_utility_code)
4854        if len(self.arg_tuple.args) == 1 and self.append_newline:
4855            env.use_utility_code(printing_one_utility_code)
4856        return self
4857
4858    nogil_check = Node.gil_error
4859    gil_message = "Python print statement"
4860
4861    def generate_execution_code(self, code):
4862        if self.stream:
4863            self.stream.generate_evaluation_code(code)
4864            stream_result = self.stream.py_result()
4865        else:
4866            stream_result = '0'
4867        if len(self.arg_tuple.args) == 1 and self.append_newline:
4868            arg = self.arg_tuple.args[0]
4869            arg.generate_evaluation_code(code)
4870
4871            code.putln(
4872                "if (__Pyx_PrintOne(%s, %s) < 0) %s" % (
4873                    stream_result,
4874                    arg.py_result(),
4875                    code.error_goto(self.pos)))
4876            arg.generate_disposal_code(code)
4877            arg.free_temps(code)
4878        else:
4879            self.arg_tuple.generate_evaluation_code(code)
4880            code.putln(
4881                "if (__Pyx_Print(%s, %s, %d) < 0) %s" % (
4882                    stream_result,
4883                    self.arg_tuple.py_result(),
4884                    self.append_newline,
4885                    code.error_goto(self.pos)))
4886            self.arg_tuple.generate_disposal_code(code)
4887            self.arg_tuple.free_temps(code)
4888
4889        if self.stream:
4890            self.stream.generate_disposal_code(code)
4891            self.stream.free_temps(code)
4892
4893    def generate_function_definitions(self, env, code):
4894        if self.stream:
4895            self.stream.generate_function_definitions(env, code)
4896        self.arg_tuple.generate_function_definitions(env, code)
4897
4898    def annotate(self, code):
4899        if self.stream:
4900            self.stream.annotate(code)
4901        self.arg_tuple.annotate(code)
4902
4903
4904class ExecStatNode(StatNode):
4905    #  exec statement
4906    #
4907    #  args     [ExprNode]
4908
4909    child_attrs = ["args"]
4910
4911    def analyse_expressions(self, env):
4912        for i, arg in enumerate(self.args):
4913            arg = arg.analyse_expressions(env)
4914            arg = arg.coerce_to_pyobject(env)
4915            self.args[i] = arg
4916        env.use_utility_code(Builtin.pyexec_utility_code)
4917        return self
4918
4919    nogil_check = Node.gil_error
4920    gil_message = "Python exec statement"
4921
4922    def generate_execution_code(self, code):
4923        args = []
4924        for arg in self.args:
4925            arg.generate_evaluation_code(code)
4926            args.append( arg.py_result() )
4927        args = tuple(args + ['0', '0'][:3-len(args)])
4928        temp_result = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
4929        code.putln("%s = __Pyx_PyExec3(%s, %s, %s);" % (
4930                (temp_result,) + args))
4931        for arg in self.args:
4932            arg.generate_disposal_code(code)
4933            arg.free_temps(code)
4934        code.putln(
4935            code.error_goto_if_null(temp_result, self.pos))
4936        code.put_gotref(temp_result)
4937        code.put_decref_clear(temp_result, py_object_type)
4938        code.funcstate.release_temp(temp_result)
4939
4940    def annotate(self, code):
4941        for arg in self.args:
4942            arg.annotate(code)
4943
4944
4945class DelStatNode(StatNode):
4946    #  del statement
4947    #
4948    #  args     [ExprNode]
4949
4950    child_attrs = ["args"]
4951    ignore_nonexisting = False
4952
4953    def analyse_declarations(self, env):
4954        for arg in self.args:
4955            arg.analyse_target_declaration(env)
4956
4957    def analyse_expressions(self, env):
4958        for i, arg in enumerate(self.args):
4959            arg = self.args[i] = arg.analyse_target_expression(env, None)
4960            if arg.type.is_pyobject or (arg.is_name and
4961                                        arg.type.is_memoryviewslice):
4962                if arg.is_name and arg.entry.is_cglobal:
4963                    error(arg.pos, "Deletion of global C variable")
4964            elif arg.type.is_ptr and arg.type.base_type.is_cpp_class:
4965                self.cpp_check(env)
4966            elif arg.type.is_cpp_class:
4967                error(arg.pos, "Deletion of non-heap C++ object")
4968            elif arg.is_subscript and arg.base.type is Builtin.bytearray_type:
4969                pass  # del ba[i]
4970            else:
4971                error(arg.pos, "Deletion of non-Python, non-C++ object")
4972            #arg.release_target_temp(env)
4973        return self
4974
4975    def nogil_check(self, env):
4976        for arg in self.args:
4977            if arg.type.is_pyobject:
4978                self.gil_error()
4979
4980    gil_message = "Deleting Python object"
4981
4982    def generate_execution_code(self, code):
4983        for arg in self.args:
4984            if (arg.type.is_pyobject or
4985                    arg.type.is_memoryviewslice or
4986                    arg.is_subscript and arg.base.type is Builtin.bytearray_type):
4987                arg.generate_deletion_code(
4988                    code, ignore_nonexisting=self.ignore_nonexisting)
4989            elif arg.type.is_ptr and arg.type.base_type.is_cpp_class:
4990                arg.generate_result_code(code)
4991                code.putln("delete %s;" % arg.result())
4992            # else error reported earlier
4993
4994    def annotate(self, code):
4995        for arg in self.args:
4996            arg.annotate(code)
4997
4998
4999class PassStatNode(StatNode):
5000    #  pass statement
5001
5002    child_attrs = []
5003
5004    def analyse_expressions(self, env):
5005        return self
5006
5007    def generate_execution_code(self, code):
5008        pass
5009
5010
5011class IndirectionNode(StatListNode):
5012    """
5013    This adds an indirection so that the node can be shared and a subtree can
5014    be removed at any time by clearing self.stats.
5015    """
5016
5017    def __init__(self, stats):
5018        super(IndirectionNode, self).__init__(stats[0].pos, stats=stats)
5019
5020class BreakStatNode(StatNode):
5021
5022    child_attrs = []
5023    is_terminator = True
5024
5025    def analyse_expressions(self, env):
5026        return self
5027
5028    def generate_execution_code(self, code):
5029        if not code.break_label:
5030            error(self.pos, "break statement not inside loop")
5031        else:
5032            code.put_goto(code.break_label)
5033
5034
5035class ContinueStatNode(StatNode):
5036
5037    child_attrs = []
5038    is_terminator = True
5039
5040    def analyse_expressions(self, env):
5041        return self
5042
5043    def generate_execution_code(self, code):
5044        if code.funcstate.in_try_finally:
5045            error(self.pos, "continue statement inside try of try...finally")
5046        elif not code.continue_label:
5047            error(self.pos, "continue statement not inside loop")
5048        else:
5049            code.put_goto(code.continue_label)
5050
5051
5052class ReturnStatNode(StatNode):
5053    #  return statement
5054    #
5055    #  value         ExprNode or None
5056    #  return_type   PyrexType
5057    #  in_generator  return inside of generator => raise StopIteration
5058
5059    child_attrs = ["value"]
5060    is_terminator = True
5061    in_generator = False
5062
5063    # Whether we are in a parallel section
5064    in_parallel = False
5065
5066    def analyse_expressions(self, env):
5067        return_type = env.return_type
5068        self.return_type = return_type
5069        if not return_type:
5070            error(self.pos, "Return not inside a function body")
5071            return self
5072        if self.value:
5073            self.value = self.value.analyse_types(env)
5074            if return_type.is_void or return_type.is_returncode:
5075                error(self.value.pos,
5076                    "Return with value in void function")
5077            else:
5078                self.value = self.value.coerce_to(env.return_type, env)
5079        else:
5080            if (not return_type.is_void
5081                and not return_type.is_pyobject
5082                and not return_type.is_returncode):
5083                    error(self.pos, "Return value required")
5084        return self
5085
5086    def nogil_check(self, env):
5087        if self.return_type.is_pyobject:
5088            self.gil_error()
5089
5090    gil_message = "Returning Python object"
5091
5092    def generate_execution_code(self, code):
5093        code.mark_pos(self.pos)
5094        if not self.return_type:
5095            # error reported earlier
5096            return
5097        if self.return_type.is_pyobject:
5098            code.put_xdecref(Naming.retval_cname,
5099                             self.return_type)
5100
5101        if self.value:
5102            self.value.generate_evaluation_code(code)
5103            if self.return_type.is_memoryviewslice:
5104                import MemoryView
5105                MemoryView.put_acquire_memoryviewslice(
5106                        lhs_cname=Naming.retval_cname,
5107                        lhs_type=self.return_type,
5108                        lhs_pos=self.value.pos,
5109                        rhs=self.value,
5110                        code=code,
5111                        have_gil=self.in_nogil_context)
5112            elif self.in_generator:
5113                # return value == raise StopIteration(value), but uncatchable
5114                code.putln(
5115                    "%s = NULL; PyErr_SetObject(PyExc_StopIteration, %s);" % (
5116                        Naming.retval_cname,
5117                        self.value.result_as(self.return_type)))
5118                self.value.generate_disposal_code(code)
5119            else:
5120                self.value.make_owned_reference(code)
5121                code.putln(
5122                    "%s = %s;" % (
5123                        Naming.retval_cname,
5124                        self.value.result_as(self.return_type)))
5125            self.value.generate_post_assignment_code(code)
5126            self.value.free_temps(code)
5127        else:
5128            if self.return_type.is_pyobject:
5129                code.put_init_to_py_none(Naming.retval_cname, self.return_type)
5130            elif self.return_type.is_returncode:
5131                self.put_return(code, self.return_type.default_value)
5132
5133        for cname, type in code.funcstate.temps_holding_reference():
5134            code.put_decref_clear(cname, type)
5135
5136        code.put_goto(code.return_label)
5137
5138    def put_return(self, code, value):
5139        if self.in_parallel:
5140            code.putln_openmp("#pragma omp critical(__pyx_returning)")
5141        code.putln("%s = %s;" % (Naming.retval_cname, value))
5142
5143    def generate_function_definitions(self, env, code):
5144        if self.value is not None:
5145            self.value.generate_function_definitions(env, code)
5146
5147    def annotate(self, code):
5148        if self.value:
5149            self.value.annotate(code)
5150
5151
5152class RaiseStatNode(StatNode):
5153    #  raise statement
5154    #
5155    #  exc_type    ExprNode or None
5156    #  exc_value   ExprNode or None
5157    #  exc_tb      ExprNode or None
5158    #  cause       ExprNode or None
5159
5160    child_attrs = ["exc_type", "exc_value", "exc_tb", "cause"]
5161    is_terminator = True
5162
5163    def analyse_expressions(self, env):
5164        if self.exc_type:
5165            exc_type = self.exc_type.analyse_types(env)
5166            self.exc_type = exc_type.coerce_to_pyobject(env)
5167        if self.exc_value:
5168            exc_value = self.exc_value.analyse_types(env)
5169            self.exc_value = exc_value.coerce_to_pyobject(env)
5170        if self.exc_tb:
5171            exc_tb = self.exc_tb.analyse_types(env)
5172            self.exc_tb = exc_tb.coerce_to_pyobject(env)
5173        if self.cause:
5174            cause = self.cause.analyse_types(env)
5175            self.cause = cause.coerce_to_pyobject(env)
5176        # special cases for builtin exceptions
5177        self.builtin_exc_name = None
5178        if self.exc_type and not self.exc_value and not self.exc_tb:
5179            exc = self.exc_type
5180            import ExprNodes
5181            if (isinstance(exc, ExprNodes.SimpleCallNode) and
5182                not (exc.args or (exc.arg_tuple is not None and
5183                                  exc.arg_tuple.args))):
5184                exc = exc.function # extract the exception type
5185            if exc.is_name and exc.entry.is_builtin:
5186                self.builtin_exc_name = exc.name
5187                if self.builtin_exc_name == 'MemoryError':
5188                    self.exc_type = None # has a separate implementation
5189        return self
5190
5191    nogil_check = Node.gil_error
5192    gil_message = "Raising exception"
5193
5194    def generate_execution_code(self, code):
5195        if self.builtin_exc_name == 'MemoryError':
5196            code.putln('PyErr_NoMemory(); %s' % code.error_goto(self.pos))
5197            return
5198
5199        if self.exc_type:
5200            self.exc_type.generate_evaluation_code(code)
5201            type_code = self.exc_type.py_result()
5202        else:
5203            type_code = "0"
5204        if self.exc_value:
5205            self.exc_value.generate_evaluation_code(code)
5206            value_code = self.exc_value.py_result()
5207        else:
5208            value_code = "0"
5209        if self.exc_tb:
5210            self.exc_tb.generate_evaluation_code(code)
5211            tb_code = self.exc_tb.py_result()
5212        else:
5213            tb_code = "0"
5214        if self.cause:
5215            self.cause.generate_evaluation_code(code)
5216            cause_code = self.cause.py_result()
5217        else:
5218            cause_code = "0"
5219        code.globalstate.use_utility_code(raise_utility_code)
5220        code.putln(
5221            "__Pyx_Raise(%s, %s, %s, %s);" % (
5222                type_code,
5223                value_code,
5224                tb_code,
5225                cause_code))
5226        for obj in (self.exc_type, self.exc_value, self.exc_tb, self.cause):
5227            if obj:
5228                obj.generate_disposal_code(code)
5229                obj.free_temps(code)
5230        code.putln(
5231            code.error_goto(self.pos))
5232
5233    def generate_function_definitions(self, env, code):
5234        if self.exc_type is not None:
5235            self.exc_type.generate_function_definitions(env, code)
5236        if self.exc_value is not None:
5237            self.exc_value.generate_function_definitions(env, code)
5238        if self.exc_tb is not None:
5239            self.exc_tb.generate_function_definitions(env, code)
5240        if self.cause is not None:
5241            self.cause.generate_function_definitions(env, code)
5242
5243    def annotate(self, code):
5244        if self.exc_type:
5245            self.exc_type.annotate(code)
5246        if self.exc_value:
5247            self.exc_value.annotate(code)
5248        if self.exc_tb:
5249            self.exc_tb.annotate(code)
5250        if self.cause:
5251            self.cause.annotate(code)
5252
5253
5254class ReraiseStatNode(StatNode):
5255
5256    child_attrs = []
5257    is_terminator = True
5258
5259    def analyse_expressions(self, env):
5260        return self
5261
5262    nogil_check = Node.gil_error
5263    gil_message = "Raising exception"
5264
5265    def generate_execution_code(self, code):
5266        vars = code.funcstate.exc_vars
5267        if vars:
5268            code.globalstate.use_utility_code(restore_exception_utility_code)
5269            code.put_giveref(vars[0])
5270            code.put_giveref(vars[1])
5271            # fresh exceptions may not have a traceback yet (-> finally!)
5272            code.put_xgiveref(vars[2])
5273            code.putln("__Pyx_ErrRestore(%s, %s, %s);" % tuple(vars))
5274            for varname in vars:
5275                code.put("%s = 0; " % varname)
5276            code.putln()
5277            code.putln(code.error_goto(self.pos))
5278        else:
5279            code.globalstate.use_utility_code(
5280                UtilityCode.load_cached("ReRaiseException", "Exceptions.c"))
5281            code.putln("__Pyx_ReraiseException(); %s" % code.error_goto(self.pos))
5282
5283class AssertStatNode(StatNode):
5284    #  assert statement
5285    #
5286    #  cond    ExprNode
5287    #  value   ExprNode or None
5288
5289    child_attrs = ["cond", "value"]
5290
5291    def analyse_expressions(self, env):
5292        self.cond = self.cond.analyse_boolean_expression(env)
5293        if self.value:
5294            value = self.value.analyse_types(env)
5295            if value.type is Builtin.tuple_type or not value.type.is_builtin_type:
5296                # prevent tuple values from being interpreted as argument value tuples
5297                from ExprNodes import TupleNode
5298                value = TupleNode(value.pos, args=[value], slow=True)
5299                self.value = value.analyse_types(env, skip_children=True)
5300            else:
5301                self.value = value.coerce_to_pyobject(env)
5302        return self
5303
5304    nogil_check = Node.gil_error
5305    gil_message = "Raising exception"
5306
5307    def generate_execution_code(self, code):
5308        code.putln("#ifndef CYTHON_WITHOUT_ASSERTIONS")
5309        code.putln("if (unlikely(!Py_OptimizeFlag)) {")
5310        self.cond.generate_evaluation_code(code)
5311        code.putln(
5312            "if (unlikely(!%s)) {" %
5313                self.cond.result())
5314        if self.value:
5315            self.value.generate_evaluation_code(code)
5316            code.putln(
5317                "PyErr_SetObject(PyExc_AssertionError, %s);" %
5318                    self.value.py_result())
5319            self.value.generate_disposal_code(code)
5320            self.value.free_temps(code)
5321        else:
5322            code.putln(
5323                "PyErr_SetNone(PyExc_AssertionError);")
5324        code.putln(
5325                code.error_goto(self.pos))
5326        code.putln(
5327            "}")
5328        self.cond.generate_disposal_code(code)
5329        self.cond.free_temps(code)
5330        code.putln(
5331            "}")
5332        code.putln("#endif")
5333
5334    def generate_function_definitions(self, env, code):
5335        self.cond.generate_function_definitions(env, code)
5336        if self.value is not None:
5337            self.value.generate_function_definitions(env, code)
5338
5339    def annotate(self, code):
5340        self.cond.annotate(code)
5341        if self.value:
5342            self.value.annotate(code)
5343
5344
5345class IfStatNode(StatNode):
5346    #  if statement
5347    #
5348    #  if_clauses   [IfClauseNode]
5349    #  else_clause  StatNode or None
5350
5351    child_attrs = ["if_clauses", "else_clause"]
5352
5353    def analyse_declarations(self, env):
5354        for if_clause in self.if_clauses:
5355            if_clause.analyse_declarations(env)
5356        if self.else_clause:
5357            self.else_clause.analyse_declarations(env)
5358
5359    def analyse_expressions(self, env):
5360        self.if_clauses = [ if_clause.analyse_expressions(env)
5361                            for if_clause in self.if_clauses ]
5362        if self.else_clause:
5363            self.else_clause = self.else_clause.analyse_expressions(env)
5364        return self
5365
5366    def generate_execution_code(self, code):
5367        code.mark_pos(self.pos)
5368        end_label = code.new_label()
5369        for if_clause in self.if_clauses:
5370            if_clause.generate_execution_code(code, end_label)
5371        if self.else_clause:
5372            code.putln("/*else*/ {")
5373            self.else_clause.generate_execution_code(code)
5374            code.putln("}")
5375        code.put_label(end_label)
5376
5377    def generate_function_definitions(self, env, code):
5378        for clause in self.if_clauses:
5379            clause.generate_function_definitions(env, code)
5380        if self.else_clause is not None:
5381            self.else_clause.generate_function_definitions(env, code)
5382
5383    def annotate(self, code):
5384        for if_clause in self.if_clauses:
5385            if_clause.annotate(code)
5386        if self.else_clause:
5387            self.else_clause.annotate(code)
5388
5389
5390class IfClauseNode(Node):
5391    #  if or elif clause in an if statement
5392    #
5393    #  condition   ExprNode
5394    #  body        StatNode
5395
5396    child_attrs = ["condition", "body"]
5397
5398    def analyse_declarations(self, env):
5399        self.body.analyse_declarations(env)
5400
5401    def analyse_expressions(self, env):
5402        self.condition = \
5403            self.condition.analyse_temp_boolean_expression(env)
5404        self.body = self.body.analyse_expressions(env)
5405        return self
5406
5407    def generate_execution_code(self, code, end_label):
5408        self.condition.generate_evaluation_code(code)
5409        code.putln(
5410            "if (%s) {" %
5411                self.condition.result())
5412        self.condition.generate_disposal_code(code)
5413        self.condition.free_temps(code)
5414        self.body.generate_execution_code(code)
5415        if not self.body.is_terminator:
5416            code.put_goto(end_label)
5417        code.putln("}")
5418
5419    def generate_function_definitions(self, env, code):
5420        self.condition.generate_function_definitions(env, code)
5421        self.body.generate_function_definitions(env, code)
5422
5423    def annotate(self, code):
5424        self.condition.annotate(code)
5425        self.body.annotate(code)
5426
5427
5428class SwitchCaseNode(StatNode):
5429    # Generated in the optimization of an if-elif-else node
5430    #
5431    # conditions    [ExprNode]
5432    # body          StatNode
5433
5434    child_attrs = ['conditions', 'body']
5435
5436    def generate_execution_code(self, code):
5437        for cond in self.conditions:
5438            code.mark_pos(cond.pos)
5439            cond.generate_evaluation_code(code)
5440            code.putln("case %s:" % cond.result())
5441        self.body.generate_execution_code(code)
5442        code.putln("break;")
5443
5444    def generate_function_definitions(self, env, code):
5445        for cond in self.conditions:
5446            cond.generate_function_definitions(env, code)
5447        self.body.generate_function_definitions(env, code)
5448
5449    def annotate(self, code):
5450        for cond in self.conditions:
5451            cond.annotate(code)
5452        self.body.annotate(code)
5453
5454class SwitchStatNode(StatNode):
5455    # Generated in the optimization of an if-elif-else node
5456    #
5457    # test          ExprNode
5458    # cases         [SwitchCaseNode]
5459    # else_clause   StatNode or None
5460
5461    child_attrs = ['test', 'cases', 'else_clause']
5462
5463    def generate_execution_code(self, code):
5464        self.test.generate_evaluation_code(code)
5465        code.putln("switch (%s) {" % self.test.result())
5466        for case in self.cases:
5467            case.generate_execution_code(code)
5468        if self.else_clause is not None:
5469            code.putln("default:")
5470            self.else_clause.generate_execution_code(code)
5471            code.putln("break;")
5472        else:
5473            # Always generate a default clause to prevent C compiler warnings
5474            # about unmatched enum values (it was not the user who decided to
5475            # generate the switch statement, so shouldn't be bothered).
5476            code.putln("default: break;")
5477        code.putln("}")
5478
5479    def generate_function_definitions(self, env, code):
5480        self.test.generate_function_definitions(env, code)
5481        for case in self.cases:
5482            case.generate_function_definitions(env, code)
5483        if self.else_clause is not None:
5484            self.else_clause.generate_function_definitions(env, code)
5485
5486    def annotate(self, code):
5487        self.test.annotate(code)
5488        for case in self.cases:
5489            case.annotate(code)
5490        if self.else_clause is not None:
5491            self.else_clause.annotate(code)
5492
5493class LoopNode(object):
5494    pass
5495
5496
5497class WhileStatNode(LoopNode, StatNode):
5498    #  while statement
5499    #
5500    #  condition    ExprNode
5501    #  body         StatNode
5502    #  else_clause  StatNode
5503
5504    child_attrs = ["condition", "body", "else_clause"]
5505
5506    def analyse_declarations(self, env):
5507        self.body.analyse_declarations(env)
5508        if self.else_clause:
5509            self.else_clause.analyse_declarations(env)
5510
5511    def analyse_expressions(self, env):
5512        if self.condition:
5513            self.condition = self.condition.analyse_temp_boolean_expression(env)
5514        self.body = self.body.analyse_expressions(env)
5515        if self.else_clause:
5516            self.else_clause = self.else_clause.analyse_expressions(env)
5517        return self
5518
5519    def generate_execution_code(self, code):
5520        old_loop_labels = code.new_loop_labels()
5521        code.putln(
5522            "while (1) {")
5523        if self.condition:
5524            self.condition.generate_evaluation_code(code)
5525            self.condition.generate_disposal_code(code)
5526            code.putln(
5527                "if (!%s) break;" %
5528                    self.condition.result())
5529            self.condition.free_temps(code)
5530        self.body.generate_execution_code(code)
5531        code.put_label(code.continue_label)
5532        code.putln("}")
5533        break_label = code.break_label
5534        code.set_loop_labels(old_loop_labels)
5535        if self.else_clause:
5536            code.mark_pos(self.else_clause.pos)
5537            code.putln("/*else*/ {")
5538            self.else_clause.generate_execution_code(code)
5539            code.putln("}")
5540        code.put_label(break_label)
5541
5542    def generate_function_definitions(self, env, code):
5543        if self.condition:
5544            self.condition.generate_function_definitions(env, code)
5545        self.body.generate_function_definitions(env, code)
5546        if self.else_clause is not None:
5547            self.else_clause.generate_function_definitions(env, code)
5548
5549    def annotate(self, code):
5550        if self.condition:
5551            self.condition.annotate(code)
5552        self.body.annotate(code)
5553        if self.else_clause:
5554            self.else_clause.annotate(code)
5555
5556
5557class DictIterationNextNode(Node):
5558    # Helper node for calling PyDict_Next() inside of a WhileStatNode
5559    # and checking the dictionary size for changes.  Created in
5560    # Optimize.py.
5561    child_attrs = ['dict_obj', 'expected_size', 'pos_index_var',
5562                   'coerced_key_var', 'coerced_value_var', 'coerced_tuple_var',
5563                   'key_target', 'value_target', 'tuple_target', 'is_dict_flag']
5564
5565    coerced_key_var = key_ref = None
5566    coerced_value_var = value_ref = None
5567    coerced_tuple_var = tuple_ref = None
5568
5569    def __init__(self, dict_obj, expected_size, pos_index_var,
5570                 key_target, value_target, tuple_target, is_dict_flag):
5571        Node.__init__(
5572            self, dict_obj.pos,
5573            dict_obj = dict_obj,
5574            expected_size = expected_size,
5575            pos_index_var = pos_index_var,
5576            key_target = key_target,
5577            value_target = value_target,
5578            tuple_target = tuple_target,
5579            is_dict_flag = is_dict_flag,
5580            is_temp = True,
5581            type = PyrexTypes.c_bint_type)
5582
5583    def analyse_expressions(self, env):
5584        import ExprNodes
5585        self.dict_obj = self.dict_obj.analyse_types(env)
5586        self.expected_size = self.expected_size.analyse_types(env)
5587        if self.pos_index_var:
5588            self.pos_index_var = self.pos_index_var.analyse_types(env)
5589        if self.key_target:
5590            self.key_target = self.key_target.analyse_target_types(env)
5591            self.key_ref = ExprNodes.TempNode(self.key_target.pos, PyrexTypes.py_object_type)
5592            self.coerced_key_var = self.key_ref.coerce_to(self.key_target.type, env)
5593        if self.value_target:
5594            self.value_target = self.value_target.analyse_target_types(env)
5595            self.value_ref = ExprNodes.TempNode(self.value_target.pos, type=PyrexTypes.py_object_type)
5596            self.coerced_value_var = self.value_ref.coerce_to(self.value_target.type, env)
5597        if self.tuple_target:
5598            self.tuple_target = self.tuple_target.analyse_target_types(env)
5599            self.tuple_ref = ExprNodes.TempNode(self.tuple_target.pos, PyrexTypes.py_object_type)
5600            self.coerced_tuple_var = self.tuple_ref.coerce_to(self.tuple_target.type, env)
5601        self.is_dict_flag = self.is_dict_flag.analyse_types(env)
5602        return self
5603
5604    def generate_function_definitions(self, env, code):
5605        self.dict_obj.generate_function_definitions(env, code)
5606
5607    def generate_execution_code(self, code):
5608        code.globalstate.use_utility_code(UtilityCode.load_cached("dict_iter", "Optimize.c"))
5609        self.dict_obj.generate_evaluation_code(code)
5610
5611        assignments = []
5612        temp_addresses = []
5613        for var, result, target in [(self.key_ref, self.coerced_key_var, self.key_target),
5614                                    (self.value_ref, self.coerced_value_var, self.value_target),
5615                                    (self.tuple_ref, self.coerced_tuple_var, self.tuple_target)]:
5616            if target is None:
5617                addr = 'NULL'
5618            else:
5619                assignments.append((var, result, target))
5620                var.allocate(code)
5621                addr = '&%s' % var.result()
5622            temp_addresses.append(addr)
5623
5624        result_temp = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
5625        code.putln("%s = __Pyx_dict_iter_next(%s, %s, &%s, %s, %s, %s, %s);" % (
5626            result_temp,
5627            self.dict_obj.py_result(),
5628            self.expected_size.result(),
5629            self.pos_index_var.result(),
5630            temp_addresses[0],
5631            temp_addresses[1],
5632            temp_addresses[2],
5633            self.is_dict_flag.result()
5634        ))
5635        code.putln("if (unlikely(%s == 0)) break;" % result_temp)
5636        code.putln(code.error_goto_if("%s == -1" % result_temp, self.pos))
5637        code.funcstate.release_temp(result_temp)
5638
5639        # evaluate all coercions before the assignments
5640        for var, result, target in assignments:
5641            code.put_gotref(var.result())
5642        for var, result, target in assignments:
5643            result.generate_evaluation_code(code)
5644        for var, result, target in assignments:
5645            target.generate_assignment_code(result, code)
5646            var.release(code)
5647
5648def ForStatNode(pos, **kw):
5649    if 'iterator' in kw:
5650        return ForInStatNode(pos, **kw)
5651    else:
5652        return ForFromStatNode(pos, **kw)
5653
5654class ForInStatNode(LoopNode, StatNode):
5655    #  for statement
5656    #
5657    #  target        ExprNode
5658    #  iterator      IteratorNode
5659    #  body          StatNode
5660    #  else_clause   StatNode
5661    #  item          NextNode       used internally
5662
5663    child_attrs = ["target", "iterator", "body", "else_clause"]
5664    item = None
5665
5666    def analyse_declarations(self, env):
5667        import ExprNodes
5668        self.target.analyse_target_declaration(env)
5669        self.body.analyse_declarations(env)
5670        if self.else_clause:
5671            self.else_clause.analyse_declarations(env)
5672        self.item = ExprNodes.NextNode(self.iterator)
5673
5674    def analyse_expressions(self, env):
5675        self.target = self.target.analyse_target_types(env)
5676        self.iterator = self.iterator.analyse_expressions(env)
5677        import ExprNodes
5678        self.item = ExprNodes.NextNode(self.iterator)  # must rewrap after analysis
5679        self.item = self.item.analyse_expressions(env)
5680        if (self.iterator.type.is_ptr or self.iterator.type.is_array) and \
5681            self.target.type.assignable_from(self.iterator.type):
5682            # C array slice optimization.
5683            pass
5684        else:
5685            self.item = self.item.coerce_to(self.target.type, env)
5686        self.body = self.body.analyse_expressions(env)
5687        if self.else_clause:
5688            self.else_clause = self.else_clause.analyse_expressions(env)
5689        return self
5690
5691    def generate_execution_code(self, code):
5692        old_loop_labels = code.new_loop_labels()
5693        self.iterator.generate_evaluation_code(code)
5694        code.putln("for (;;) {")
5695        self.item.generate_evaluation_code(code)
5696        self.target.generate_assignment_code(self.item, code)
5697        self.body.generate_execution_code(code)
5698        code.put_label(code.continue_label)
5699        code.putln("}")
5700        break_label = code.break_label
5701        code.set_loop_labels(old_loop_labels)
5702
5703        if self.else_clause:
5704            # in nested loops, the 'else' block can contain a
5705            # 'continue' statement for the outer loop, but we may need
5706            # to generate cleanup code before taking that path, so we
5707            # intercept it here
5708            orig_continue_label = code.continue_label
5709            code.continue_label = code.new_label('outer_continue')
5710
5711            code.putln("/*else*/ {")
5712            self.else_clause.generate_execution_code(code)
5713            code.putln("}")
5714
5715            if code.label_used(code.continue_label):
5716                code.put_goto(break_label)
5717                code.put_label(code.continue_label)
5718                self.iterator.generate_disposal_code(code)
5719                code.put_goto(orig_continue_label)
5720            code.set_loop_labels(old_loop_labels)
5721
5722        if code.label_used(break_label):
5723            code.put_label(break_label)
5724        self.iterator.generate_disposal_code(code)
5725        self.iterator.free_temps(code)
5726
5727    def generate_function_definitions(self, env, code):
5728        self.target.generate_function_definitions(env, code)
5729        self.iterator.generate_function_definitions(env, code)
5730        self.body.generate_function_definitions(env, code)
5731        if self.else_clause is not None:
5732            self.else_clause.generate_function_definitions(env, code)
5733
5734    def annotate(self, code):
5735        self.target.annotate(code)
5736        self.iterator.annotate(code)
5737        self.body.annotate(code)
5738        if self.else_clause:
5739            self.else_clause.annotate(code)
5740        self.item.annotate(code)
5741
5742
5743class ForFromStatNode(LoopNode, StatNode):
5744    #  for name from expr rel name rel expr
5745    #
5746    #  target        NameNode
5747    #  bound1        ExprNode
5748    #  relation1     string
5749    #  relation2     string
5750    #  bound2        ExprNode
5751    #  step          ExprNode or None
5752    #  body          StatNode
5753    #  else_clause   StatNode or None
5754    #
5755    #  Used internally:
5756    #
5757    #  from_range         bool
5758    #  is_py_target       bool
5759    #  loopvar_node       ExprNode (usually a NameNode or temp node)
5760    #  py_loopvar_node    PyTempNode or None
5761    child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
5762
5763    is_py_target = False
5764    loopvar_node = None
5765    py_loopvar_node = None
5766    from_range = False
5767
5768    gil_message = "For-loop using object bounds or target"
5769
5770    def nogil_check(self, env):
5771        for x in (self.target, self.bound1, self.bound2):
5772            if x.type.is_pyobject:
5773                self.gil_error()
5774
5775    def analyse_declarations(self, env):
5776        self.target.analyse_target_declaration(env)
5777        self.body.analyse_declarations(env)
5778        if self.else_clause:
5779            self.else_clause.analyse_declarations(env)
5780
5781    def analyse_expressions(self, env):
5782        import ExprNodes
5783        self.target = self.target.analyse_target_types(env)
5784        self.bound1 = self.bound1.analyse_types(env)
5785        self.bound2 = self.bound2.analyse_types(env)
5786        if self.step is not None:
5787            if isinstance(self.step, ExprNodes.UnaryMinusNode):
5788                warning(self.step.pos, "Probable infinite loop in for-from-by statement. Consider switching the directions of the relations.", 2)
5789            self.step = self.step.analyse_types(env)
5790
5791        if self.target.type.is_numeric:
5792            loop_type = self.target.type
5793        else:
5794            loop_type = PyrexTypes.c_int_type
5795            if not self.bound1.type.is_pyobject:
5796                loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
5797            if not self.bound2.type.is_pyobject:
5798                loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
5799            if self.step is not None and not self.step.type.is_pyobject:
5800                loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
5801        self.bound1 = self.bound1.coerce_to(loop_type, env)
5802        self.bound2 = self.bound2.coerce_to(loop_type, env)
5803        if not self.bound2.is_literal:
5804            self.bound2 = self.bound2.coerce_to_temp(env)
5805        if self.step is not None:
5806            self.step = self.step.coerce_to(loop_type, env)
5807            if not self.step.is_literal:
5808                self.step = self.step.coerce_to_temp(env)
5809
5810        target_type = self.target.type
5811        if not (target_type.is_pyobject or target_type.is_numeric):
5812            error(self.target.pos,
5813                "for-from loop variable must be c numeric type or Python object")
5814        if target_type.is_numeric:
5815            self.is_py_target = False
5816            if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
5817                raise error(self.pos, "Buffer indexing not allowed as for loop target.")
5818            self.loopvar_node = self.target
5819            self.py_loopvar_node = None
5820        else:
5821            self.is_py_target = True
5822            c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
5823            self.loopvar_node = c_loopvar_node
5824            self.py_loopvar_node = \
5825                ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
5826        self.body = self.body.analyse_expressions(env)
5827        if self.else_clause:
5828            self.else_clause = self.else_clause.analyse_expressions(env)
5829        return self
5830
5831    def generate_execution_code(self, code):
5832        old_loop_labels = code.new_loop_labels()
5833        from_range = self.from_range
5834        self.bound1.generate_evaluation_code(code)
5835        self.bound2.generate_evaluation_code(code)
5836        offset, incop = self.relation_table[self.relation1]
5837        if self.step is not None:
5838            self.step.generate_evaluation_code(code)
5839            step = self.step.result()
5840            incop = "%s=%s" % (incop[0], step)
5841        import ExprNodes
5842        if isinstance(self.loopvar_node, ExprNodes.TempNode):
5843            self.loopvar_node.allocate(code)
5844        if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
5845            self.py_loopvar_node.allocate(code)
5846        if from_range:
5847            loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
5848        else:
5849            loopvar_name = self.loopvar_node.result()
5850        code.putln(
5851            "for (%s = %s%s; %s %s %s; %s%s) {" % (
5852                loopvar_name,
5853                self.bound1.result(), offset,
5854                loopvar_name, self.relation2, self.bound2.result(),
5855                loopvar_name, incop))
5856        if self.py_loopvar_node:
5857            self.py_loopvar_node.generate_evaluation_code(code)
5858            self.target.generate_assignment_code(self.py_loopvar_node, code)
5859        elif from_range:
5860            code.putln("%s = %s;" % (
5861                            self.target.result(), loopvar_name))
5862        self.body.generate_execution_code(code)
5863        code.put_label(code.continue_label)
5864        if self.py_loopvar_node:
5865            # This mess is to make for..from loops with python targets behave
5866            # exactly like those with C targets with regards to re-assignment
5867            # of the loop variable.
5868            import ExprNodes
5869            if self.target.entry.is_pyglobal:
5870                # We know target is a NameNode, this is the only ugly case.
5871                target_node = ExprNodes.PyTempNode(self.target.pos, None)
5872                target_node.allocate(code)
5873                interned_cname = code.intern_identifier(self.target.entry.name)
5874                if self.target.entry.scope.is_module_scope:
5875                    code.globalstate.use_utility_code(
5876                        UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c"))
5877                    lookup_func = '__Pyx_GetModuleGlobalName(%s)'
5878                else:
5879                    code.globalstate.use_utility_code(
5880                        UtilityCode.load_cached("GetNameInClass", "ObjectHandling.c"))
5881                    lookup_func = '__Pyx_GetNameInClass(%s, %%s)' % (
5882                        self.target.entry.scope.namespace_cname)
5883                code.putln("%s = %s; %s" % (
5884                    target_node.result(),
5885                    lookup_func % interned_cname,
5886                    code.error_goto_if_null(target_node.result(), self.target.pos)))
5887                code.put_gotref(target_node.result())
5888            else:
5889                target_node = self.target
5890            from_py_node = ExprNodes.CoerceFromPyTypeNode(
5891                self.loopvar_node.type, target_node, self.target.entry.scope)
5892            from_py_node.temp_code = loopvar_name
5893            from_py_node.generate_result_code(code)
5894            if self.target.entry.is_pyglobal:
5895                code.put_decref(target_node.result(), target_node.type)
5896                target_node.release(code)
5897        code.putln("}")
5898        if self.py_loopvar_node:
5899            # This is potentially wasteful, but we don't want the semantics to
5900            # depend on whether or not the loop is a python type.
5901            self.py_loopvar_node.generate_evaluation_code(code)
5902            self.target.generate_assignment_code(self.py_loopvar_node, code)
5903        if from_range:
5904            code.funcstate.release_temp(loopvar_name)
5905        break_label = code.break_label
5906        code.set_loop_labels(old_loop_labels)
5907        if self.else_clause:
5908            code.putln("/*else*/ {")
5909            self.else_clause.generate_execution_code(code)
5910            code.putln("}")
5911        code.put_label(break_label)
5912        self.bound1.generate_disposal_code(code)
5913        self.bound1.free_temps(code)
5914        self.bound2.generate_disposal_code(code)
5915        self.bound2.free_temps(code)
5916        if isinstance(self.loopvar_node, ExprNodes.TempNode):
5917            self.loopvar_node.release(code)
5918        if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
5919            self.py_loopvar_node.release(code)
5920        if self.step is not None:
5921            self.step.generate_disposal_code(code)
5922            self.step.free_temps(code)
5923
5924    relation_table = {
5925        # {relop : (initial offset, increment op)}
5926        '<=': ("",   "++"),
5927        '<' : ("+1", "++"),
5928        '>=': ("",   "--"),
5929        '>' : ("-1", "--")
5930    }
5931
5932    def generate_function_definitions(self, env, code):
5933        self.target.generate_function_definitions(env, code)
5934        self.bound1.generate_function_definitions(env, code)
5935        self.bound2.generate_function_definitions(env, code)
5936        if self.step is not None:
5937            self.step.generate_function_definitions(env, code)
5938        self.body.generate_function_definitions(env, code)
5939        if self.else_clause is not None:
5940            self.else_clause.generate_function_definitions(env, code)
5941
5942    def annotate(self, code):
5943        self.target.annotate(code)
5944        self.bound1.annotate(code)
5945        self.bound2.annotate(code)
5946        if self.step:
5947            self.step.annotate(code)
5948        self.body.annotate(code)
5949        if self.else_clause:
5950            self.else_clause.annotate(code)
5951
5952
5953class WithStatNode(StatNode):
5954    """
5955    Represents a Python with statement.
5956
5957    Implemented by the WithTransform as follows:
5958
5959        MGR = EXPR
5960        EXIT = MGR.__exit__
5961        VALUE = MGR.__enter__()
5962        EXC = True
5963        try:
5964            try:
5965                TARGET = VALUE  # optional
5966                BODY
5967            except:
5968                EXC = False
5969                if not EXIT(*EXCINFO):
5970                    raise
5971        finally:
5972            if EXC:
5973                EXIT(None, None, None)
5974            MGR = EXIT = VALUE = None
5975    """
5976    #  manager          The with statement manager object
5977    #  target           ExprNode  the target lhs of the __enter__() call
5978    #  body             StatNode
5979    #  enter_call       ExprNode  the call to the __enter__() method
5980    #  exit_var         String    the cname of the __exit__() method reference
5981
5982    child_attrs = ["manager", "enter_call", "target", "body"]
5983
5984    enter_call = None
5985
5986    def analyse_declarations(self, env):
5987        self.manager.analyse_declarations(env)
5988        self.enter_call.analyse_declarations(env)
5989        self.body.analyse_declarations(env)
5990
5991    def analyse_expressions(self, env):
5992        self.manager = self.manager.analyse_types(env)
5993        self.enter_call = self.enter_call.analyse_types(env)
5994        self.body = self.body.analyse_expressions(env)
5995        return self
5996
5997    def generate_function_definitions(self, env, code):
5998        self.manager.generate_function_definitions(env, code)
5999        self.enter_call.generate_function_definitions(env, code)
6000        self.body.generate_function_definitions(env, code)
6001
6002    def generate_execution_code(self, code):
6003        code.putln("/*with:*/ {")
6004        self.manager.generate_evaluation_code(code)
6005        self.exit_var = code.funcstate.allocate_temp(py_object_type, manage_ref=False)
6006        code.globalstate.use_utility_code(
6007            UtilityCode.load_cached("PyObjectLookupSpecial", "ObjectHandling.c"))
6008        code.putln("%s = __Pyx_PyObject_LookupSpecial(%s, %s); %s" % (
6009            self.exit_var,
6010            self.manager.py_result(),
6011            code.intern_identifier(EncodedString('__exit__')),
6012            code.error_goto_if_null(self.exit_var, self.pos),
6013            ))
6014        code.put_gotref(self.exit_var)
6015
6016        # need to free exit_var in the face of exceptions during setup
6017        old_error_label = code.new_error_label()
6018        intermediate_error_label = code.error_label
6019
6020        self.enter_call.generate_evaluation_code(code)
6021        if not self.target:
6022            self.enter_call.generate_disposal_code(code)
6023            self.enter_call.free_temps(code)
6024        else:
6025            # Otherwise, the node will be cleaned up by the
6026            # WithTargetAssignmentStatNode after assigning its result
6027            # to the target of the 'with' statement.
6028            pass
6029        self.manager.generate_disposal_code(code)
6030        self.manager.free_temps(code)
6031
6032        code.error_label = old_error_label
6033        self.body.generate_execution_code(code)
6034
6035        if code.label_used(intermediate_error_label):
6036            step_over_label = code.new_label()
6037            code.put_goto(step_over_label)
6038            code.put_label(intermediate_error_label)
6039            code.put_decref_clear(self.exit_var, py_object_type)
6040            code.put_goto(old_error_label)
6041            code.put_label(step_over_label)
6042
6043        code.funcstate.release_temp(self.exit_var)
6044        code.putln('}')
6045
6046class WithTargetAssignmentStatNode(AssignmentNode):
6047    # The target assignment of the 'with' statement value (return
6048    # value of the __enter__() call).
6049    #
6050    # This is a special cased assignment that steals the RHS reference
6051    # and frees its temp.
6052    #
6053    # lhs       ExprNode   the assignment target
6054    # rhs       CloneNode  a (coerced) CloneNode for the orig_rhs (not owned by this node)
6055    # orig_rhs  ExprNode   the original ExprNode of the rhs. this node will clean up the
6056    #                      temps of the orig_rhs. basically, it takes ownership of the node
6057    #                      when the WithStatNode is done with it.
6058
6059    child_attrs = ["lhs"]
6060
6061    def analyse_declarations(self, env):
6062        self.lhs.analyse_target_declaration(env)
6063
6064    def analyse_expressions(self, env):
6065        self.rhs = self.rhs.analyse_types(env)
6066        self.lhs = self.lhs.analyse_target_types(env)
6067        self.lhs.gil_assignment_check(env)
6068        self.rhs = self.rhs.coerce_to(self.lhs.type, env)
6069        return self
6070
6071    def generate_execution_code(self, code):
6072        if self.orig_rhs.type.is_pyobject:
6073            # make sure rhs gets freed on errors, see below
6074            old_error_label = code.new_error_label()
6075            intermediate_error_label = code.error_label
6076
6077        self.rhs.generate_evaluation_code(code)
6078        self.lhs.generate_assignment_code(self.rhs, code)
6079
6080        if self.orig_rhs.type.is_pyobject:
6081            self.orig_rhs.generate_disposal_code(code)
6082            code.error_label = old_error_label
6083            if code.label_used(intermediate_error_label):
6084                step_over_label = code.new_label()
6085                code.put_goto(step_over_label)
6086                code.put_label(intermediate_error_label)
6087                self.orig_rhs.generate_disposal_code(code)
6088                code.put_goto(old_error_label)
6089                code.put_label(step_over_label)
6090
6091        self.orig_rhs.free_temps(code)
6092
6093    def annotate(self, code):
6094        self.lhs.annotate(code)
6095        self.rhs.annotate(code)
6096
6097
6098class TryExceptStatNode(StatNode):
6099    #  try .. except statement
6100    #
6101    #  body             StatNode
6102    #  except_clauses   [ExceptClauseNode]
6103    #  else_clause      StatNode or None
6104
6105    child_attrs = ["body", "except_clauses", "else_clause"]
6106
6107    def analyse_declarations(self, env):
6108        self.body.analyse_declarations(env)
6109        for except_clause in self.except_clauses:
6110            except_clause.analyse_declarations(env)
6111        if self.else_clause:
6112            self.else_clause.analyse_declarations(env)
6113
6114    def analyse_expressions(self, env):
6115        self.body = self.body.analyse_expressions(env)
6116        default_clause_seen = 0
6117        for i, except_clause in enumerate(self.except_clauses):
6118            except_clause = self.except_clauses[i] = except_clause.analyse_expressions(env)
6119            if default_clause_seen:
6120                error(except_clause.pos, "default 'except:' must be last")
6121            if not except_clause.pattern:
6122                default_clause_seen = 1
6123        self.has_default_clause = default_clause_seen
6124        if self.else_clause:
6125            self.else_clause = self.else_clause.analyse_expressions(env)
6126        return self
6127
6128    nogil_check = Node.gil_error
6129    gil_message = "Try-except statement"
6130
6131    def generate_execution_code(self, code):
6132        old_return_label = code.return_label
6133        old_break_label = code.break_label
6134        old_continue_label = code.continue_label
6135        old_error_label = code.new_error_label()
6136        our_error_label = code.error_label
6137        except_end_label = code.new_label('exception_handled')
6138        except_error_label = code.new_label('except_error')
6139        except_return_label = code.new_label('except_return')
6140        try_return_label = code.new_label('try_return')
6141        try_break_label = code.new_label('try_break')
6142        try_continue_label = code.new_label('try_continue')
6143        try_end_label = code.new_label('try_end')
6144
6145        exc_save_vars = [code.funcstate.allocate_temp(py_object_type, False)
6146                         for _ in xrange(3)]
6147        code.putln("{")
6148        save_exc = code.insertion_point()
6149        code.putln(
6150            "/*try:*/ {")
6151        code.return_label = try_return_label
6152        code.break_label = try_break_label
6153        code.continue_label = try_continue_label
6154        self.body.generate_execution_code(code)
6155        code.putln(
6156            "}")
6157        temps_to_clean_up = code.funcstate.all_free_managed_temps()
6158        can_raise = code.label_used(our_error_label)
6159
6160        if can_raise:
6161            # inject code before the try block to save away the exception state
6162            code.globalstate.use_utility_code(reset_exception_utility_code)
6163            save_exc.putln("__Pyx_ExceptionSave(%s);" %
6164                           ', '.join(['&%s' % var for var in exc_save_vars]))
6165            for var in exc_save_vars:
6166                save_exc.put_xgotref(var)
6167
6168            def restore_saved_exception():
6169                for name in exc_save_vars:
6170                    code.put_xgiveref(name)
6171                code.putln("__Pyx_ExceptionReset(%s);" %
6172                           ', '.join(exc_save_vars))
6173        else:
6174            # try block cannot raise exceptions, but we had to allocate the temps above,
6175            # so just keep the C compiler from complaining about them being unused
6176            save_exc.putln("if (%s); else {/*mark used*/};" % '||'.join(exc_save_vars))
6177
6178            def restore_saved_exception():
6179                pass
6180
6181        code.error_label = except_error_label
6182        code.return_label = except_return_label
6183        if self.else_clause:
6184            code.putln(
6185                "/*else:*/ {")
6186            self.else_clause.generate_execution_code(code)
6187            code.putln(
6188                "}")
6189
6190        if can_raise:
6191            for var in exc_save_vars:
6192                code.put_xdecref_clear(var, py_object_type)
6193            code.put_goto(try_end_label)
6194            code.put_label(our_error_label)
6195            for temp_name, temp_type in temps_to_clean_up:
6196                code.put_xdecref_clear(temp_name, temp_type)
6197            for except_clause in self.except_clauses:
6198                except_clause.generate_handling_code(code, except_end_label)
6199            if not self.has_default_clause:
6200                code.put_goto(except_error_label)
6201
6202        for exit_label, old_label in [(except_error_label, old_error_label),
6203                                      (try_break_label, old_break_label),
6204                                      (try_continue_label, old_continue_label),
6205                                      (try_return_label, old_return_label),
6206                                      (except_return_label, old_return_label)]:
6207            if code.label_used(exit_label):
6208                if not code.label_used(try_end_label):
6209                    code.put_goto(try_end_label)
6210                code.put_label(exit_label)
6211                restore_saved_exception()
6212                code.put_goto(old_label)
6213
6214        if code.label_used(except_end_label):
6215            if not code.label_used(try_end_label):
6216                code.put_goto(try_end_label)
6217            code.put_label(except_end_label)
6218            restore_saved_exception()
6219        if code.label_used(try_end_label):
6220            code.put_label(try_end_label)
6221        code.putln("}")
6222
6223        for cname in exc_save_vars:
6224            code.funcstate.release_temp(cname)
6225
6226        code.return_label = old_return_label
6227        code.break_label = old_break_label
6228        code.continue_label = old_continue_label
6229        code.error_label = old_error_label
6230
6231    def generate_function_definitions(self, env, code):
6232        self.body.generate_function_definitions(env, code)
6233        for except_clause in self.except_clauses:
6234            except_clause.generate_function_definitions(env, code)
6235        if self.else_clause is not None:
6236            self.else_clause.generate_function_definitions(env, code)
6237
6238    def annotate(self, code):
6239        self.body.annotate(code)
6240        for except_node in self.except_clauses:
6241            except_node.annotate(code)
6242        if self.else_clause:
6243            self.else_clause.annotate(code)
6244
6245
6246class ExceptClauseNode(Node):
6247    #  Part of try ... except statement.
6248    #
6249    #  pattern        [ExprNode]
6250    #  target         ExprNode or None
6251    #  body           StatNode
6252    #  excinfo_target TupleNode(3*ResultRefNode) or None   optional target for exception info (not owned here!)
6253    #  match_flag     string             result of exception match
6254    #  exc_value      ExcValueNode       used internally
6255    #  function_name  string             qualified name of enclosing function
6256    #  exc_vars       (string * 3)       local exception variables
6257    #  is_except_as   bool               Py3-style "except ... as xyz"
6258
6259    # excinfo_target is never set by the parser, but can be set by a transform
6260    # in order to extract more extensive information about the exception as a
6261    # sys.exc_info()-style tuple into a target variable
6262
6263    child_attrs = ["pattern", "target", "body", "exc_value"]
6264
6265    exc_value = None
6266    excinfo_target = None
6267    is_except_as = False
6268
6269    def analyse_declarations(self, env):
6270        if self.target:
6271            self.target.analyse_target_declaration(env)
6272        self.body.analyse_declarations(env)
6273
6274    def analyse_expressions(self, env):
6275        self.function_name = env.qualified_name
6276        if self.pattern:
6277            # normalise/unpack self.pattern into a list
6278            for i, pattern in enumerate(self.pattern):
6279                pattern = pattern.analyse_expressions(env)
6280                self.pattern[i] = pattern.coerce_to_pyobject(env)
6281
6282        if self.target:
6283            import ExprNodes
6284            self.exc_value = ExprNodes.ExcValueNode(self.pos)
6285            self.target = self.target.analyse_target_expression(env, self.exc_value)
6286
6287        self.body = self.body.analyse_expressions(env)
6288        return self
6289
6290    def generate_handling_code(self, code, end_label):
6291        code.mark_pos(self.pos)
6292        if self.pattern:
6293            exc_tests = []
6294            for pattern in self.pattern:
6295                pattern.generate_evaluation_code(code)
6296                exc_tests.append("PyErr_ExceptionMatches(%s)" % pattern.py_result())
6297
6298            match_flag = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
6299            code.putln(
6300                "%s = %s;" % (match_flag, ' || '.join(exc_tests)))
6301            for pattern in self.pattern:
6302                pattern.generate_disposal_code(code)
6303                pattern.free_temps(code)
6304            code.putln(
6305                "if (%s) {" %
6306                    match_flag)
6307            code.funcstate.release_temp(match_flag)
6308        else:
6309            code.putln("/*except:*/ {")
6310
6311        if (not getattr(self.body, 'stats', True)
6312                and self.excinfo_target is None
6313                and self.target is None):
6314            # most simple case: no exception variable, empty body (pass)
6315            # => reset the exception state, done
6316            code.putln("PyErr_Restore(0,0,0);")
6317            code.put_goto(end_label)
6318            code.putln("}")
6319            return
6320
6321        exc_vars = [code.funcstate.allocate_temp(py_object_type,
6322                                                 manage_ref=True)
6323                    for _ in xrange(3)]
6324        code.put_add_traceback(self.function_name)
6325        # We always have to fetch the exception value even if
6326        # there is no target, because this also normalises the
6327        # exception and stores it in the thread state.
6328        code.globalstate.use_utility_code(get_exception_utility_code)
6329        exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
6330        code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
6331            code.error_goto(self.pos)))
6332        for x in exc_vars:
6333            code.put_gotref(x)
6334        if self.target:
6335            self.exc_value.set_var(exc_vars[1])
6336            self.exc_value.generate_evaluation_code(code)
6337            self.target.generate_assignment_code(self.exc_value, code)
6338        if self.excinfo_target is not None:
6339            for tempvar, node in zip(exc_vars, self.excinfo_target.args):
6340                node.set_var(tempvar)
6341
6342        old_break_label, old_continue_label = code.break_label, code.continue_label
6343        code.break_label = code.new_label('except_break')
6344        code.continue_label = code.new_label('except_continue')
6345
6346        old_exc_vars = code.funcstate.exc_vars
6347        code.funcstate.exc_vars = exc_vars
6348        self.body.generate_execution_code(code)
6349        code.funcstate.exc_vars = old_exc_vars
6350        for var in exc_vars:
6351            code.put_decref_clear(var, py_object_type)
6352        code.put_goto(end_label)
6353
6354        for new_label, old_label in [(code.break_label, old_break_label),
6355                                     (code.continue_label, old_continue_label)]:
6356            if code.label_used(new_label):
6357                code.put_label(new_label)
6358                for var in exc_vars:
6359                    code.put_decref_clear(var, py_object_type)
6360                code.put_goto(old_label)
6361        code.break_label = old_break_label
6362        code.continue_label = old_continue_label
6363
6364        for temp in exc_vars:
6365            code.funcstate.release_temp(temp)
6366
6367        code.putln(
6368            "}")
6369
6370    def generate_function_definitions(self, env, code):
6371        if self.target is not None:
6372            self.target.generate_function_definitions(env, code)
6373        self.body.generate_function_definitions(env, code)
6374
6375    def annotate(self, code):
6376        if self.pattern:
6377            for pattern in self.pattern:
6378                pattern.annotate(code)
6379        if self.target:
6380            self.target.annotate(code)
6381        self.body.annotate(code)
6382
6383
6384class TryFinallyStatNode(StatNode):
6385    #  try ... finally statement
6386    #
6387    #  body             StatNode
6388    #  finally_clause   StatNode
6389    #
6390    #  The plan is that we funnel all continue, break
6391    #  return and error gotos into the beginning of the
6392    #  finally block, setting a variable to remember which
6393    #  one we're doing. At the end of the finally block, we
6394    #  switch on the variable to figure out where to go.
6395    #  In addition, if we're doing an error, we save the
6396    #  exception on entry to the finally block and restore
6397    #  it on exit.
6398
6399    child_attrs = ["body", "finally_clause"]
6400
6401    preserve_exception = 1
6402
6403    # handle exception case, in addition to return/break/continue
6404    handle_error_case = True
6405    func_return_type = None
6406
6407    disallow_continue_in_try_finally = 0
6408    # There doesn't seem to be any point in disallowing
6409    # continue in the try block, since we have no problem
6410    # handling it.
6411
6412    is_try_finally_in_nogil = False
6413
6414    def create_analysed(pos, env, body, finally_clause):
6415        node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
6416        return node
6417    create_analysed = staticmethod(create_analysed)
6418
6419    def analyse_declarations(self, env):
6420        self.body.analyse_declarations(env)
6421        self.finally_clause.analyse_declarations(env)
6422
6423    def analyse_expressions(self, env):
6424        self.body = self.body.analyse_expressions(env)
6425        self.finally_clause = self.finally_clause.analyse_expressions(env)
6426        if env.return_type and not env.return_type.is_void:
6427            self.func_return_type = env.return_type
6428        return self
6429
6430    nogil_check = Node.gil_error
6431    gil_message = "Try-finally statement"
6432
6433    def generate_execution_code(self, code):
6434        old_error_label = code.error_label
6435        old_labels = code.all_new_labels()
6436        new_labels = code.get_all_labels()
6437        new_error_label = code.error_label
6438        if not self.handle_error_case:
6439            code.error_label = old_error_label
6440        catch_label = code.new_label()
6441
6442        code.putln("/*try:*/ {")
6443
6444        if self.disallow_continue_in_try_finally:
6445            was_in_try_finally = code.funcstate.in_try_finally
6446            code.funcstate.in_try_finally = 1
6447
6448        self.body.generate_execution_code(code)
6449
6450        if self.disallow_continue_in_try_finally:
6451            code.funcstate.in_try_finally = was_in_try_finally
6452
6453        code.putln("}")
6454        code.set_all_labels(old_labels)
6455
6456        temps_to_clean_up = code.funcstate.all_free_managed_temps()
6457        code.mark_pos(self.finally_clause.pos)
6458        code.putln("/*finally:*/ {")
6459
6460        def fresh_finally_clause(_next=[self.finally_clause]):
6461            # generate the original subtree once and always keep a fresh copy
6462            node = _next[0]
6463            node_copy = copy.deepcopy(node)
6464            if node is self.finally_clause:
6465                _next[0] = node_copy
6466            else:
6467                node = node_copy
6468            return node
6469
6470        preserve_error = self.preserve_exception and code.label_used(new_error_label)
6471        needs_success_cleanup = not self.finally_clause.is_terminator
6472
6473        if not self.body.is_terminator:
6474            code.putln('/*normal exit:*/{')
6475            fresh_finally_clause().generate_execution_code(code)
6476            if not self.finally_clause.is_terminator:
6477                code.put_goto(catch_label)
6478            code.putln('}')
6479
6480        if preserve_error:
6481            code.putln('/*exception exit:*/{')
6482            if self.is_try_finally_in_nogil:
6483                code.declare_gilstate()
6484            if needs_success_cleanup:
6485                exc_lineno_cnames = tuple([
6486                    code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False)
6487                    for _ in range(2)])
6488                exc_filename_cname = code.funcstate.allocate_temp(
6489                    PyrexTypes.CPtrType(PyrexTypes.c_const_type(PyrexTypes.c_char_type)),
6490                    manage_ref=False)
6491            else:
6492                exc_lineno_cnames = exc_filename_cname = None
6493            exc_vars = tuple([
6494                code.funcstate.allocate_temp(py_object_type, manage_ref=False)
6495                for _ in range(6)])
6496            code.put_label(new_error_label)
6497            self.put_error_catcher(
6498                code, temps_to_clean_up, exc_vars, exc_lineno_cnames, exc_filename_cname)
6499            finally_old_labels = code.all_new_labels()
6500
6501            code.putln('{')
6502            old_exc_vars = code.funcstate.exc_vars
6503            code.funcstate.exc_vars = exc_vars[:3]
6504            fresh_finally_clause().generate_execution_code(code)
6505            code.funcstate.exc_vars = old_exc_vars
6506            code.putln('}')
6507
6508            if needs_success_cleanup:
6509                self.put_error_uncatcher(code, exc_vars, exc_lineno_cnames, exc_filename_cname)
6510                if exc_lineno_cnames:
6511                    for cname in exc_lineno_cnames:
6512                        code.funcstate.release_temp(cname)
6513                if exc_filename_cname:
6514                    code.funcstate.release_temp(exc_filename_cname)
6515                code.put_goto(old_error_label)
6516
6517            for new_label, old_label in zip(code.get_all_labels(), finally_old_labels):
6518                if not code.label_used(new_label):
6519                    continue
6520                code.put_label(new_label)
6521                self.put_error_cleaner(code, exc_vars)
6522                code.put_goto(old_label)
6523
6524            for cname in exc_vars:
6525                code.funcstate.release_temp(cname)
6526            code.putln('}')
6527
6528        code.set_all_labels(old_labels)
6529        return_label = code.return_label
6530        for i, (new_label, old_label) in enumerate(zip(new_labels, old_labels)):
6531            if not code.label_used(new_label):
6532                continue
6533            if new_label == new_error_label and preserve_error:
6534                continue  # handled above
6535
6536            code.put('%s: ' % new_label)
6537            code.putln('{')
6538            ret_temp = None
6539            if old_label == return_label and not self.finally_clause.is_terminator:
6540                # store away return value for later reuse
6541                if (self.func_return_type and
6542                        not self.is_try_finally_in_nogil and
6543                        not isinstance(self.finally_clause, GILExitNode)):
6544                    ret_temp = code.funcstate.allocate_temp(
6545                        self.func_return_type, manage_ref=False)
6546                    code.putln("%s = %s;" % (ret_temp, Naming.retval_cname))
6547                    if self.func_return_type.is_pyobject:
6548                        code.putln("%s = 0;" % Naming.retval_cname)
6549            fresh_finally_clause().generate_execution_code(code)
6550            if ret_temp:
6551                code.putln("%s = %s;" % (Naming.retval_cname, ret_temp))
6552                if self.func_return_type.is_pyobject:
6553                    code.putln("%s = 0;" % ret_temp)
6554                code.funcstate.release_temp(ret_temp)
6555                ret_temp = None
6556            if not self.finally_clause.is_terminator:
6557                code.put_goto(old_label)
6558            code.putln('}')
6559
6560        # End finally
6561        code.put_label(catch_label)
6562        code.putln(
6563            "}")
6564
6565    def generate_function_definitions(self, env, code):
6566        self.body.generate_function_definitions(env, code)
6567        self.finally_clause.generate_function_definitions(env, code)
6568
6569    def put_error_catcher(self, code, temps_to_clean_up, exc_vars,
6570                          exc_lineno_cnames, exc_filename_cname):
6571        code.globalstate.use_utility_code(restore_exception_utility_code)
6572        code.globalstate.use_utility_code(get_exception_utility_code)
6573        code.globalstate.use_utility_code(swap_exception_utility_code)
6574
6575        code.putln(' '.join(["%s = 0;"]*len(exc_vars)) % exc_vars)
6576        if self.is_try_finally_in_nogil:
6577            code.put_ensure_gil(declare_gilstate=False)
6578
6579        for temp_name, type in temps_to_clean_up:
6580            code.put_xdecref_clear(temp_name, type)
6581
6582        # not using preprocessor here to avoid warnings about
6583        # unused utility functions and/or temps
6584        code.putln("if (PY_MAJOR_VERSION >= 3)"
6585                   " __Pyx_ExceptionSwap(&%s, &%s, &%s);" % exc_vars[3:])
6586        code.putln("if ((PY_MAJOR_VERSION < 3) ||"
6587                   # if __Pyx_GetException() fails in Py3,
6588                   # store the newly raised exception instead
6589                   " unlikely(__Pyx_GetException(&%s, &%s, &%s) < 0)) "
6590                   "__Pyx_ErrFetch(&%s, &%s, &%s);" % (exc_vars[:3] * 2))
6591        for var in exc_vars:
6592            code.put_xgotref(var)
6593        if exc_lineno_cnames:
6594            code.putln("%s = %s; %s = %s; %s = %s;" % (
6595                exc_lineno_cnames[0], Naming.lineno_cname,
6596                exc_lineno_cnames[1], Naming.clineno_cname,
6597                exc_filename_cname, Naming.filename_cname))
6598
6599        if self.is_try_finally_in_nogil:
6600            code.put_release_ensured_gil()
6601
6602    def put_error_uncatcher(self, code, exc_vars, exc_lineno_cnames, exc_filename_cname):
6603        code.globalstate.use_utility_code(restore_exception_utility_code)
6604        code.globalstate.use_utility_code(reset_exception_utility_code)
6605
6606        if self.is_try_finally_in_nogil:
6607            code.put_ensure_gil(declare_gilstate=False)
6608
6609        # not using preprocessor here to avoid warnings about
6610        # unused utility functions and/or temps
6611        code.putln("if (PY_MAJOR_VERSION >= 3) {")
6612        for var in exc_vars[3:]:
6613            code.put_xgiveref(var)
6614        code.putln("__Pyx_ExceptionReset(%s, %s, %s);" % exc_vars[3:])
6615        code.putln("}")
6616        for var in exc_vars[:3]:
6617            code.put_xgiveref(var)
6618        code.putln("__Pyx_ErrRestore(%s, %s, %s);" % exc_vars[:3])
6619
6620        if self.is_try_finally_in_nogil:
6621            code.put_release_ensured_gil()
6622
6623        code.putln(' '.join(["%s = 0;"]*len(exc_vars)) % exc_vars)
6624        if exc_lineno_cnames:
6625            code.putln("%s = %s; %s = %s; %s = %s;" % (
6626                Naming.lineno_cname, exc_lineno_cnames[0],
6627                Naming.clineno_cname, exc_lineno_cnames[1],
6628                Naming.filename_cname, exc_filename_cname))
6629
6630    def put_error_cleaner(self, code, exc_vars):
6631        code.globalstate.use_utility_code(reset_exception_utility_code)
6632        if self.is_try_finally_in_nogil:
6633            code.put_ensure_gil(declare_gilstate=False)
6634        # not using preprocessor here to avoid warnings about
6635        # unused utility functions and/or temps
6636        code.putln("if (PY_MAJOR_VERSION >= 3) {")
6637        for var in exc_vars[3:]:
6638            code.put_xgiveref(var)
6639        code.putln("__Pyx_ExceptionReset(%s, %s, %s);" % exc_vars[3:])
6640        code.putln("}")
6641        for var in exc_vars[:3]:
6642            code.put_xdecref_clear(var, py_object_type)
6643        if self.is_try_finally_in_nogil:
6644            code.put_release_ensured_gil()
6645        code.putln(' '.join(["%s = 0;"]*3) % exc_vars[3:])
6646
6647    def annotate(self, code):
6648        self.body.annotate(code)
6649        self.finally_clause.annotate(code)
6650
6651
6652class NogilTryFinallyStatNode(TryFinallyStatNode):
6653    """
6654    A try/finally statement that may be used in nogil code sections.
6655    """
6656
6657    preserve_exception = False
6658    nogil_check = None
6659
6660
6661class GILStatNode(NogilTryFinallyStatNode):
6662    #  'with gil' or 'with nogil' statement
6663    #
6664    #   state   string   'gil' or 'nogil'
6665
6666    state_temp = None
6667
6668    def __init__(self, pos, state, body):
6669        self.state = state
6670        self.create_state_temp_if_needed(pos, state, body)
6671        TryFinallyStatNode.__init__(self, pos,
6672            body=body,
6673            finally_clause=GILExitNode(
6674                pos, state=state, state_temp=self.state_temp))
6675
6676    def create_state_temp_if_needed(self, pos, state, body):
6677        from ParseTreeTransforms import YieldNodeCollector
6678        collector = YieldNodeCollector()
6679        collector.visitchildren(body)
6680        if not collector.yields:
6681            return
6682
6683        if state == 'gil':
6684            temp_type = PyrexTypes.c_gilstate_type
6685        else:
6686            temp_type = PyrexTypes.c_threadstate_ptr_type
6687        import ExprNodes
6688        self.state_temp = ExprNodes.TempNode(pos, temp_type)
6689
6690    def analyse_declarations(self, env):
6691        env._in_with_gil_block = (self.state == 'gil')
6692        if self.state == 'gil':
6693            env.has_with_gil_block = True
6694
6695        return super(GILStatNode, self).analyse_declarations(env)
6696
6697    def analyse_expressions(self, env):
6698        env.use_utility_code(
6699            UtilityCode.load_cached("ForceInitThreads", "ModuleSetupCode.c"))
6700        was_nogil = env.nogil
6701        env.nogil = self.state == 'nogil'
6702        node = TryFinallyStatNode.analyse_expressions(self, env)
6703        env.nogil = was_nogil
6704        return node
6705
6706    def generate_execution_code(self, code):
6707        code.mark_pos(self.pos)
6708        code.begin_block()
6709        if self.state_temp:
6710            self.state_temp.allocate(code)
6711            variable = self.state_temp.result()
6712        else:
6713            variable = None
6714
6715        old_trace_config = code.funcstate.can_trace
6716        if self.state == 'gil':
6717            code.put_ensure_gil(variable=variable)
6718            # FIXME: not that easy, tracing may not be possible at all here
6719            #code.funcstate.can_trace = True
6720        else:
6721            code.put_release_gil(variable=variable)
6722            code.funcstate.can_trace = False
6723
6724        TryFinallyStatNode.generate_execution_code(self, code)
6725
6726        if self.state_temp:
6727            self.state_temp.release(code)
6728
6729        code.funcstate.can_trace = old_trace_config
6730        code.end_block()
6731
6732
6733class GILExitNode(StatNode):
6734    """
6735    Used as the 'finally' block in a GILStatNode
6736
6737    state   string   'gil' or 'nogil'
6738    """
6739
6740    child_attrs = []
6741    state_temp = None
6742
6743    def analyse_expressions(self, env):
6744        return self
6745
6746    def generate_execution_code(self, code):
6747        if self.state_temp:
6748            variable = self.state_temp.result()
6749        else:
6750            variable = None
6751
6752        if self.state == 'gil':
6753            code.put_release_ensured_gil(variable)
6754        else:
6755            code.put_acquire_gil(variable)
6756
6757
6758class EnsureGILNode(GILExitNode):
6759    """
6760    Ensure the GIL in nogil functions for cleanup before returning.
6761    """
6762
6763    def generate_execution_code(self, code):
6764        code.put_ensure_gil(declare_gilstate=False)
6765
6766utility_code_for_cimports = {
6767    # utility code (or inlining c) in a pxd (or pyx) file.
6768    # TODO: Consider a generic user-level mechanism for importing
6769    'cpython.array'         : ("ArrayAPI", "arrayarray.h"),
6770    'cpython.array.array'   : ("ArrayAPI", "arrayarray.h"),
6771}
6772
6773class CImportStatNode(StatNode):
6774    #  cimport statement
6775    #
6776    #  module_name   string           Qualified name of module being imported
6777    #  as_name       string or None   Name specified in "as" clause, if any
6778
6779    child_attrs = []
6780
6781    def analyse_declarations(self, env):
6782        if not env.is_module_scope:
6783            error(self.pos, "cimport only allowed at module level")
6784            return
6785        module_scope = env.find_module(self.module_name, self.pos)
6786        if "." in self.module_name:
6787            names = [EncodedString(name) for name in self.module_name.split(".")]
6788            top_name = names[0]
6789            top_module_scope = env.context.find_submodule(top_name)
6790            module_scope = top_module_scope
6791            for name in names[1:]:
6792                submodule_scope = module_scope.find_submodule(name)
6793                module_scope.declare_module(name, submodule_scope, self.pos)
6794                module_scope = submodule_scope
6795            if self.as_name:
6796                env.declare_module(self.as_name, module_scope, self.pos)
6797            else:
6798                env.add_imported_module(module_scope)
6799                env.declare_module(top_name, top_module_scope, self.pos)
6800        else:
6801            name = self.as_name or self.module_name
6802            env.declare_module(name, module_scope, self.pos)
6803        if self.module_name in utility_code_for_cimports:
6804            env.use_utility_code(UtilityCode.load_cached(
6805                *utility_code_for_cimports[self.module_name]))
6806
6807    def analyse_expressions(self, env):
6808        return self
6809
6810    def generate_execution_code(self, code):
6811        pass
6812
6813
6814class FromCImportStatNode(StatNode):
6815    #  from ... cimport statement
6816    #
6817    #  module_name     string                        Qualified name of module
6818    #  imported_names  [(pos, name, as_name, kind)]  Names to be imported
6819
6820    child_attrs = []
6821
6822    def analyse_declarations(self, env):
6823        if not env.is_module_scope:
6824            error(self.pos, "cimport only allowed at module level")
6825            return
6826        module_scope = env.find_module(self.module_name, self.pos)
6827        env.add_imported_module(module_scope)
6828        for pos, name, as_name, kind in self.imported_names:
6829            if name == "*":
6830                for local_name, entry in module_scope.entries.items():
6831                    env.add_imported_entry(local_name, entry, pos)
6832            else:
6833                entry = module_scope.lookup(name)
6834                if entry:
6835                    if kind and not self.declaration_matches(entry, kind):
6836                        entry.redeclared(pos)
6837                    entry.used = 1
6838                else:
6839                    if kind == 'struct' or kind == 'union':
6840                        entry = module_scope.declare_struct_or_union(name,
6841                            kind = kind, scope = None, typedef_flag = 0, pos = pos)
6842                    elif kind == 'class':
6843                        entry = module_scope.declare_c_class(name, pos = pos,
6844                            module_name = self.module_name)
6845                    else:
6846                        submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
6847                        if submodule_scope.parent_module is module_scope:
6848                            env.declare_module(as_name or name, submodule_scope, self.pos)
6849                        else:
6850                            error(pos, "Name '%s' not declared in module '%s'"
6851                                % (name, self.module_name))
6852
6853                if entry:
6854                    local_name = as_name or name
6855                    env.add_imported_entry(local_name, entry, pos)
6856
6857        if self.module_name.startswith('cpython'): # enough for now
6858            if self.module_name in utility_code_for_cimports:
6859                env.use_utility_code(UtilityCode.load_cached(
6860                    *utility_code_for_cimports[self.module_name]))
6861            for _, name, _, _ in self.imported_names:
6862                fqname = '%s.%s' % (self.module_name, name)
6863                if fqname in utility_code_for_cimports:
6864                    env.use_utility_code(UtilityCode.load_cached(
6865                        *utility_code_for_cimports[fqname]))
6866
6867    def declaration_matches(self, entry, kind):
6868        if not entry.is_type:
6869            return 0
6870        type = entry.type
6871        if kind == 'class':
6872            if not type.is_extension_type:
6873                return 0
6874        else:
6875            if not type.is_struct_or_union:
6876                return 0
6877            if kind != type.kind:
6878                return 0
6879        return 1
6880
6881    def analyse_expressions(self, env):
6882        return self
6883
6884    def generate_execution_code(self, code):
6885        pass
6886
6887
6888class FromImportStatNode(StatNode):
6889    #  from ... import statement
6890    #
6891    #  module           ImportNode
6892    #  items            [(string, NameNode)]
6893    #  interned_items   [(string, NameNode, ExprNode)]
6894    #  item             PyTempNode            used internally
6895    #  import_star      boolean               used internally
6896
6897    child_attrs = ["module"]
6898    import_star = 0
6899
6900    def analyse_declarations(self, env):
6901        for name, target in self.items:
6902            if name == "*":
6903                if not env.is_module_scope:
6904                    error(self.pos, "import * only allowed at module level")
6905                    return
6906                env.has_import_star = 1
6907                self.import_star = 1
6908            else:
6909                target.analyse_target_declaration(env)
6910
6911    def analyse_expressions(self, env):
6912        import ExprNodes
6913        self.module = self.module.analyse_expressions(env)
6914        self.item = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
6915        self.interned_items = []
6916        for name, target in self.items:
6917            if name == '*':
6918                for _, entry in env.entries.items():
6919                    if not entry.is_type and entry.type.is_extension_type:
6920                        env.use_utility_code(UtilityCode.load_cached("ExtTypeTest", "ObjectHandling.c"))
6921                        break
6922            else:
6923                entry =  env.lookup(target.name)
6924                # check whether or not entry is already cimported
6925                if (entry.is_type and entry.type.name == name
6926                        and hasattr(entry.type, 'module_name')):
6927                    if entry.type.module_name == self.module.module_name.value:
6928                        # cimported with absolute name
6929                        continue
6930                    try:
6931                        # cimported with relative name
6932                        module = env.find_module(self.module.module_name.value,
6933                                                 pos=None)
6934                        if entry.type.module_name == module.qualified_name:
6935                            continue
6936                    except AttributeError:
6937                        pass
6938                target = target.analyse_target_expression(env, None)  # FIXME?
6939                if target.type is py_object_type:
6940                    coerced_item = None
6941                else:
6942                    coerced_item = self.item.coerce_to(target.type, env)
6943                self.interned_items.append((name, target, coerced_item))
6944        return self
6945
6946    def generate_execution_code(self, code):
6947        self.module.generate_evaluation_code(code)
6948        if self.import_star:
6949            code.putln(
6950                'if (%s(%s) < 0) %s;' % (
6951                    Naming.import_star,
6952                    self.module.py_result(),
6953                    code.error_goto(self.pos)))
6954        item_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
6955        self.item.set_cname(item_temp)
6956        if self.interned_items:
6957            code.globalstate.use_utility_code(
6958                UtilityCode.load_cached("ImportFrom", "ImportExport.c"))
6959        for name, target, coerced_item in self.interned_items:
6960            code.putln(
6961                '%s = __Pyx_ImportFrom(%s, %s); %s' % (
6962                    item_temp,
6963                    self.module.py_result(),
6964                    code.intern_identifier(name),
6965                    code.error_goto_if_null(item_temp, self.pos)))
6966            code.put_gotref(item_temp)
6967            if coerced_item is None:
6968                target.generate_assignment_code(self.item, code)
6969            else:
6970                coerced_item.allocate_temp_result(code)
6971                coerced_item.generate_result_code(code)
6972                target.generate_assignment_code(coerced_item, code)
6973            code.put_decref_clear(item_temp, py_object_type)
6974        code.funcstate.release_temp(item_temp)
6975        self.module.generate_disposal_code(code)
6976        self.module.free_temps(code)
6977
6978
6979class ParallelNode(Node):
6980    """
6981    Base class for cython.parallel constructs.
6982    """
6983
6984    nogil_check = None
6985
6986
6987class ParallelStatNode(StatNode, ParallelNode):
6988    """
6989    Base class for 'with cython.parallel.parallel():' and 'for i in prange():'.
6990
6991    assignments     { Entry(var) : (var.pos, inplace_operator_or_None) }
6992                    assignments to variables in this parallel section
6993
6994    parent          parent ParallelStatNode or None
6995    is_parallel     indicates whether this node is OpenMP parallel
6996                    (true for #pragma omp parallel for and
6997                              #pragma omp parallel)
6998
6999    is_parallel is true for:
7000
7001        #pragma omp parallel
7002        #pragma omp parallel for
7003
7004    sections, but NOT for
7005
7006        #pragma omp for
7007
7008    We need this to determine the sharing attributes.
7009
7010    privatization_insertion_point   a code insertion point used to make temps
7011                                    private (esp. the "nsteps" temp)
7012
7013    args         tuple          the arguments passed to the parallel construct
7014    kwargs       DictNode       the keyword arguments passed to the parallel
7015                                construct (replaced by its compile time value)
7016    """
7017
7018    child_attrs = ['body', 'num_threads']
7019
7020    body = None
7021
7022    is_prange = False
7023    is_nested_prange = False
7024
7025    error_label_used = False
7026
7027    num_threads = None
7028    chunksize = None
7029
7030    parallel_exc = (
7031        Naming.parallel_exc_type,
7032        Naming.parallel_exc_value,
7033        Naming.parallel_exc_tb,
7034    )
7035
7036    parallel_pos_info = (
7037        Naming.parallel_filename,
7038        Naming.parallel_lineno,
7039        Naming.parallel_clineno,
7040    )
7041
7042    pos_info = (
7043        Naming.filename_cname,
7044        Naming.lineno_cname,
7045        Naming.clineno_cname,
7046    )
7047
7048    critical_section_counter = 0
7049
7050    def __init__(self, pos, **kwargs):
7051        super(ParallelStatNode, self).__init__(pos, **kwargs)
7052
7053        # All assignments in this scope
7054        self.assignments = kwargs.get('assignments') or {}
7055
7056        # All seen closure cnames and their temporary cnames
7057        self.seen_closure_vars = set()
7058
7059        # Dict of variables that should be declared (first|last|)private or
7060        # reduction { Entry: (op, lastprivate) }.
7061        # If op is not None, it's a reduction.
7062        self.privates = {}
7063
7064        # [NameNode]
7065        self.assigned_nodes = []
7066
7067    def analyse_declarations(self, env):
7068        self.body.analyse_declarations(env)
7069
7070        self.num_threads = None
7071
7072        if self.kwargs:
7073            # Try to find num_threads and chunksize keyword arguments
7074            pairs = []
7075            for dictitem in self.kwargs.key_value_pairs:
7076                if dictitem.key.value == 'num_threads':
7077                    self.num_threads = dictitem.value
7078                elif self.is_prange and dictitem.key.value == 'chunksize':
7079                    self.chunksize = dictitem.value
7080                else:
7081                    pairs.append(dictitem)
7082
7083            self.kwargs.key_value_pairs = pairs
7084
7085            try:
7086                self.kwargs = self.kwargs.compile_time_value(env)
7087            except Exception, e:
7088                error(self.kwargs.pos, "Only compile-time values may be "
7089                                       "supplied as keyword arguments")
7090        else:
7091            self.kwargs = {}
7092
7093        for kw, val in self.kwargs.iteritems():
7094            if kw not in self.valid_keyword_arguments:
7095                error(self.pos, "Invalid keyword argument: %s" % kw)
7096            else:
7097                setattr(self, kw, val)
7098
7099    def analyse_expressions(self, env):
7100        if self.num_threads:
7101            self.num_threads = self.num_threads.analyse_expressions(env)
7102
7103        if self.chunksize:
7104            self.chunksize = self.chunksize.analyse_expressions(env)
7105
7106        self.body = self.body.analyse_expressions(env)
7107        self.analyse_sharing_attributes(env)
7108
7109        if self.num_threads is not None:
7110            if (self.parent and self.parent.num_threads is not None and not
7111                                                    self.parent.is_prange):
7112                error(self.pos,
7113                      "num_threads already declared in outer section")
7114            elif self.parent and not self.parent.is_prange:
7115                error(self.pos,
7116                      "num_threads must be declared in the parent parallel section")
7117            elif (self.num_threads.type.is_int and
7118                  self.num_threads.is_literal and
7119                  self.num_threads.compile_time_value(env) <= 0):
7120                error(self.pos,
7121                      "argument to num_threads must be greater than 0")
7122
7123            if not self.num_threads.is_simple():
7124                self.num_threads = self.num_threads.coerce_to(
7125                    PyrexTypes.c_int_type, env).coerce_to_temp(env)
7126        return self
7127
7128    def analyse_sharing_attributes(self, env):
7129        """
7130        Analyse the privates for this block and set them in self.privates.
7131        This should be called in a post-order fashion during the
7132        analyse_expressions phase
7133        """
7134        for entry, (pos, op) in self.assignments.iteritems():
7135
7136            if self.is_prange and not self.is_parallel:
7137                # closely nested prange in a with parallel block, disallow
7138                # assigning to privates in the with parallel block (we
7139                # consider it too implicit and magicky for users)
7140                if entry in self.parent.assignments:
7141                    error(pos,
7142                          "Cannot assign to private of outer parallel block")
7143                    continue
7144
7145            if not self.is_prange and op:
7146                # Again possible, but considered to magicky
7147                error(pos, "Reductions not allowed for parallel blocks")
7148                continue
7149
7150            # By default all variables should have the same values as if
7151            # executed sequentially
7152            lastprivate = True
7153            self.propagate_var_privatization(entry, pos, op, lastprivate)
7154
7155    def propagate_var_privatization(self, entry, pos, op, lastprivate):
7156        """
7157        Propagate the sharing attributes of a variable. If the privatization is
7158        determined by a parent scope, done propagate further.
7159
7160        If we are a prange, we propagate our sharing attributes outwards to
7161        other pranges. If we are a prange in parallel block and the parallel
7162        block does not determine the variable private, we propagate to the
7163        parent of the parent. Recursion stops at parallel blocks, as they have
7164        no concept of lastprivate or reduction.
7165
7166        So the following cases propagate:
7167
7168            sum is a reduction for all loops:
7169
7170                for i in prange(n):
7171                    for j in prange(n):
7172                        for k in prange(n):
7173                            sum += i * j * k
7174
7175            sum is a reduction for both loops, local_var is private to the
7176            parallel with block:
7177
7178                for i in prange(n):
7179                    with parallel:
7180                        local_var = ... # private to the parallel
7181                        for j in prange(n):
7182                            sum += i * j
7183
7184        Nested with parallel blocks are disallowed, because they wouldn't
7185        allow you to propagate lastprivates or reductions:
7186
7187            #pragma omp parallel for lastprivate(i)
7188            for i in prange(n):
7189
7190                sum = 0
7191
7192                #pragma omp parallel private(j, sum)
7193                with parallel:
7194
7195                    #pragma omp parallel
7196                    with parallel:
7197
7198                        #pragma omp for lastprivate(j) reduction(+:sum)
7199                        for j in prange(n):
7200                            sum += i
7201
7202                    # sum and j are well-defined here
7203
7204                # sum and j are undefined here
7205
7206            # sum and j are undefined here
7207        """
7208        self.privates[entry] = (op, lastprivate)
7209
7210        if entry.type.is_memoryviewslice:
7211            error(pos, "Memoryview slices can only be shared in parallel sections")
7212            return
7213
7214        if self.is_prange:
7215            if not self.is_parallel and entry not in self.parent.assignments:
7216                # Parent is a parallel with block
7217                parent = self.parent.parent
7218            else:
7219                parent = self.parent
7220
7221            # We don't need to propagate privates, only reductions and
7222            # lastprivates
7223            if parent and (op or lastprivate):
7224                parent.propagate_var_privatization(entry, pos, op, lastprivate)
7225
7226    def _allocate_closure_temp(self, code, entry):
7227        """
7228        Helper function that allocate a temporary for a closure variable that
7229        is assigned to.
7230        """
7231        if self.parent:
7232            return self.parent._allocate_closure_temp(code, entry)
7233
7234        if entry.cname in self.seen_closure_vars:
7235            return entry.cname
7236
7237        cname = code.funcstate.allocate_temp(entry.type, True)
7238
7239        # Add both the actual cname and the temp cname, as the actual cname
7240        # will be replaced with the temp cname on the entry
7241        self.seen_closure_vars.add(entry.cname)
7242        self.seen_closure_vars.add(cname)
7243
7244        self.modified_entries.append((entry, entry.cname))
7245        code.putln("%s = %s;" % (cname, entry.cname))
7246        entry.cname = cname
7247
7248    def initialize_privates_to_nan(self, code, exclude=None):
7249        first = True
7250
7251        for entry, (op, lastprivate) in self.privates.iteritems():
7252            if not op and (not exclude or entry != exclude):
7253                invalid_value = entry.type.invalid_value()
7254
7255                if invalid_value:
7256                    if first:
7257                        code.putln("/* Initialize private variables to "
7258                                   "invalid values */")
7259                        first = False
7260                    code.putln("%s = %s;" % (entry.cname,
7261                                             entry.type.cast_code(invalid_value)))
7262
7263    def evaluate_before_block(self, code, expr):
7264        c = self.begin_of_parallel_control_block_point_after_decls
7265        # we need to set the owner to ourselves temporarily, as
7266        # allocate_temp may generate a comment in the middle of our pragma
7267        # otherwise when DebugFlags.debug_temp_code_comments is in effect
7268        owner = c.funcstate.owner
7269        c.funcstate.owner = c
7270        expr.generate_evaluation_code(c)
7271        c.funcstate.owner = owner
7272
7273        return expr.result()
7274
7275    def put_num_threads(self, code):
7276        """
7277        Write self.num_threads if set as the num_threads OpenMP directive
7278        """
7279        if self.num_threads is not None:
7280            code.put(" num_threads(%s)" % self.evaluate_before_block(code,
7281                                                        self.num_threads))
7282
7283
7284    def declare_closure_privates(self, code):
7285        """
7286        If a variable is in a scope object, we need to allocate a temp and
7287        assign the value from the temp to the variable in the scope object
7288        after the parallel section. This kind of copying should be done only
7289        in the outermost parallel section.
7290        """
7291        self.modified_entries = []
7292
7293        for entry in self.assignments:
7294            if entry.from_closure or entry.in_closure:
7295                self._allocate_closure_temp(code, entry)
7296
7297    def release_closure_privates(self, code):
7298        """
7299        Release any temps used for variables in scope objects. As this is the
7300        outermost parallel block, we don't need to delete the cnames from
7301        self.seen_closure_vars.
7302        """
7303        for entry, original_cname in self.modified_entries:
7304            code.putln("%s = %s;" % (original_cname, entry.cname))
7305            code.funcstate.release_temp(entry.cname)
7306            entry.cname = original_cname
7307
7308    def privatize_temps(self, code, exclude_temps=()):
7309        """
7310        Make any used temporaries private. Before the relevant code block
7311        code.start_collecting_temps() should have been called.
7312        """
7313        if self.is_parallel:
7314            c = self.privatization_insertion_point
7315
7316            self.temps = temps = code.funcstate.stop_collecting_temps()
7317            privates, firstprivates = [], []
7318            for temp, type in temps:
7319                if type.is_pyobject or type.is_memoryviewslice:
7320                    firstprivates.append(temp)
7321                else:
7322                    privates.append(temp)
7323
7324            if privates:
7325                c.put(" private(%s)" % ", ".join(privates))
7326            if firstprivates:
7327                c.put(" firstprivate(%s)" % ", ".join(firstprivates))
7328
7329            if self.breaking_label_used:
7330                shared_vars = [Naming.parallel_why]
7331                if self.error_label_used:
7332                    shared_vars.extend(self.parallel_exc)
7333                    c.put(" private(%s, %s, %s)" % self.pos_info)
7334
7335                c.put(" shared(%s)" % ', '.join(shared_vars))
7336
7337    def cleanup_temps(self, code):
7338        # Now clean up any memoryview slice and object temporaries
7339        if self.is_parallel and not self.is_nested_prange:
7340            code.putln("/* Clean up any temporaries */")
7341            for temp, type in self.temps:
7342                if type.is_memoryviewslice:
7343                    code.put_xdecref_memoryviewslice(temp, have_gil=False)
7344                elif type.is_pyobject:
7345                    code.put_xdecref(temp, type)
7346                    code.putln("%s = NULL;" % temp)
7347
7348    def setup_parallel_control_flow_block(self, code):
7349        """
7350        Sets up a block that surrounds the parallel block to determine
7351        how the parallel section was exited. Any kind of return is
7352        trapped (break, continue, return, exceptions). This is the idea:
7353
7354        {
7355            int why = 0;
7356
7357            #pragma omp parallel
7358            {
7359                return # -> goto new_return_label;
7360                goto end_parallel;
7361
7362            new_return_label:
7363                why = 3;
7364                goto end_parallel;
7365
7366            end_parallel:;
7367                #pragma omp flush(why) # we need to flush for every iteration
7368            }
7369
7370            if (why == 3)
7371                goto old_return_label;
7372        }
7373        """
7374        self.old_loop_labels = code.new_loop_labels()
7375        self.old_error_label = code.new_error_label()
7376        self.old_return_label = code.return_label
7377        code.return_label = code.new_label(name="return")
7378
7379        code.begin_block() # parallel control flow block
7380        self.begin_of_parallel_control_block_point = code.insertion_point()
7381        self.begin_of_parallel_control_block_point_after_decls = code.insertion_point()
7382
7383        self.undef_builtin_expect_apple_gcc_bug(code)
7384
7385    def begin_parallel_block(self, code):
7386        """
7387        Each OpenMP thread in a parallel section that contains a with gil block
7388        must have the thread-state initialized. The call to
7389        PyGILState_Release() then deallocates our threadstate. If we wouldn't
7390        do this, each with gil block would allocate and deallocate one, thereby
7391        losing exception information before it can be saved before leaving the
7392        parallel section.
7393        """
7394        self.begin_of_parallel_block = code.insertion_point()
7395
7396    def end_parallel_block(self, code):
7397        """
7398        To ensure all OpenMP threads have thread states, we ensure the GIL
7399        in each thread (which creates a thread state if it doesn't exist),
7400        after which we release the GIL.
7401        On exit, reacquire the GIL and release the thread state.
7402
7403        If compiled without OpenMP support (at the C level), then we still have
7404        to acquire the GIL to decref any object temporaries.
7405        """
7406        if self.error_label_used:
7407            begin_code = self.begin_of_parallel_block
7408            end_code = code
7409
7410            begin_code.putln("#ifdef _OPENMP")
7411            begin_code.put_ensure_gil(declare_gilstate=True)
7412            begin_code.putln("Py_BEGIN_ALLOW_THREADS")
7413            begin_code.putln("#endif /* _OPENMP */")
7414
7415            end_code.putln("#ifdef _OPENMP")
7416            end_code.putln("Py_END_ALLOW_THREADS")
7417            end_code.putln("#else")
7418            end_code.put_safe("{\n")
7419            end_code.put_ensure_gil()
7420            end_code.putln("#endif /* _OPENMP */")
7421            self.cleanup_temps(end_code)
7422            end_code.put_release_ensured_gil()
7423            end_code.putln("#ifndef _OPENMP")
7424            end_code.put_safe("}\n")
7425            end_code.putln("#endif /* _OPENMP */")
7426
7427    def trap_parallel_exit(self, code, should_flush=False):
7428        """
7429        Trap any kind of return inside a parallel construct. 'should_flush'
7430        indicates whether the variable should be flushed, which is needed by
7431        prange to skip the loop. It also indicates whether we need to register
7432        a continue (we need this for parallel blocks, but not for prange
7433        loops, as it is a direct jump there).
7434
7435        It uses the same mechanism as try/finally:
7436            1 continue
7437            2 break
7438            3 return
7439            4 error
7440        """
7441        save_lastprivates_label = code.new_label()
7442        dont_return_label = code.new_label()
7443
7444        self.any_label_used = False
7445        self.breaking_label_used = False
7446        self.error_label_used = False
7447
7448        self.parallel_private_temps = []
7449
7450        all_labels = code.get_all_labels()
7451
7452        # Figure this out before starting to generate any code
7453        for label in all_labels:
7454            if code.label_used(label):
7455                self.breaking_label_used = (self.breaking_label_used or
7456                                            label != code.continue_label)
7457                self.any_label_used = True
7458
7459        if self.any_label_used:
7460            code.put_goto(dont_return_label)
7461
7462        for i, label in enumerate(all_labels):
7463            if not code.label_used(label):
7464                continue
7465
7466            is_continue_label = label == code.continue_label
7467
7468            code.put_label(label)
7469
7470            if not (should_flush and is_continue_label):
7471                if label == code.error_label:
7472                    self.error_label_used = True
7473                    self.fetch_parallel_exception(code)
7474
7475                code.putln("%s = %d;" % (Naming.parallel_why, i + 1))
7476
7477            if (self.breaking_label_used and self.is_prange and not
7478                    is_continue_label):
7479                code.put_goto(save_lastprivates_label)
7480            else:
7481                code.put_goto(dont_return_label)
7482
7483        if self.any_label_used:
7484            if self.is_prange and self.breaking_label_used:
7485                # Don't rely on lastprivate, save our lastprivates
7486                code.put_label(save_lastprivates_label)
7487                self.save_parallel_vars(code)
7488
7489            code.put_label(dont_return_label)
7490
7491            if should_flush and self.breaking_label_used:
7492                code.putln_openmp("#pragma omp flush(%s)" % Naming.parallel_why)
7493
7494    def save_parallel_vars(self, code):
7495        """
7496        The following shenanigans are instated when we break, return or
7497        propagate errors from a prange. In this case we cannot rely on
7498        lastprivate() to do its job, as no iterations may have executed yet
7499        in the last thread, leaving the values undefined. It is most likely
7500        that the breaking thread has well-defined values of the lastprivate
7501        variables, so we keep those values.
7502        """
7503        section_name = ("__pyx_parallel_lastprivates%d" %
7504                                            self.critical_section_counter)
7505        code.putln_openmp("#pragma omp critical(%s)" % section_name)
7506        ParallelStatNode.critical_section_counter += 1
7507
7508        code.begin_block() # begin critical section
7509
7510        c = self.begin_of_parallel_control_block_point
7511
7512        temp_count = 0
7513        for entry, (op, lastprivate) in self.privates.iteritems():
7514            if not lastprivate or entry.type.is_pyobject:
7515                continue
7516
7517            type_decl = entry.type.declaration_code("")
7518            temp_cname = "__pyx_parallel_temp%d" % temp_count
7519            private_cname = entry.cname
7520
7521            temp_count += 1
7522
7523            invalid_value = entry.type.invalid_value()
7524            if invalid_value:
7525                init = ' = ' + invalid_value
7526            else:
7527                init = ''
7528            # Declare the parallel private in the outer block
7529            c.putln("%s %s%s;" % (type_decl, temp_cname, init))
7530
7531            # Initialize before escaping
7532            code.putln("%s = %s;" % (temp_cname, private_cname))
7533
7534            self.parallel_private_temps.append((temp_cname, private_cname))
7535
7536        code.end_block() # end critical section
7537
7538    def fetch_parallel_exception(self, code):
7539        """
7540        As each OpenMP thread may raise an exception, we need to fetch that
7541        exception from the threadstate and save it for after the parallel
7542        section where it can be re-raised in the master thread.
7543
7544        Although it would seem that __pyx_filename, __pyx_lineno and
7545        __pyx_clineno are only assigned to under exception conditions (i.e.,
7546        when we have the GIL), and thus should be allowed to be shared without
7547        any race condition, they are in fact subject to the same race
7548        conditions that they were previously when they were global variables
7549        and functions were allowed to release the GIL:
7550
7551            thread A                thread B
7552                acquire
7553                set lineno
7554                release
7555                                        acquire
7556                                        set lineno
7557                                        release
7558                acquire
7559                fetch exception
7560                release
7561                                        skip the fetch
7562
7563                deallocate threadstate  deallocate threadstate
7564        """
7565        code.begin_block()
7566        code.put_ensure_gil(declare_gilstate=True)
7567
7568        code.putln_openmp("#pragma omp flush(%s)" % Naming.parallel_exc_type)
7569        code.putln(
7570            "if (!%s) {" % Naming.parallel_exc_type)
7571
7572        code.putln("__Pyx_ErrFetch(&%s, &%s, &%s);" % self.parallel_exc)
7573        pos_info = chain(*zip(self.parallel_pos_info, self.pos_info))
7574        code.funcstate.uses_error_indicator = True
7575        code.putln("%s = %s; %s = %s; %s = %s;" % tuple(pos_info))
7576        code.put_gotref(Naming.parallel_exc_type)
7577
7578        code.putln(
7579            "}")
7580
7581        code.put_release_ensured_gil()
7582        code.end_block()
7583
7584    def restore_parallel_exception(self, code):
7585        "Re-raise a parallel exception"
7586        code.begin_block()
7587        code.put_ensure_gil(declare_gilstate=True)
7588
7589        code.put_giveref(Naming.parallel_exc_type)
7590        code.putln("__Pyx_ErrRestore(%s, %s, %s);" % self.parallel_exc)
7591        pos_info = chain(*zip(self.pos_info, self.parallel_pos_info))
7592        code.putln("%s = %s; %s = %s; %s = %s;" % tuple(pos_info))
7593
7594        code.put_release_ensured_gil()
7595        code.end_block()
7596
7597    def restore_labels(self, code):
7598        """
7599        Restore all old labels. Call this before the 'else' clause to for
7600        loops and always before ending the parallel control flow block.
7601        """
7602        code.set_all_labels(self.old_loop_labels + (self.old_return_label,
7603                                                    self.old_error_label))
7604
7605    def end_parallel_control_flow_block(self, code,
7606                                        break_=False, continue_=False):
7607        """
7608        This ends the parallel control flow block and based on how the parallel
7609        section was exited, takes the corresponding action. The break_ and
7610        continue_ parameters indicate whether these should be propagated
7611        outwards:
7612
7613            for i in prange(...):
7614                with cython.parallel.parallel():
7615                    continue
7616
7617        Here break should be trapped in the parallel block, and propagated to
7618        the for loop.
7619        """
7620        c = self.begin_of_parallel_control_block_point
7621
7622        # Firstly, always prefer errors over returning, continue or break
7623        if self.error_label_used:
7624            c.putln("const char *%s = NULL; int %s = 0, %s = 0;" %
7625                                                self.parallel_pos_info)
7626
7627            c.putln("PyObject *%s = NULL, *%s = NULL, *%s = NULL;" %
7628                                                        self.parallel_exc)
7629
7630            code.putln(
7631                "if (%s) {" % Naming.parallel_exc_type)
7632            code.putln("/* This may have been overridden by a continue, "
7633                       "break or return in another thread. Prefer the error. */")
7634            code.putln("%s = 4;" % Naming.parallel_why)
7635            code.putln(
7636                "}")
7637
7638        if continue_:
7639            any_label_used = self.any_label_used
7640        else:
7641            any_label_used = self.breaking_label_used
7642
7643        if any_label_used:
7644            # __pyx_parallel_why is used, declare and initialize
7645            c.putln("int %s;" % Naming.parallel_why)
7646            c.putln("%s = 0;" % Naming.parallel_why)
7647
7648            code.putln(
7649                "if (%s) {" % Naming.parallel_why)
7650
7651            for temp_cname, private_cname in self.parallel_private_temps:
7652                code.putln("%s = %s;" % (private_cname, temp_cname))
7653
7654            code.putln("switch (%s) {" % Naming.parallel_why)
7655            if continue_:
7656                code.put("    case 1: ")
7657                code.put_goto(code.continue_label)
7658
7659            if break_:
7660                code.put("    case 2: ")
7661                code.put_goto(code.break_label)
7662
7663            code.put("    case 3: ")
7664            code.put_goto(code.return_label)
7665
7666            if self.error_label_used:
7667                code.globalstate.use_utility_code(restore_exception_utility_code)
7668                code.putln("    case 4:")
7669                self.restore_parallel_exception(code)
7670                code.put_goto(code.error_label)
7671
7672            code.putln("}") # end switch
7673            code.putln(
7674                "}") # end if
7675
7676        code.end_block() # end parallel control flow block
7677        self.redef_builtin_expect_apple_gcc_bug(code)
7678
7679    # FIXME: improve with version number for OS X Lion
7680    buggy_platform_macro_condition = "(defined(__APPLE__) || defined(__OSX__))"
7681    have_expect_condition = "(defined(__GNUC__) && " \
7682                             "(__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))))"
7683    redef_condition = "(%s && %s)" % (buggy_platform_macro_condition, have_expect_condition)
7684
7685    def undef_builtin_expect_apple_gcc_bug(self, code):
7686        """
7687        A bug on OS X Lion disallows __builtin_expect macros. This code avoids them
7688        """
7689        if not self.parent:
7690            code.undef_builtin_expect(self.redef_condition)
7691
7692    def redef_builtin_expect_apple_gcc_bug(self, code):
7693        if not self.parent:
7694            code.redef_builtin_expect(self.redef_condition)
7695
7696
7697class ParallelWithBlockNode(ParallelStatNode):
7698    """
7699    This node represents a 'with cython.parallel.parallel():' block
7700    """
7701
7702    valid_keyword_arguments = ['num_threads']
7703
7704    num_threads = None
7705
7706    def analyse_declarations(self, env):
7707        super(ParallelWithBlockNode, self).analyse_declarations(env)
7708        if self.args:
7709            error(self.pos, "cython.parallel.parallel() does not take "
7710                            "positional arguments")
7711
7712    def generate_execution_code(self, code):
7713        self.declare_closure_privates(code)
7714        self.setup_parallel_control_flow_block(code)
7715
7716        code.putln("#ifdef _OPENMP")
7717        code.put("#pragma omp parallel ")
7718
7719        if self.privates:
7720            privates = [e.cname for e in self.privates
7721                                    if not e.type.is_pyobject]
7722            code.put('private(%s)' % ', '.join(privates))
7723
7724        self.privatization_insertion_point = code.insertion_point()
7725        self.put_num_threads(code)
7726        code.putln("")
7727
7728        code.putln("#endif /* _OPENMP */")
7729
7730        code.begin_block() # parallel block
7731        self.begin_parallel_block(code)
7732        self.initialize_privates_to_nan(code)
7733        code.funcstate.start_collecting_temps()
7734        self.body.generate_execution_code(code)
7735        self.trap_parallel_exit(code)
7736        self.privatize_temps(code)
7737        self.end_parallel_block(code)
7738        code.end_block() # end parallel block
7739
7740        continue_ = code.label_used(code.continue_label)
7741        break_ = code.label_used(code.break_label)
7742
7743        self.restore_labels(code)
7744        self.end_parallel_control_flow_block(code, break_=break_,
7745                                             continue_=continue_)
7746        self.release_closure_privates(code)
7747
7748
7749class ParallelRangeNode(ParallelStatNode):
7750    """
7751    This node represents a 'for i in cython.parallel.prange():' construct.
7752
7753    target       NameNode       the target iteration variable
7754    else_clause  Node or None   the else clause of this loop
7755    """
7756
7757    child_attrs = ['body', 'target', 'else_clause', 'args', 'num_threads',
7758                   'chunksize']
7759
7760    body = target = else_clause = args = None
7761
7762    start = stop = step = None
7763
7764    is_prange = True
7765
7766    nogil = None
7767    schedule = None
7768
7769    valid_keyword_arguments = ['schedule', 'nogil', 'num_threads', 'chunksize']
7770
7771    def __init__(self, pos, **kwds):
7772        super(ParallelRangeNode, self).__init__(pos, **kwds)
7773        # Pretend to be a ForInStatNode for control flow analysis
7774        self.iterator = PassStatNode(pos)
7775
7776    def analyse_declarations(self, env):
7777        super(ParallelRangeNode, self).analyse_declarations(env)
7778        self.target.analyse_target_declaration(env)
7779        if self.else_clause is not None:
7780            self.else_clause.analyse_declarations(env)
7781
7782        if not self.args or len(self.args) > 3:
7783            error(self.pos, "Invalid number of positional arguments to prange")
7784            return
7785
7786        if len(self.args) == 1:
7787            self.stop, = self.args
7788        elif len(self.args) == 2:
7789            self.start, self.stop = self.args
7790        else:
7791            self.start, self.stop, self.step = self.args
7792
7793        if hasattr(self.schedule, 'decode'):
7794            self.schedule = self.schedule.decode('ascii')
7795
7796        if self.schedule not in (None, 'static', 'dynamic', 'guided',
7797                                 'runtime'):
7798            error(self.pos, "Invalid schedule argument to prange: %s" %
7799                                                        (self.schedule,))
7800
7801    def analyse_expressions(self, env):
7802        was_nogil = env.nogil
7803        if self.nogil:
7804            env.nogil = True
7805
7806        if self.target is None:
7807            error(self.pos, "prange() can only be used as part of a for loop")
7808            return self
7809
7810        self.target = self.target.analyse_target_types(env)
7811
7812        if not self.target.type.is_numeric:
7813            # Not a valid type, assume one for now anyway
7814
7815            if not self.target.type.is_pyobject:
7816                # nogil_check will catch the is_pyobject case
7817                error(self.target.pos,
7818                      "Must be of numeric type, not %s" % self.target.type)
7819
7820            self.index_type = PyrexTypes.c_py_ssize_t_type
7821        else:
7822            self.index_type = self.target.type
7823            if not self.index_type.signed:
7824                warning(self.target.pos,
7825                        "Unsigned index type not allowed before OpenMP 3.0",
7826                        level=2)
7827
7828        # Setup start, stop and step, allocating temps if needed
7829        self.names = 'start', 'stop', 'step'
7830        start_stop_step = self.start, self.stop, self.step
7831
7832        for node, name in zip(start_stop_step, self.names):
7833            if node is not None:
7834                node.analyse_types(env)
7835                if not node.type.is_numeric:
7836                    error(node.pos, "%s argument must be numeric" % name)
7837                    continue
7838
7839                if not node.is_literal:
7840                    node = node.coerce_to_temp(env)
7841                    setattr(self, name, node)
7842
7843                # As we range from 0 to nsteps, computing the index along the
7844                # way, we need a fitting type for 'i' and 'nsteps'
7845                self.index_type = PyrexTypes.widest_numeric_type(
7846                                        self.index_type, node.type)
7847
7848        if self.else_clause is not None:
7849            self.else_clause = self.else_clause.analyse_expressions(env)
7850
7851        # Although not actually an assignment in this scope, it should be
7852        # treated as such to ensure it is unpacked if a closure temp, and to
7853        # ensure lastprivate behaviour and propagation. If the target index is
7854        # not a NameNode, it won't have an entry, and an error was issued by
7855        # ParallelRangeTransform
7856        if hasattr(self.target, 'entry'):
7857            self.assignments[self.target.entry] = self.target.pos, None
7858
7859        node = super(ParallelRangeNode, self).analyse_expressions(env)
7860
7861        if node.chunksize:
7862            if not node.schedule:
7863                error(node.chunksize.pos,
7864                      "Must provide schedule with chunksize")
7865            elif node.schedule == 'runtime':
7866                error(node.chunksize.pos,
7867                      "Chunksize not valid for the schedule runtime")
7868            elif (node.chunksize.type.is_int and
7869                  node.chunksize.is_literal and
7870                  node.chunksize.compile_time_value(env) <= 0):
7871                error(node.chunksize.pos, "Chunksize must not be negative")
7872
7873            node.chunksize = node.chunksize.coerce_to(
7874                PyrexTypes.c_int_type, env).coerce_to_temp(env)
7875
7876        if node.nogil:
7877            env.nogil = was_nogil
7878
7879        node.is_nested_prange = node.parent and node.parent.is_prange
7880        if node.is_nested_prange:
7881            parent = node
7882            while parent.parent and parent.parent.is_prange:
7883                parent = parent.parent
7884
7885            parent.assignments.update(node.assignments)
7886            parent.privates.update(node.privates)
7887            parent.assigned_nodes.extend(node.assigned_nodes)
7888        return node
7889
7890    def nogil_check(self, env):
7891        names = 'start', 'stop', 'step', 'target'
7892        nodes = self.start, self.stop, self.step, self.target
7893        for name, node in zip(names, nodes):
7894            if node is not None and node.type.is_pyobject:
7895                error(node.pos, "%s may not be a Python object "
7896                                "as we don't have the GIL" % name)
7897
7898    def generate_execution_code(self, code):
7899        """
7900        Generate code in the following steps
7901
7902            1)  copy any closure variables determined thread-private
7903                into temporaries
7904
7905            2)  allocate temps for start, stop and step
7906
7907            3)  generate a loop that calculates the total number of steps,
7908                which then computes the target iteration variable for every step:
7909
7910                    for i in prange(start, stop, step):
7911                        ...
7912
7913                becomes
7914
7915                    nsteps = (stop - start) / step;
7916                    i = start;
7917
7918                    #pragma omp parallel for lastprivate(i)
7919                    for (temp = 0; temp < nsteps; temp++) {
7920                        i = start + step * temp;
7921                        ...
7922                    }
7923
7924                Note that accumulation of 'i' would have a data dependency
7925                between iterations.
7926
7927                Also, you can't do this
7928
7929                    for (i = start; i < stop; i += step)
7930                        ...
7931
7932                as the '<' operator should become '>' for descending loops.
7933                'for i from x < i < y:' does not suffer from this problem
7934                as the relational operator is known at compile time!
7935
7936            4) release our temps and write back any private closure variables
7937        """
7938        self.declare_closure_privates(code)
7939
7940        # This can only be a NameNode
7941        target_index_cname = self.target.entry.cname
7942
7943        # This will be used as the dict to format our code strings, holding
7944        # the start, stop , step, temps and target cnames
7945        fmt_dict = {
7946            'target': target_index_cname,
7947        }
7948
7949        # Setup start, stop and step, allocating temps if needed
7950        start_stop_step = self.start, self.stop, self.step
7951        defaults = '0', '0', '1'
7952        for node, name, default in zip(start_stop_step, self.names, defaults):
7953            if node is None:
7954                result = default
7955            elif node.is_literal:
7956                result = node.get_constant_c_result_code()
7957            else:
7958                node.generate_evaluation_code(code)
7959                result = node.result()
7960
7961            fmt_dict[name] = result
7962
7963        fmt_dict['i'] = code.funcstate.allocate_temp(self.index_type, False)
7964        fmt_dict['nsteps'] = code.funcstate.allocate_temp(self.index_type, False)
7965
7966        # TODO: check if the step is 0 and if so, raise an exception in a
7967        # 'with gil' block. For now, just abort
7968        code.putln("if (%(step)s == 0) abort();" % fmt_dict)
7969
7970        self.setup_parallel_control_flow_block(code) # parallel control flow block
7971
7972        self.control_flow_var_code_point = code.insertion_point()
7973
7974        # Note: nsteps is private in an outer scope if present
7975        code.putln("%(nsteps)s = (%(stop)s - %(start)s) / %(step)s;" % fmt_dict)
7976
7977        # The target iteration variable might not be initialized, do it only if
7978        # we are executing at least 1 iteration, otherwise we should leave the
7979        # target unaffected. The target iteration variable is firstprivate to
7980        # shut up compiler warnings caused by lastprivate, as the compiler
7981        # erroneously believes that nsteps may be <= 0, leaving the private
7982        # target index uninitialized
7983        code.putln("if (%(nsteps)s > 0)" % fmt_dict)
7984        code.begin_block() # if block
7985        self.generate_loop(code, fmt_dict)
7986        code.end_block() # end if block
7987
7988        self.restore_labels(code)
7989
7990        if self.else_clause:
7991            if self.breaking_label_used:
7992                code.put("if (%s < 2)" % Naming.parallel_why)
7993
7994            code.begin_block() # else block
7995            code.putln("/* else */")
7996            self.else_clause.generate_execution_code(code)
7997            code.end_block() # end else block
7998
7999        # ------ cleanup ------
8000        self.end_parallel_control_flow_block(code) # end parallel control flow block
8001
8002        # And finally, release our privates and write back any closure
8003        # variables
8004        for temp in start_stop_step:
8005            if temp is not None:
8006                temp.generate_disposal_code(code)
8007                temp.free_temps(code)
8008
8009        code.funcstate.release_temp(fmt_dict['i'])
8010        code.funcstate.release_temp(fmt_dict['nsteps'])
8011
8012        self.release_closure_privates(code)
8013
8014    def generate_loop(self, code, fmt_dict):
8015        if self.is_nested_prange:
8016            code.putln("#if 0")
8017        else:
8018            code.putln("#ifdef _OPENMP")
8019
8020        if not self.is_parallel:
8021            code.put("#pragma omp for")
8022            self.privatization_insertion_point = code.insertion_point()
8023            reduction_codepoint = self.parent.privatization_insertion_point
8024        else:
8025            code.put("#pragma omp parallel")
8026            self.privatization_insertion_point = code.insertion_point()
8027            reduction_codepoint = self.privatization_insertion_point
8028            code.putln("")
8029            code.putln("#endif /* _OPENMP */")
8030
8031            code.begin_block() # pragma omp parallel begin block
8032
8033            # Initialize the GIL if needed for this thread
8034            self.begin_parallel_block(code)
8035
8036            if self.is_nested_prange:
8037                code.putln("#if 0")
8038            else:
8039                code.putln("#ifdef _OPENMP")
8040            code.put("#pragma omp for")
8041
8042        for entry, (op, lastprivate) in self.privates.iteritems():
8043            # Don't declare the index variable as a reduction
8044            if op and op in "+*-&^|" and entry != self.target.entry:
8045                if entry.type.is_pyobject:
8046                    error(self.pos, "Python objects cannot be reductions")
8047                else:
8048                    #code.put(" reduction(%s:%s)" % (op, entry.cname))
8049                    # This is the only way reductions + nesting works in gcc4.5
8050                    reduction_codepoint.put(
8051                                " reduction(%s:%s)" % (op, entry.cname))
8052            else:
8053                if entry == self.target.entry:
8054                    code.put(" firstprivate(%s)" % entry.cname)
8055                    code.put(" lastprivate(%s)" % entry.cname)
8056                    continue
8057
8058                if not entry.type.is_pyobject:
8059                    if lastprivate:
8060                        private = 'lastprivate'
8061                    else:
8062                        private = 'private'
8063
8064                    code.put(" %s(%s)" % (private, entry.cname))
8065
8066        if self.schedule:
8067            if self.chunksize:
8068                chunksize = ", %s" % self.evaluate_before_block(code,
8069                                                                self.chunksize)
8070            else:
8071                chunksize = ""
8072
8073            code.put(" schedule(%s%s)" % (self.schedule, chunksize))
8074
8075        self.put_num_threads(reduction_codepoint)
8076
8077        code.putln("")
8078        code.putln("#endif /* _OPENMP */")
8079
8080        code.put("for (%(i)s = 0; %(i)s < %(nsteps)s; %(i)s++)" % fmt_dict)
8081        code.begin_block() # for loop block
8082
8083        guard_around_body_codepoint = code.insertion_point()
8084
8085        # Start if guard block around the body. This may be unnecessary, but
8086        # at least it doesn't spoil indentation
8087        code.begin_block()
8088
8089        code.putln("%(target)s = %(start)s + %(step)s * %(i)s;" % fmt_dict)
8090        self.initialize_privates_to_nan(code, exclude=self.target.entry)
8091
8092        if self.is_parallel:
8093            code.funcstate.start_collecting_temps()
8094
8095        self.body.generate_execution_code(code)
8096        self.trap_parallel_exit(code, should_flush=True)
8097        self.privatize_temps(code)
8098
8099        if self.breaking_label_used:
8100            # Put a guard around the loop body in case return, break or
8101            # exceptions might be used
8102            guard_around_body_codepoint.putln("if (%s < 2)" % Naming.parallel_why)
8103
8104        code.end_block() # end guard around loop body
8105        code.end_block() # end for loop block
8106
8107        if self.is_parallel:
8108            # Release the GIL and deallocate the thread state
8109            self.end_parallel_block(code)
8110            code.end_block() # pragma omp parallel end block
8111
8112
8113class CnameDecoratorNode(StatNode):
8114    """
8115    This node is for the cname decorator in CythonUtilityCode:
8116
8117        @cname('the_cname')
8118        cdef func(...):
8119            ...
8120
8121    In case of a cdef class the cname specifies the objstruct_cname.
8122
8123    node        the node to which the cname decorator is applied
8124    cname       the cname the node should get
8125    """
8126
8127    child_attrs = ['node']
8128
8129    def analyse_declarations(self, env):
8130        self.node.analyse_declarations(env)
8131
8132        node = self.node
8133        if isinstance(node, CompilerDirectivesNode):
8134            node = node.body.stats[0]
8135
8136        self.is_function = isinstance(node, FuncDefNode)
8137        is_struct_or_enum = isinstance(node, (CStructOrUnionDefNode,
8138                                                   CEnumDefNode))
8139        e = node.entry
8140
8141        if self.is_function:
8142            e.cname = self.cname
8143            e.func_cname = self.cname
8144            e.used = True
8145            if e.pyfunc_cname and '.' in e.pyfunc_cname:
8146                e.pyfunc_cname = self.mangle(e.pyfunc_cname)
8147        elif is_struct_or_enum:
8148            e.cname = e.type.cname = self.cname
8149        else:
8150            scope = node.scope
8151
8152            e.cname = self.cname
8153            e.type.objstruct_cname = self.cname + '_obj'
8154            e.type.typeobj_cname = Naming.typeobj_prefix + self.cname
8155            e.type.typeptr_cname = self.cname + '_type'
8156            e.type.scope.namespace_cname = e.type.typeptr_cname
8157
8158            e.as_variable.cname = py_object_type.cast_code(e.type.typeptr_cname)
8159
8160            scope.scope_prefix = self.cname + "_"
8161
8162            for name, entry in scope.entries.iteritems():
8163                if entry.func_cname:
8164                    entry.func_cname = self.mangle(entry.cname)
8165                if entry.pyfunc_cname:
8166                    entry.pyfunc_cname = self.mangle(entry.pyfunc_cname)
8167
8168    def mangle(self, cname):
8169        if '.' in cname:
8170            # remove __pyx_base from func_cname
8171            cname = cname.split('.')[-1]
8172        return '%s_%s' % (self.cname, cname)
8173
8174    def analyse_expressions(self, env):
8175        self.node = self.node.analyse_expressions(env)
8176        return self
8177
8178    def generate_function_definitions(self, env, code):
8179        "Ensure a prototype for every @cname method in the right place"
8180        if self.is_function and env.is_c_class_scope:
8181            # method in cdef class, generate a prototype in the header
8182            h_code = code.globalstate['utility_code_proto']
8183
8184            if isinstance(self.node, DefNode):
8185                self.node.generate_function_header(
8186                            h_code, with_pymethdef=False, proto_only=True)
8187            else:
8188                import ModuleNode
8189                entry = self.node.entry
8190                cname = entry.cname
8191                entry.cname = entry.func_cname
8192
8193                ModuleNode.generate_cfunction_declaration(
8194                        entry,
8195                        env.global_scope(),
8196                        h_code,
8197                        definition=True)
8198
8199                entry.cname = cname
8200
8201        self.node.generate_function_definitions(env, code)
8202
8203    def generate_execution_code(self, code):
8204        self.node.generate_execution_code(code)
8205
8206
8207#------------------------------------------------------------------------------------
8208#
8209#  Runtime support code
8210#
8211#------------------------------------------------------------------------------------
8212
8213if Options.gcc_branch_hints:
8214    branch_prediction_macros = """
8215/* Test for GCC > 2.95 */
8216#if defined(__GNUC__) \
8217    && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)))
8218  #define likely(x)   __builtin_expect(!!(x), 1)
8219  #define unlikely(x) __builtin_expect(!!(x), 0)
8220#else /* !__GNUC__ or GCC < 2.95 */
8221  #define likely(x)   (x)
8222  #define unlikely(x) (x)
8223#endif /* __GNUC__ */
8224"""
8225else:
8226    branch_prediction_macros = """
8227#define likely(x)   (x)
8228#define unlikely(x) (x)
8229"""
8230
8231#------------------------------------------------------------------------------------
8232
8233printing_utility_code = UtilityCode.load_cached("Print", "Printing.c")
8234printing_one_utility_code = UtilityCode.load_cached("PrintOne", "Printing.c")
8235
8236#------------------------------------------------------------------------------------
8237
8238# Exception raising code
8239#
8240# Exceptions are raised by __Pyx_Raise() and stored as plain
8241# type/value/tb in PyThreadState->curexc_*.  When being caught by an
8242# 'except' statement, curexc_* is moved over to exc_* by
8243# __Pyx_GetException()
8244
8245restore_exception_utility_code = UtilityCode.load_cached("PyErrFetchRestore", "Exceptions.c")
8246raise_utility_code = UtilityCode.load_cached("RaiseException", "Exceptions.c")
8247get_exception_utility_code = UtilityCode.load_cached("GetException", "Exceptions.c")
8248swap_exception_utility_code = UtilityCode.load_cached("SwapException", "Exceptions.c")
8249reset_exception_utility_code = UtilityCode.load_cached("SaveResetException", "Exceptions.c")
8250traceback_utility_code = UtilityCode.load_cached("AddTraceback", "Exceptions.c")
8251
8252#------------------------------------------------------------------------------------
8253
8254get_exception_tuple_utility_code = UtilityCode(proto="""
8255static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
8256""",
8257# I doubt that calling __Pyx_GetException() here is correct as it moves
8258# the exception from tstate->curexc_* to tstate->exc_*, which prevents
8259# exception handlers later on from receiving it.
8260impl = """
8261static PyObject *__Pyx_GetExceptionTuple(void) {
8262    PyObject *type = NULL, *value = NULL, *tb = NULL;
8263    if (__Pyx_GetException(&type, &value, &tb) == 0) {
8264        PyObject* exc_info = PyTuple_New(3);
8265        if (exc_info) {
8266            Py_INCREF(type);
8267            Py_INCREF(value);
8268            Py_INCREF(tb);
8269            PyTuple_SET_ITEM(exc_info, 0, type);
8270            PyTuple_SET_ITEM(exc_info, 1, value);
8271            PyTuple_SET_ITEM(exc_info, 2, tb);
8272            return exc_info;
8273        }
8274    }
8275    return NULL;
8276}
8277""",
8278requires=[get_exception_utility_code])
8279