15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#   Parse tree nodes
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import cython
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)cython.declare(sys=object, os=object, copy=object,
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               Builtin=object, error=object, warning=object, Naming=object, PyrexTypes=object,
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               py_object_type=object, ModuleScope=object, LocalScope=object, ClosureScope=object,
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               StructOrUnionScope=object, PyClassScope=object,
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               CppClassScope=object, UtilityCode=object, EncodedString=object,
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               absolute_path_length=cython.Py_ssize_t)
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import sys, os, copy
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from itertools import chain
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import Builtin
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Errors import error, warning, InternalError, CompileError
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import Naming
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import PyrexTypes
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import TypeSlots
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from PyrexTypes import py_object_type, error_type
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Symtab import (ModuleScope, LocalScope, ClosureScope,
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    StructOrUnionScope, PyClassScope, CppClassScope, TemplateScope)
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Code import UtilityCode
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from StringEncoding import EncodedString, escape_byte_string, split_string_literal
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import Options
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import DebugFlags
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Cython.Utils import cached_function
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)absolute_path_length = 0
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def relative_position(pos):
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    We embed the relative filename in the generated C file, since we
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    don't want to have to regenerate and compile all the source code
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    whenever the Python install directory moves (which could happen,
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    e.g,. when distributing binaries.)
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    INPUT:
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        a position tuple -- (absolute filename, line number column position)
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OUTPUT:
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        relative filename
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        line number
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    AUTHOR: William Stein
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    global absolute_path_length
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if absolute_path_length==0:
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        absolute_path_length = len(os.path.abspath(os.getcwd()))
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def embed_position(pos, docstring):
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if not Options.embed_pos_in_docstring:
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return docstring
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if docstring is None:
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # unicode string
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return EncodedString(pos_line)
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # make sure we can encode the filename in the docstring encoding
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # otherwise make the docstring a unicode string
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    encoding = docstring.encoding
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if encoding is not None:
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        try:
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pos_line.encode(encoding)
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        except UnicodeEncodeError:
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            encoding = None
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if not docstring:
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # reuse the string encoding of the original docstring
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        doc = EncodedString(pos_line)
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    else:
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        doc = EncodedString(pos_line + u'\n' + docstring)
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    doc.encoding = encoding
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return doc
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def write_func_call(func, codewriter_class):
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def f(*args, **kwds):
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if len(args) > 1 and isinstance(args[1], codewriter_class):
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # here we annotate the code with this function call
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # but only if new code is generated
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node, code = args[:2]
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            marker = '                    /* %s -> %s.%s %s */' % (
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    ' ' * code.call_level,
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node.__class__.__name__,
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    func.__name__,
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node.pos[1:])
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pristine = code.buffer.stream.tell()
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(marker)
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            start = code.buffer.stream.tell()
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.call_level += 4
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            res = func(*args, **kwds)
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.call_level -= 4
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if start == code.buffer.stream.tell():
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.buffer.stream.seek(pristine)
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                marker = marker.replace('->', '<-')
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln(marker)
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return res
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return func(*args, **kwds)
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return f
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class VerboseCodeWriter(type):
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Set this as a metaclass to trace function calls in code.
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # This slows down code generation and makes much larger files.
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __new__(cls, name, bases, attrs):
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        from types import FunctionType
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        from Code import CCodeWriter
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        attrs = dict(attrs)
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for mname, m in attrs.items():
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if isinstance(m, FunctionType):
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                attrs[mname] = write_func_call(m, CCodeWriter)
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return super(VerboseCodeWriter, cls).__new__(cls, name, bases, attrs)
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CheckAnalysers(type):
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """Metaclass to check that type analysis functions return a node.
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    methods = set(['analyse_types',
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   'analyse_expressions',
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   'analyse_target_types'])
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __new__(cls, name, bases, attrs):
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        from types import FunctionType
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        def check(name, func):
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            def call(*args, **kwargs):
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                retval = func(*args, **kwargs)
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if retval is None:
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    print name, args, kwargs
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return retval
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return call
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        attrs = dict(attrs)
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for mname, m in attrs.items():
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if isinstance(m, FunctionType) and mname in cls.methods:
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                attrs[mname] = check(mname, m)
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return super(CheckAnalysers, cls).__new__(cls, name, bases, attrs)
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class Node(object):
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  pos         (string, int, int)   Source file position
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  is_name     boolean              Is a NameNode
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  is_literal  boolean              Is a ConstNode
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #__metaclass__ = CheckAnalysers
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if DebugFlags.debug_trace_code_generation:
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        __metaclass__ = VerboseCodeWriter
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_name = 0
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_none = 0
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_nonecheck = 0
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_literal = 0
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_terminator = 0
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    temps = None
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # All descendants should set child_attrs to a list of the attributes
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # containing nodes considered "children" in the tree. Each such attribute
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # can either contain a single node or a list of nodes. See Visitor.py.
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = None
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    cf_state = None
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # This may be an additional (or 'actual') type that will be checked when
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # this node is coerced to another type. This could be useful to set when
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # the actual type to which it can coerce is known, but you want to leave
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # the type a py_object_type
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    coercion_type = None
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, pos, **kw):
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.pos = pos
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.__dict__.update(kw)
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gil_message = "Operation"
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    nogil_check = None
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def gil_error(self, env=None):
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        error(self.pos, "%s not allowed without gil" % self.gil_message)
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    cpp_message = "Operation"
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def cpp_check(self, env):
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not env.is_cpp():
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.cpp_error()
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def cpp_error(self):
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        error(self.pos, "%s only allowed in c++" % self.cpp_message)
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def clone_node(self):
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """Clone the node. This is defined as a shallow copy, except for member lists
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)           amongst the child attributes (from get_child_accessors) which are also
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)           copied. Lists containing child nodes are thus seen as a way for the node
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)           to hold multiple children directly; the list is not treated as a separate
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)           level in the tree."""
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        result = copy.copy(self)
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for attrname in result.child_attrs:
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            value = getattr(result, attrname)
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if isinstance(value, list):
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                setattr(result, attrname, [x for x in value])
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return result
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  There are 3 phases of parse tree processing, applied in order to
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  all the statements in a given scope-block:
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  (0) analyse_declarations
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #        Make symbol table entries for all declarations at the current
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #        level, both explicit (def, cdef, etc.) and implicit (assignment
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #        to an otherwise undeclared name).
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  (1) analyse_expressions
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #         Determine the result types of expressions and fill in the
2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #         'type' attribute of each ExprNode. Insert coercion nodes into the
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #         tree where needed to convert to and from Python objects.
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #         Allocate temporary locals for intermediate results. Fill
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #         in the 'result_code' attribute of each ExprNode with a C code
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #         fragment.
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  (2) generate_code
2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #         Emit C code for all declarations, statements and expressions.
2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #         Recursively applies the 3 processing phases to the bodies of
2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #         functions.
2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        raise InternalError("analyse_expressions not implemented for %s" % \
2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.__class__.__name__)
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_code(self, code):
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        raise InternalError("generate_code not implemented for %s" % \
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.__class__.__name__)
2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # mro does the wrong thing
2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(self, BlockNode):
2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.body.annotate(code)
2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def end_pos(self):
2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        try:
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self._end_pos
2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        except AttributeError:
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pos = self.pos
2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.child_attrs:
2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self._end_pos = pos
2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return pos
2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for attr in self.child_attrs:
2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                child = getattr(self, attr)
2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # Sometimes lists, sometimes nodes
2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if child is None:
2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    pass
2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif isinstance(child, list):
2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    for c in child:
2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        pos = max(pos, c.end_pos())
2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    pos = max(pos, child.end_pos())
2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self._end_pos = pos
2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return pos
2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """Debug helper method that returns a recursive string representation of this node.
2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if cutoff == 0:
2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return "<...nesting level cutoff...>"
2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if encountered is None:
2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            encountered = set()
2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if id(self) in encountered:
2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return "<%s (0x%x) -- already output>" % (self.__class__.__name__, id(self))
2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        encountered.add(id(self))
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        def dump_child(x, level):
2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if isinstance(x, Node):
2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return x.dump(level, filter_out, cutoff-1, encountered)
2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif isinstance(x, list):
2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return "[%s]" % ", ".join([dump_child(item, level) for item in x])
2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return repr(x)
2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        attrs = [(key, value) for key, value in self.__dict__.items() if key not in filter_out]
2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if len(attrs) == 0:
2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return "<%s (0x%x)>" % (self.__class__.__name__, id(self))
2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            indent = "  " * level
2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            res = "<%s (0x%x)\n" % (self.__class__.__name__, id(self))
2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for key, value in attrs:
2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                res += "%s  %s: %s\n" % (indent, key, dump_child(value, level + 1))
2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            res += "%s>" % indent
2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return res
2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def dump_pos(self, mark_column=False, marker='(#)'):
2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """Debug helper method that returns the source code context of this node as a string.
2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.pos:
3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return u''
3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        source_desc, line, col = self.pos
3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        contents = source_desc.get_lines(encoding='ASCII',
3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         error_handling='ignore')
3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # line numbers start at 1
3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lines = contents[max(0,line-3):line]
3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        current = lines[-1]
3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if mark_column:
3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            current = current[:col] + marker + current[col:]
3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lines[-1] = current.rstrip() + u'             # <<<<<<<<<<<<<<\n'
3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lines += contents[line:line+2]
3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return u'"%s":%d:%d\n%s\n' % (
3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            source_desc.get_escaped_description(), line, col, u''.join(lines))
3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CompilerDirectivesNode(Node):
3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Sets compiler directives for the children nodes
3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  directives     {string:value}  A dictionary holding the right value for
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #                                 *all* possible directives.
3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  body           Node
3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["body"]
3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old = env.directives
3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.directives = self.directives
3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.analyse_declarations(env)
3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.directives = old
3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old = env.directives
3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.directives = self.directives
3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = self.body.analyse_expressions(env)
3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.directives = old
3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env_old = env.directives
3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code_old = code.globalstate.directives
3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.directives = self.directives
3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_function_definitions(env, code)
3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.directives = env_old
3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.directives = code_old
3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old = code.globalstate.directives
3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.directives = self.directives
3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.directives = old
3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old = code.globalstate.directives
3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.directives = self.directives
3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.annotate(code)
3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.directives = old
3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class BlockNode(object):
3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  Mixin class for nodes representing a declaration block.
3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_cached_builtins_decls(self, env, code):
3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entries = env.global_scope().undeclared_cached_builtins
3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry in entries:
3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.globalstate.add_cached_builtin_decl(entry)
3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        del entries[:]
3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_lambda_definitions(self, env, code):
3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for node in env.lambda_defs:
3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.generate_function_definitions(env, code)
3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class StatListNode(Node):
3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # stats     a list of StatNode
3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["stats"]
3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def create_analysed(pos, env, *args, **kw):
3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node = StatListNode(pos, *args, **kw)
3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node # No node-specific analysis necesarry
3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    create_analysed = staticmethod(create_analysed)
3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #print "StatListNode.analyse_declarations" ###
3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for stat in self.stats:
3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            stat.analyse_declarations(env)
3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #print "StatListNode.analyse_expressions" ###
3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.stats = [ stat.analyse_expressions(env)
3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       for stat in self.stats ]
3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #print "StatListNode.generate_function_definitions" ###
3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for stat in self.stats:
3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            stat.generate_function_definitions(env, code)
3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
3975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #print "StatListNode.generate_execution_code" ###
3985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for stat in self.stats:
3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.mark_pos(stat.pos)
4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            stat.generate_execution_code(code)
4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
4035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for stat in self.stats:
4045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            stat.annotate(code)
4055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class StatNode(Node):
4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  Code generation for statements is split into the following subphases:
4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  (1) generate_function_definitions
4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #        Emit C code for the definitions of any structs,
4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #        unions, enums and functions defined in the current
4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #        scope-block.
4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  (2) generate_execution_code
4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #        Emit C code for executable statements.
4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        raise InternalError("generate_execution_code not implemented for %s" % \
4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.__class__.__name__)
4265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CDefExternNode(StatNode):
4295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  include_file   string or None
4305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  body           StatNode
4315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["body"]
4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.include_file:
4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.add_include_file(self.include_file)
4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_cinclude_flag = env.in_cinclude
4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.in_cinclude = 1
4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.analyse_declarations(env)
4405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.in_cinclude = old_cinclude_flag
4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
4435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
4445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
4465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.annotate(code)
4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CDeclaratorNode(Node):
4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Part of a C declaration.
4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Processing during analyse_declarations phase:
4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #   analyse
4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #      Returns (name, type) pair where name is the
4595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #      CNameDeclaratorNode of the name being declared
4605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #      and type is the type it is being declared as.
4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  calling_convention  string   Calling convention of CFuncDeclaratorNode
4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #                               for which this is a base
4645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = []
4665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    calling_convention = ""
4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_templates(self):
4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Only C++ functions have templates.
4715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return None
4725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CNameDeclaratorNode(CDeclaratorNode):
4745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  name    string             The Cython name being declared
4755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  cname   string or None     C name, if specified
4765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  default ExprNode or None   the value assigned on declaration
4775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ['default']
4795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    default = None
4815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse(self, base_type, env, nonempty = 0):
4835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if nonempty and self.name == '':
4845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # May have mistaken the name for the type.
4855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "Missing argument name")
4875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif base_type.is_void:
4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
4895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
4905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.name = base_type.declaration_code("", for_display=1, pyrex=1)
4915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                base_type = py_object_type
4925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if base_type.is_fused and env.fused_to_specific:
4945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            base_type = base_type.specialize(env.fused_to_specific)
4955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.type = base_type
4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self, base_type
4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CPtrDeclaratorNode(CDeclaratorNode):
5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # base     CDeclaratorNode
5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["base"]
5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse(self, base_type, env, nonempty = 0):
5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if base_type.is_pyobject:
5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos,
5075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "Pointer base type cannot be a Python object")
5085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ptr_type = PyrexTypes.c_ptr_type(base_type)
5095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.base.analyse(ptr_type, env, nonempty = nonempty)
5105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CReferenceDeclaratorNode(CDeclaratorNode):
5125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # base     CDeclaratorNode
5135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["base"]
5155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse(self, base_type, env, nonempty = 0):
5175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if base_type.is_pyobject:
5185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos,
5195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  "Reference base type cannot be a Python object")
5205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ref_type = PyrexTypes.c_ref_type(base_type)
5215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.base.analyse(ref_type, env, nonempty = nonempty)
5225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CArrayDeclaratorNode(CDeclaratorNode):
5245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # base        CDeclaratorNode
5255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # dimension   ExprNode
5265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["base", "dimension"]
5285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse(self, base_type, env, nonempty = 0):
5305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if base_type.is_cpp_class or base_type.is_cfunction:
5315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            from ExprNodes import TupleNode
5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if isinstance(self.dimension, TupleNode):
5335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                args = self.dimension.args
5345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
5355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                args = self.dimension,
5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            values = [v.analyse_as_type(env) for v in args]
5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if None in values:
5385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ix = values.index(None)
5395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(args[ix].pos, "Template parameter not a type")
5405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                base_type = error_type
5415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
5425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                base_type = base_type.specialize_here(self.pos, values)
5435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.base.analyse(base_type, env, nonempty = nonempty)
5445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.dimension:
5455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.dimension = self.dimension.analyse_const_expression(env)
5465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.dimension.type.is_int:
5475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.dimension.pos, "Array dimension not integer")
5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            size = self.dimension.get_constant_c_result_code()
5495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if size is not None:
5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                try:
5515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    size = int(size)
5525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                except ValueError:
5535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    # runtime constant?
5545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    pass
5555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
5565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            size = None
5575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not base_type.is_complete():
5585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos,
5595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "Array element type '%s' is incomplete" % base_type)
5605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if base_type.is_pyobject:
5615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos,
5625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "Array element cannot be a Python object")
5635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if base_type.is_cfunction:
5645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos,
5655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "Array element cannot be a function")
5665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        array_type = PyrexTypes.c_array_type(base_type, size)
5675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.base.analyse(array_type, env, nonempty = nonempty)
5685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CFuncDeclaratorNode(CDeclaratorNode):
5715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # base             CDeclaratorNode
5725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # args             [CArgDeclNode]
5735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # templates        [TemplatePlaceholderType]
5745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # has_varargs      boolean
5755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # exception_value  ConstNode
5765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # exception_check  boolean    True if PyErr_Occurred check needed
5775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # nogil            boolean    Can be called without gil
5785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # with_gil         boolean    Acquire gil around function body
5795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # is_const_method  boolean    Whether this is a const method
5805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["base", "args", "exception_value"]
5825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    overridable = 0
5845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    optional_arg_count = 0
5855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_const_method = 0
5865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    templates = None
5875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_templates(self):
5895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(self.base, CArrayDeclaratorNode):
5905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            from ExprNodes import TupleNode, NameNode
5915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            template_node = self.base.dimension
5925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if isinstance(template_node, TupleNode):
5935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                template_nodes = template_node.args
5945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif isinstance(template_node, NameNode):
5955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                template_nodes = [template_node]
5965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
5975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(template_node.pos, "Template arguments must be a list of names")
5985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return None
5995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.templates = []
6005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for template in template_nodes:
6015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if isinstance(template, NameNode):
6025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.templates.append(PyrexTypes.TemplatePlaceholderType(template.name))
6035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
6045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(template.pos, "Template arguments must be a list of names")
6055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.base = self.base.base
6065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.templates
6075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
6085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
6095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse(self, return_type, env, nonempty = 0, directive_locals = {}):
6115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if nonempty:
6125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            nonempty -= 1
6135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        func_type_args = []
6145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i, arg_node in enumerate(self.args):
6155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            name_declarator, type = arg_node.analyse(env, nonempty = nonempty,
6165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                     is_self_arg = (i == 0 and env.is_c_class_scope))
6175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            name = name_declarator.name
6185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if name in directive_locals:
6195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                type_node = directive_locals[name]
6205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                other_type = type_node.analyse_as_type(env)
6215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if other_type is None:
6225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(type_node.pos, "Not a type")
6235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif (type is not PyrexTypes.py_object_type
6245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      and not type.same_as(other_type)):
6255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(self.base.pos, "Signature does not agree with previous declaration")
6265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(type_node.pos, "Previous declaration here")
6275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
6285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    type = other_type
6295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if name_declarator.cname:
6305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos,
6315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    "Function argument cannot have C name specification")
6325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if i==0 and env.is_c_class_scope and type.is_unspecified:
6335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # fix the type of self
6345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                type = env.parent_type
6355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Turn *[] argument into **
6365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if type.is_array:
6375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                type = PyrexTypes.c_ptr_type(type.base_type)
6385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Catch attempted C-style func(void) decl
6395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if type.is_void:
6405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
6415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            func_type_args.append(
6425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
6435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg_node.default:
6445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.optional_arg_count += 1
6455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif self.optional_arg_count:
6465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "Non-default argument follows default argument")
6475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        exc_val = None
6495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        exc_check = 0
6505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.exception_check == '+':
6515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.add_include_file('ios')         # for std::ios_base::failure
6525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.add_include_file('new')         # for std::bad_alloc
6535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.add_include_file('stdexcept')
6545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.add_include_file('typeinfo')    # for std::bad_cast
6555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (return_type.is_pyobject
6565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                and (self.exception_value or self.exception_check)
6575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                and self.exception_check != '+'):
6585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos,
6595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "Exception clause not allowed for function returning Python object")
6605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
6615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.exception_value:
6625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.exception_value = self.exception_value.analyse_const_expression(env)
6635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.exception_check == '+':
6645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    exc_val_type = self.exception_value.type
6655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if (not exc_val_type.is_error
6665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            and not exc_val_type.is_pyobject
6675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            and not (exc_val_type.is_cfunction
6685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     and not exc_val_type.return_type.is_pyobject
6695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     and not exc_val_type.args)):
6705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(self.exception_value.pos,
6715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              "Exception value must be a Python exception or cdef function with no arguments.")
6725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    exc_val = self.exception_value
6735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
6745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.exception_value = self.exception_value.coerce_to(
6755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        return_type, env).analyse_const_expression(env)
6765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    exc_val = self.exception_value.get_constant_c_result_code()
6775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if exc_val is None:
6785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        raise InternalError(
6795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            "get_constant_c_result_code not implemented for %s" %
6805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            self.exception_value.__class__.__name__)
6815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if not return_type.assignable_from(self.exception_value.type):
6825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(self.exception_value.pos,
6835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              "Exception value incompatible with function return type")
6845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            exc_check = self.exception_check
6855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if return_type.is_cfunction:
6865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos,
6875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "Function cannot return a function")
6885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        func_type = PyrexTypes.CFuncType(
6895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return_type, func_type_args, self.has_varargs,
6905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            optional_arg_count = self.optional_arg_count,
6915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            exception_value = exc_val, exception_check = exc_check,
6925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            calling_convention = self.base.calling_convention,
6935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable,
6945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            is_const_method = self.is_const_method,
6955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            templates = self.templates)
6965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.optional_arg_count:
6985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if func_type.is_fused:
6995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # This is a bit of a hack... When we need to create specialized CFuncTypes
7005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # on the fly because the cdef is defined in a pxd, we need to declare the specialized optional arg
7015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # struct
7025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                def declare_opt_arg_struct(func_type, fused_cname):
7035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.declare_optional_arg_struct(func_type, env, fused_cname)
7045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                func_type.declare_opt_arg_struct = declare_opt_arg_struct
7065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
7075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.declare_optional_arg_struct(func_type, env)
7085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        callspec = env.directives['callspec']
7105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if callspec:
7115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            current = func_type.calling_convention
7125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if current and current != callspec:
7135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "cannot have both '%s' and '%s' "
7145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      "calling conventions" % (current, callspec))
7155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            func_type.calling_convention = callspec
7165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.base.analyse(func_type, env)
7175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def declare_optional_arg_struct(self, func_type, env, fused_cname=None):
7195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
7205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Declares the optional argument struct (the struct used to hold the
7215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        values for optional arguments). For fused cdef functions, this is
7225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        deferred as analyse_declarations is called only once (on the fused
7235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cdef function).
7245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
7255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        scope = StructOrUnionScope()
7265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        arg_count_member = '%sn' % Naming.pyrex_prefix
7275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        scope.declare_var(arg_count_member, PyrexTypes.c_int_type, self.pos)
7285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in func_type.args[len(func_type.args)-self.optional_arg_count:]:
7305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
7315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
7335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if fused_cname is not None:
7355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            struct_cname = PyrexTypes.get_fused_cname(fused_cname, struct_cname)
7365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        op_args_struct = env.global_scope().declare_struct_or_union(
7385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                name = struct_cname,
7395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                kind = 'struct',
7405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                scope = scope,
7415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                typedef_flag = 0,
7425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pos = self.pos,
7435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                cname = struct_cname)
7445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        op_args_struct.defined_in_pxd = 1
7465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        op_args_struct.used = 1
7475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        func_type.op_arg_struct = PyrexTypes.c_ptr_type(op_args_struct.type)
7495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CConstDeclaratorNode(CDeclaratorNode):
7525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # base     CDeclaratorNode
7535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["base"]
7555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse(self, base_type, env, nonempty = 0):
7575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if base_type.is_pyobject:
7585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos,
7595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  "Const base type cannot be a Python object")
7605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        const = PyrexTypes.c_const_type(base_type)
7615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.base.analyse(const, env, nonempty = nonempty)
7625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CArgDeclNode(Node):
7655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Item in a function declaration argument list.
7665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
7675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # base_type      CBaseTypeNode
7685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # declarator     CDeclaratorNode
7695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # not_none       boolean            Tagged with 'not None'
7705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # or_none        boolean            Tagged with 'or None'
7715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # accept_none    boolean            Resolved boolean for not_none/or_none
7725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # default        ExprNode or None
7735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # default_value  PyObjectConst      constant for default value
7745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # annotation     ExprNode or None   Py3 function arg annotation
7755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # is_self_arg    boolean            Is the "self" arg of an extension type method
7765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # is_type_arg    boolean            Is the "class" arg of an extension type classmethod
7775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # is_kw_only     boolean            Is a keyword-only argument
7785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # is_dynamic     boolean            Non-literal arg stored inside CyFunction
7795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["base_type", "declarator", "default", "annotation"]
7815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_self_arg = 0
7835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_type_arg = 0
7845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_generic = 1
7855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    kw_only = 0
7865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    not_none = 0
7875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    or_none = 0
7885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    type = None
7895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    name_declarator = None
7905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    default_value = None
7915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    annotation = None
7925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_dynamic = 0
7935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse(self, env, nonempty = 0, is_self_arg = False):
7955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if is_self_arg:
7965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.base_type.is_self_arg = self.is_self_arg = True
7975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.type is None:
7985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # The parser may misinterpret names as types. We fix that here.
7995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
8005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if nonempty:
8015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if self.base_type.is_basic_c_type:
8025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        # char, short, long called "int"
8035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        type = self.base_type.analyse(env, could_be_name = True)
8045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        arg_name = type.declaration_code("")
8055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    else:
8065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        arg_name = self.base_type.name
8075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.declarator.name = EncodedString(arg_name)
8085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.base_type.name = None
8095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.base_type.is_basic_c_type = False
8105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                could_be_name = True
8115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
8125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                could_be_name = False
8135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.base_type.is_arg = True
8145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            base_type = self.base_type.analyse(env, could_be_name = could_be_name)
8155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
8165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.declarator.name = self.base_type.arg_name
8175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # The parser is unable to resolve the ambiguity of [] as part of the
8185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # type (e.g. in buffers) or empty declarator (as with arrays).
8195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # This is only arises for empty multi-dimensional arrays.
8205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (base_type.is_array
8215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    and isinstance(self.base_type, TemplatedTypeNode)
8225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    and isinstance(self.declarator, CArrayDeclaratorNode)):
8235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                declarator = self.declarator
8245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                while isinstance(declarator.base, CArrayDeclaratorNode):
8255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    declarator = declarator.base
8265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                declarator.base = self.base_type.array_declarator
8275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                base_type = base_type.base_type
8285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.declarator.analyse(base_type, env, nonempty = nonempty)
8295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
8305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.name_declarator, self.type
8315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def calculate_default_value_code(self, code):
8335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.default_value is None:
8345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.default:
8355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.default.is_literal:
8365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    # will not output any code, just assign the result_code
8375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.default.generate_evaluation_code(code)
8385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    return self.type.cast_code(self.default.result())
8395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.default_value = code.get_argument_default_const(self.type)
8405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.default_value
8415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
8435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.default:
8445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.default.annotate(code)
8455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_assignment_code(self, code, target=None):
8475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        default = self.default
8485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if default is None or default.is_literal:
8495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
8505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if target is None:
8515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            target = self.calculate_default_value_code(code)
8525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        default.generate_evaluation_code(code)
8535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        default.make_owned_reference(code)
8545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        result = default.result_as(self.type)
8555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("%s = %s;" % (target, result))
8565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.type.is_pyobject:
8575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_giveref(default.result())
8585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        default.generate_post_assignment_code(code)
8595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        default.free_temps(code)
8605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CBaseTypeNode(Node):
8635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Abstract base class for C base type nodes.
8645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
8655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Processing during analyse_declarations phase:
8665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
8675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #   analyse
8685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #     Returns the type.
8695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    pass
8715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_as_type(self, env):
8735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.analyse(env)
8745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CAnalysedBaseTypeNode(Node):
8765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # type            type
8775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = []
8795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse(self, env, could_be_name = False):
8815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.type
8825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CSimpleBaseTypeNode(CBaseTypeNode):
8845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # name             string
8855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # module_path      [string]     Qualifying name components
8865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # is_basic_c_type  boolean
8875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # signed           boolean
8885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # longness         integer
8895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # complex          boolean
8905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # is_self_arg      boolean      Is self argument of C method
8915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # ##is_type_arg      boolean      Is type argument of class method
8925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = []
8945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    arg_name = None   # in case the argument name was interpreted as a type
8955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    module_path = []
8965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_basic_c_type = False
8975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    complex = False
8985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse(self, env, could_be_name = False):
9005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Return type descriptor.
9015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
9025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        type = None
9035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_basic_c_type:
9045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
9055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not type:
9065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "Unrecognised type modifier combination")
9075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif self.name == "object" and not self.module_path:
9085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            type = py_object_type
9095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif self.name is None:
9105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.is_self_arg and env.is_c_class_scope:
9115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
9125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                type = env.parent_type
9135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            ## elif self.is_type_arg and env.is_c_class_scope:
9145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            ##     type = Builtin.type_type
9155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
9165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                type = py_object_type
9175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
9185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.module_path:
9195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # Maybe it's a nested C++ class.
9205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                scope = env
9215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for item in self.module_path:
9225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    entry = scope.lookup(item)
9235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if entry is not None and entry.is_cpp_class:
9245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        scope = entry.type.scope
9255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    else:
9265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        scope = None
9275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        break
9285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if scope is None:
9305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    # Maybe it's a cimport.
9315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    scope = env.find_imported_module(self.module_path, self.pos)
9325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if scope:
9335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        scope.fused_to_specific = env.fused_to_specific
9345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
9355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                scope = env
9365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if scope:
9385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if scope.is_c_class_scope:
9395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    scope = scope.global_scope()
9405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                type = scope.lookup_type(self.name)
9425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if type is not None:
9435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    pass
9445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif could_be_name:
9455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if self.is_self_arg and env.is_c_class_scope:
9465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        type = env.parent_type
9475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    ## elif self.is_type_arg and env.is_c_class_scope:
9485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    ##     type = Builtin.type_type
9495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    else:
9505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        type = py_object_type
9515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.arg_name = EncodedString(self.name)
9525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
9535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if self.templates:
9545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        if not self.name in self.templates:
9555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            error(self.pos, "'%s' is not a type identifier" % self.name)
9565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        type = PyrexTypes.TemplatePlaceholderType(self.name)
9575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    else:
9585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(self.pos, "'%s' is not a type identifier" % self.name)
9595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.complex:
9605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not type.is_numeric or type.is_complex:
9615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "can only complexify c numeric types")
9625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            type = PyrexTypes.CComplexType(type)
9635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            type.create_declaration_utility_code(env)
9645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif type is Builtin.complex_type:
9655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Special case: optimise builtin complex type into C's
9665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # double complex.  The parser cannot do this (as for the
9675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # normal scalar types) as the user may have redeclared the
9685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # 'complex' type.  Testing for the exact type here works.
9695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            type = PyrexTypes.c_double_complex_type
9705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            type.create_declaration_utility_code(env)
9715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.complex = True
9725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if type:
9735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return type
9745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
9755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return PyrexTypes.error_type
9765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class MemoryViewSliceTypeNode(CBaseTypeNode):
9785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    name = 'memoryview'
9805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ['base_type_node', 'axes']
9815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse(self, env, could_be_name = False):
9835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base_type = self.base_type_node.analyse(env)
9855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if base_type.is_error: return base_type
9865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import MemoryView
9885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        try:
9905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            axes_specs = MemoryView.get_axes_specs(env, self.axes)
9915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        except CompileError, e:
9925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(e.position, e.message_only)
9935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.type = PyrexTypes.ErrorType()
9945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.type
9955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not MemoryView.validate_axes(self.pos, axes_specs):
9975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.type = error_type
9985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
9995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            MemoryView.validate_memslice_dtype(self.pos, base_type)
10005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.type = PyrexTypes.MemoryViewSliceType(base_type, axes_specs)
10015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.use_memview_utilities(env)
10025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.type
10045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def use_memview_utilities(self, env):
10065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import MemoryView
10075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.use_utility_code(MemoryView.view_utility_code)
10085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CNestedBaseTypeNode(CBaseTypeNode):
10115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # For C++ classes that live inside other C++ classes.
10125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # name             string
10145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # base_type        CBaseTypeNode
10155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ['base_type']
10175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse(self, env, could_be_name = None):
10195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base_type = self.base_type.analyse(env)
10205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if base_type is PyrexTypes.error_type:
10215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return PyrexTypes.error_type
10225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not base_type.is_cpp_class:
10235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "'%s' is not a valid type scope" % base_type)
10245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return PyrexTypes.error_type
10255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        type_entry = base_type.scope.lookup_here(self.name)
10265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not type_entry or not type_entry.is_type:
10275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "'%s.%s' is not a type identifier" % (base_type, self.name))
10285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return PyrexTypes.error_type
10295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return type_entry.type
10305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class TemplatedTypeNode(CBaseTypeNode):
10335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  After parsing:
10345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  positional_args  [ExprNode]        List of positional arguments
10355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  keyword_args     DictNode          Keyword arguments
10365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  base_type_node   CBaseTypeNode
10375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  After analysis:
10395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  type             PyrexTypes.BufferType or PyrexTypes.CppClassType  ...containing the right options
10405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["base_type_node", "positional_args",
10425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   "keyword_args", "dtype_node"]
10435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    dtype_node = None
10455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    name = None
10475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse(self, env, could_be_name = False, base_type = None):
10495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if base_type is None:
10505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            base_type = self.base_type_node.analyse(env)
10515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if base_type.is_error: return base_type
10525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if base_type.is_cpp_class:
10545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Templated class
10555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.keyword_args and self.keyword_args.key_value_pairs:
10565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "c++ templates cannot take keyword arguments")
10575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.type = PyrexTypes.error_type
10585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
10595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                template_types = []
10605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for template_node in self.positional_args:
10615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    type = template_node.analyse_as_type(env)
10625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if type is None:
10635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(template_node.pos, "unknown type in template argument")
10645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        return error_type
10655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    template_types.append(type)
10665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.type = base_type.specialize_here(self.pos, template_types)
10675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif base_type.is_pyobject:
10695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Buffer
10705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            import Buffer
10715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            options = Buffer.analyse_buffer_options(
10735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.pos,
10745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                env,
10755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.positional_args,
10765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.keyword_args,
10775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                base_type.buffer_defaults)
10785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if sys.version_info[0] < 3:
10805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # Py 2.x enforces byte strings as keyword arguments ...
10815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                options = dict([ (name.encode('ASCII'), value)
10825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 for name, value in options.items() ])
10835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.type = PyrexTypes.BufferType(base_type, **options)
10855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
10875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Array
10885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            empty_declarator = CNameDeclaratorNode(self.pos, name="", cname=None)
10895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if len(self.positional_args) > 1 or self.keyword_args.key_value_pairs:
10905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "invalid array declaration")
10915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.type = PyrexTypes.error_type
10925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
10935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # It would be nice to merge this class with CArrayDeclaratorNode,
10945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # but arrays are part of the declaration, not the type...
10955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not self.positional_args:
10965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    dimension = None
10975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
10985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    dimension = self.positional_args[0]
10995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.array_declarator = CArrayDeclaratorNode(self.pos,
11005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    base = empty_declarator,
11015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    dimension = dimension)
11025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.type = self.array_declarator.analyse(base_type, env)[1]
11035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.type.is_fused and env.fused_to_specific:
11055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.type = self.type.specialize(env.fused_to_specific)
11065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.type
11085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CComplexBaseTypeNode(CBaseTypeNode):
11105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # base_type   CBaseTypeNode
11115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # declarator  CDeclaratorNode
11125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["base_type", "declarator"]
11145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse(self, env, could_be_name = False):
11165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base = self.base_type.analyse(env, could_be_name)
11175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        _, type = self.declarator.analyse(base, env)
11185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return type
11195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class FusedTypeNode(CBaseTypeNode):
11225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
11235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Represents a fused type in a ctypedef statement:
11245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ctypedef cython.fused_type(int, long, long long) integral
11265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    name            str                     name of this fused type
11285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    types           [CSimpleBaseTypeNode]   is the list of types to be fused
11295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
11305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = []
11325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
11345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        type = self.analyse(env)
11355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry = env.declare_typedef(self.name, type, self.pos)
11365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Omit the typedef declaration that self.declarator would produce
11385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry.in_cinclude = True
11395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse(self, env):
11415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        types = []
11425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for type_node in self.types:
11435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            type = type_node.analyse_as_type(env)
11445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not type:
11465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(type_node.pos, "Not a type")
11475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                continue
11485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if type in types:
11505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(type_node.pos, "Type specified multiple times")
11515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif type.is_fused:
11525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(type_node.pos, "Cannot fuse a fused type")
11535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
11545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                types.append(type)
11555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # if len(self.types) == 1:
11575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #     return types[0]
11585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return PyrexTypes.FusedType(types, name=self.name)
11605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CConstTypeNode(CBaseTypeNode):
11635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # base_type     CBaseTypeNode
11645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["base_type"]
11665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse(self, env, could_be_name = False):
11685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base = self.base_type.analyse(env, could_be_name)
11695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if base.is_pyobject:
11705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos,
11715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  "Const base type cannot be a Python object")
11725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return PyrexTypes.c_const_type(base)
11735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CVarDefNode(StatNode):
11765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  C variable definition or forward/extern function declaration.
11775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
11785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  visibility    'private' or 'public' or 'extern'
11795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  base_type     CBaseTypeNode
11805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  declarators   [CDeclaratorNode]
11815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  in_pxd        boolean
11825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  api           boolean
11835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  overridable   boolean        whether it is a cpdef
11845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  modifiers     ['inline']
11855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  decorators    [cython.locals(...)] or None
11875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  directive_locals { string : NameNode } locals defined by cython.locals(...)
11885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["base_type", "declarators"]
11905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    decorators = None
11925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    directive_locals = None
11935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env, dest_scope = None):
11955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.directive_locals is None:
11965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.directive_locals = {}
11975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not dest_scope:
11985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            dest_scope = env
11995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.dest_scope = dest_scope
12005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.declarators:
12025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            templates = self.declarators[0].analyse_templates()
12035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
12045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            templates = None
12055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if templates is not None:
12065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.visibility != 'extern':
12075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "Only extern functions allowed")
12085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if len(self.declarators) > 1:
12095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.declarators[1].pos, "Can't multiply declare template types")
12105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env = TemplateScope('func_template', env)
12115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.directives = env.outer_scope.directives
12125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for template_param in templates:
12135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                env.declare_type(template_param.name, template_param, self.pos)
12145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base_type = self.base_type.analyse(env)
12165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if base_type.is_fused and not self.in_pxd and (env.is_c_class_scope or
12185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                       env.is_module_scope):
12195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "Fused types not allowed here")
12205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return error_type
12215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry = None
12235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        visibility = self.visibility
12245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for declarator in self.declarators:
12265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (len(self.declarators) > 1
12285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                and not isinstance(declarator, CNameDeclaratorNode)
12295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                and env.directives['warn.multiple_declarators']):
12305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                warning(declarator.pos,
12315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    "Non-trivial type declarators in shared declaration (e.g. mix of pointers and values). " +
12325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    "Each pointer declaration should be on its own line.", 1)
12335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if isinstance(declarator, CFuncDeclaratorNode):
12355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                name_declarator, type = declarator.analyse(base_type, env, directive_locals=self.directive_locals)
12365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
12375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                name_declarator, type = declarator.analyse(base_type, env)
12385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not type.is_complete():
12395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not (self.visibility == 'extern' and type.is_array or type.is_memoryviewslice):
12405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(declarator.pos,
12415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        "Variable type '%s' is incomplete" % type)
12425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.visibility == 'extern' and type.is_pyobject:
12435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(declarator.pos,
12445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    "Python object cannot be declared extern")
12455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            name = name_declarator.name
12465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cname = name_declarator.cname
12475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if name == '':
12485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(declarator.pos, "Missing name in declaration.")
12495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return
12505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if type.is_cfunction:
12515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.entry = dest_scope.declare_cfunction(name, type, declarator.pos,
12525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
12535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    api = self.api, modifiers = self.modifiers)
12545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.entry is not None:
12555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.entry.is_overridable = self.overridable
12565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.entry.directive_locals = copy.copy(self.directive_locals)
12575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
12585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.directive_locals:
12595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(self.pos, "Decorators can only be followed by functions")
12605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.entry = dest_scope.declare_var(name, type, declarator.pos,
12615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            cname=cname, visibility=visibility, in_pxd=self.in_pxd,
12625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            api=self.api, is_cdef=1)
12635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if Options.docstrings:
12645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.entry.doc = embed_position(self.pos, self.doc)
12655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CStructOrUnionDefNode(StatNode):
12685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  name          string
12695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  cname         string or None
12705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  kind          "struct" or "union"
12715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  typedef_flag  boolean
12725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  visibility    "public" or "private"
12735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  api           boolean
12745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  in_pxd        boolean
12755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  attributes    [CVarDefNode] or None
12765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  entry         Entry
12775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  packed        boolean
12785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["attributes"]
12805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def declare(self, env, scope=None):
12825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.visibility == 'extern' and self.packed and not scope:
12835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "Cannot declare extern struct as 'packed'")
12845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry = env.declare_struct_or_union(
12855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.name, self.kind, scope, self.typedef_flag, self.pos,
12865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.cname, visibility = self.visibility, api = self.api,
12875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            packed = self.packed)
12885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
12905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        scope = None
12915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.attributes is not None:
12925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            scope = StructOrUnionScope(self.name)
12935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.declare(env, scope)
12945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.attributes is not None:
12955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.in_pxd and not env.in_cinclude:
12965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.entry.defined_in_pxd = 1
12975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for attr in self.attributes:
12985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                attr.analyse_declarations(env, scope)
12995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.visibility != 'extern':
13005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for attr in scope.var_entries:
13015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    type = attr.type
13025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    while type.is_array:
13035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        type = type.base_type
13045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if type == self.entry.type:
13055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(attr.pos, "Struct cannot contain itself as a member.")
13065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
13085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
13095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
13115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
13125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CppClassNode(CStructOrUnionDefNode, BlockNode):
13155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  name          string
13175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  cname         string or None
13185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  visibility    "extern"
13195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  in_pxd        boolean
13205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  attributes    [CVarDefNode] or None
13215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  entry         Entry
13225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  base_classes  [CBaseTypeNode]
13235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  templates     [string] or None
13245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def declare(self, env):
13265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.templates is None:
13275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            template_types = None
13285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
13295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            template_types = [PyrexTypes.TemplatePlaceholderType(template_name) for template_name in self.templates]
13305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry = env.declare_cpp_class(
13315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.name, None, self.pos,
13325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.cname, base_classes = [], visibility = self.visibility, templates = template_types)
13335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
13355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        scope = None
13365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.attributes is not None:
13375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            scope = CppClassScope(self.name, env, templates = self.templates)
13385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        def base_ok(base_class):
13395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if base_class.is_cpp_class or base_class.is_struct:
13405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return True
13415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
13425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "Base class '%s' not a struct or class." % base_class)
13435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base_class_types = filter(base_ok, [b.analyse(scope or env) for b in self.base_classes])
13445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.templates is None:
13455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            template_types = None
13465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
13475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            template_types = [PyrexTypes.TemplatePlaceholderType(template_name) for template_name in self.templates]
13485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry = env.declare_cpp_class(
13495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.name, scope, self.pos,
13505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.cname, base_class_types, visibility = self.visibility, templates = template_types)
13515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.entry is None:
13525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
13535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry.is_cpp_class = 1
13545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if scope is not None:
13555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            scope.type = self.entry.type
13565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        defined_funcs = []
13575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.attributes is not None:
13585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.in_pxd and not env.in_cinclude:
13595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.entry.defined_in_pxd = 1
13605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for attr in self.attributes:
13615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                attr.analyse_declarations(scope)
13625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if isinstance(attr, CFuncDefNode):
13635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    defined_funcs.append(attr)
13645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if self.templates is not None:
13655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        attr.template_declaration = "template <typename %s>" % ", typename ".join(self.templates)
13665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = StatListNode(self.pos, stats=defined_funcs)
13675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.scope = scope
13685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
13705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = self.body.analyse_expressions(self.entry.type.scope)
13715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
13725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
13745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_function_definitions(self.entry.type.scope, code)
13755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
13775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
13785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
13805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.annotate(code)
13815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CEnumDefNode(StatNode):
13845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  name           string or None
13855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  cname          string or None
13865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  items          [CEnumDefItemNode]
13875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  typedef_flag   boolean
13885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  visibility     "public" or "private"
13895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  api            boolean
13905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  in_pxd         boolean
13915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  entry          Entry
13925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["items"]
13945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def declare(self, env):
13965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)         self.entry = env.declare_enum(self.name, self.pos,
13975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             cname = self.cname, typedef_flag = self.typedef_flag,
13985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             visibility = self.visibility, api = self.api)
13995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
14015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.items is not None:
14025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.in_pxd and not env.in_cinclude:
14035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.entry.defined_in_pxd = 1
14045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for item in self.items:
14055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                item.analyse_declarations(env, self.entry)
14065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
14085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
14095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
14115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.visibility == 'public' or self.api:
14125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            temp = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
14135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for item in self.entry.enum_values:
14145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("%s = PyInt_FromLong(%s); %s" % (
14155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        temp,
14165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        item.cname,
14175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.error_goto_if_null(temp, item.pos)))
14185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_gotref(temp)
14195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('if (PyDict_SetItemString(%s, "%s", %s) < 0) %s' % (
14205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        Naming.moddict_cname,
14215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        item.name,
14225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        temp,
14235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.error_goto(item.pos)))
14245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_decref_clear(temp, PyrexTypes.py_object_type)
14255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.funcstate.release_temp(temp)
14265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CEnumDefItemNode(StatNode):
14295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  name     string
14305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  cname    string or None
14315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  value    ExprNode or None
14325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["value"]
14345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env, enum_entry):
14365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.value:
14375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.value = self.value.analyse_const_expression(env)
14385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.value.type.is_int:
14395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
14405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.value = self.value.analyse_const_expression(env)
14415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry = env.declare_const(self.name, enum_entry.type,
14425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.value, self.pos, cname = self.cname,
14435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            visibility = enum_entry.visibility, api = enum_entry.api)
14445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        enum_entry.enum_values.append(entry)
14455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CTypeDefNode(StatNode):
14485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  base_type    CBaseTypeNode
14495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  declarator   CDeclaratorNode
14505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  visibility   "public" or "private"
14515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  api          boolean
14525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  in_pxd       boolean
14535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["base_type", "declarator"]
14555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
14575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base = self.base_type.analyse(env)
14585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        name_declarator, type = self.declarator.analyse(base, env)
14595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        name = name_declarator.name
14605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cname = name_declarator.cname
14615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry = env.declare_typedef(name, type, self.pos,
14635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cname = cname, visibility = self.visibility, api = self.api)
14645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if type.is_fused:
14665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry.in_cinclude = True
14675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.in_pxd and not env.in_cinclude:
14695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry.defined_in_pxd = 1
14705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
14725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
14735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
14755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
14765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class FuncDefNode(StatNode, BlockNode):
14795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  Base class for function definition nodes.
14805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
14815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  return_type     PyrexType
14825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  #filename        string        C name of filename string const
14835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  entry           Symtab.Entry
14845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  needs_closure   boolean        Whether or not this function has inner functions/classes/yield
14855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  needs_outer_scope boolean      Whether or not this function requires outer scope
14865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  pymethdef_required boolean     Force Python method struct generation
14875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  directive_locals { string : ExprNode } locals defined by cython.locals(...)
14885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  directive_returns [ExprNode] type defined by cython.returns(...)
14895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # star_arg      PyArgDeclNode or None  * argument
14905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # starstar_arg  PyArgDeclNode or None  ** argument
14915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  has_fused_arguments  boolean
14935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #       Whether this cdef function has fused parameters. This is needed
14945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #       by AnalyseDeclarationsTransform, so it can replace CFuncDefNodes
14955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #       with fused argument types with a FusedCFuncDefNode
14965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    py_func = None
14985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    needs_closure = False
14995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    needs_outer_scope = False
15005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    pymethdef_required = False
15015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_generator = False
15025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_generator_body = False
15035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    modifiers = []
15045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    has_fused_arguments = False
15055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    star_arg = None
15065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    starstar_arg = None
15075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_cyfunction = False
15085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_default_values(self, env):
15105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        default_seen = 0
15115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
15125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.default:
15135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                default_seen = 1
15145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.is_generic:
15155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.default = arg.default.analyse_types(env)
15165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.default = arg.default.coerce_to(arg.type, env)
15175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
15185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(arg.pos,
15195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        "This argument cannot have a default value")
15205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.default = None
15215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif arg.kw_only:
15225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                default_seen = 1
15235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif default_seen:
15245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(arg.pos, "Non-default argument following default argument")
15255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def align_argument_type(self, env, arg):
15275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        directive_locals = self.directive_locals
15285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        type = arg.type
15295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if arg.name in directive_locals:
15305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            type_node = directive_locals[arg.name]
15315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            other_type = type_node.analyse_as_type(env)
15325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if other_type is None:
15335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(type_node.pos, "Not a type")
15345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif (type is not PyrexTypes.py_object_type
15355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    and not type.same_as(other_type)):
15365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(arg.base_type.pos, "Signature does not agree with previous declaration")
15375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(type_node.pos, "Previous declaration here")
15385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
15395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg.type = other_type
15405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return arg
15415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def need_gil_acquisition(self, lenv):
15435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return 0
15445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def create_local_scope(self, env):
15465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        genv = env
15475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        while genv.is_py_class_scope or genv.is_c_class_scope:
15485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            genv = genv.outer_scope
15495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.needs_closure:
15505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lenv = ClosureScope(name=self.entry.name,
15515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                outer_scope = genv,
15525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                parent_scope = env,
15535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                scope_name=self.entry.cname)
15545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
15555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lenv = LocalScope(name=self.entry.name,
15565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              outer_scope=genv,
15575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              parent_scope=env)
15585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lenv.return_type = self.return_type
15595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        type = self.entry.type
15605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if type.is_cfunction:
15615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lenv.nogil = type.nogil and not type.with_gil
15625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.local_scope = lenv
15635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lenv.directives = env.directives
15645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return lenv
15655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_body(self, env, code):
15675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
15685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
15705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import Buffer
15715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.return_type.is_memoryviewslice:
15725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            import MemoryView
15735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lenv = self.local_scope
15755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if lenv.is_closure_scope and not lenv.is_passthrough:
15765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            outer_scope_cname = "%s->%s" % (Naming.cur_scope_cname,
15775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            Naming.outer_scope_cname)
15785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
15795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            outer_scope_cname = Naming.outer_scope_cname
15805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lenv.mangle_closure_cnames(outer_scope_cname)
15815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Generate closure function definitions
15825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_function_definitions(lenv, code)
15835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # generate lambda function definitions
15845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_lambda_definitions(lenv, code)
15855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
15875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             self.entry.scope.is_c_class_scope)
15885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        is_releasebuffer_slot = (self.entry.name == "__releasebuffer__" and
15895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 self.entry.scope.is_c_class_scope)
15905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        is_buffer_slot = is_getbuffer_slot or is_releasebuffer_slot
15915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if is_buffer_slot:
15925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if 'cython_unused' not in self.modifiers:
15935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.modifiers = self.modifiers + ['cython_unused']
15945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        preprocessor_guard = self.get_preprocessor_guard()
15965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        profile = code.globalstate.directives['profile']
15985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        linetrace = code.globalstate.directives['linetrace']
15995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (linetrace or profile) and lenv.nogil:
16005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            warning(self.pos, "Cannot profile nogil function.", 1)
16015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            profile = linetrace = False
16025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if profile or linetrace:
16035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.globalstate.use_utility_code(
16045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                UtilityCode.load_cached("Profile", "Profile.c"))
16055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Generate C code for header and body of function
16075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.enter_cfunc_scope()
16085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.return_from_error_cleanup_label = code.new_label()
16095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Top-level constants used by this function
16115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.mark_pos(self.pos)
16125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_cached_builtins_decls(lenv, code)
16135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Function header
16145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("")
16155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if preprocessor_guard:
16175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(preprocessor_guard)
16185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        with_pymethdef = (self.needs_assignment_synthesis(env, code) or
16205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          self.pymethdef_required)
16215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.py_func:
16225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.py_func.generate_function_header(code,
16235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                with_pymethdef = with_pymethdef,
16245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                proto_only=True)
16255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_function_header(code,
16265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            with_pymethdef = with_pymethdef)
16275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Local variable declarations
16285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Find function scope
16295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cenv = env
16305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        while cenv.is_py_class_scope or cenv.is_c_class_scope:
16315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cenv = cenv.outer_scope
16325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.needs_closure:
16335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put(lenv.scope_class.type.declaration_code(Naming.cur_scope_cname))
16345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(";")
16355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif self.needs_outer_scope:
16365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if lenv.is_passthrough:
16375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put(lenv.scope_class.type.declaration_code(Naming.cur_scope_cname))
16385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln(";")
16395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put(cenv.scope_class.type.declaration_code(Naming.outer_scope_cname))
16405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(";")
16415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_argument_declarations(lenv, code)
16425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry in lenv.var_entries:
16445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not (entry.in_closure or entry.is_arg):
16455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_var_declaration(entry)
16465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Initialize the return variable __pyx_r
16485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        init = ""
16495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.return_type.is_void:
16505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.return_type.is_pyobject:
16515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                init = " = NULL"
16525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif self.return_type.is_memoryviewslice:
16535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                init = ' = ' + MemoryView.memslice_entry_init
16545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
16565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "%s%s;" %
16575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    (self.return_type.declaration_code(Naming.retval_cname),
16585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     init))
16595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        tempvardecl_code = code.insertion_point()
16615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_keyword_list(code)
16625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if profile or linetrace:
16645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_trace_declarations()
16655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Extern library function declarations
16675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lenv.generate_library_function_declarations(code)
16685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- GIL acquisition
16705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        acquire_gil = self.acquire_gil
16715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # See if we need to acquire the GIL for variable declarations, or for
16735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # refnanny only
16745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Profiling or closures are not currently possible for cdef nogil
16765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # functions, but check them anyway
16775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        have_object_args = (self.needs_closure or self.needs_outer_scope or
16785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            profile or linetrace)
16795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in lenv.arg_entries:
16805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.type.is_pyobject:
16815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                have_object_args = True
16825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                break
16835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        acquire_gil_for_var_decls_only = (
16855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                lenv.nogil and lenv.has_with_gil_block and
16865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                (have_object_args or lenv.buffer_entries))
16875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        acquire_gil_for_refnanny_only = (
16895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                lenv.nogil and lenv.has_with_gil_block and not
16905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                acquire_gil_for_var_decls_only)
16915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        use_refnanny = not lenv.nogil or lenv.has_with_gil_block
16935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if acquire_gil or acquire_gil_for_var_decls_only:
16955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_ensure_gil()
16965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif lenv.nogil and lenv.has_with_gil_block:
16975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.declare_gilstate()
16985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- set up refnanny
17005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if use_refnanny:
17015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            tempvardecl_code.put_declare_refcount_context()
17025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_setup_refcount_context(
17035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.entry.name, acquire_gil=acquire_gil_for_refnanny_only)
17045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Automatic lead-ins for certain special functions
17065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if is_getbuffer_slot:
17075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.getbuffer_init(code)
17085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Create closure scope object
17095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.needs_closure:
17105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            tp_slot = TypeSlots.ConstructorSlot("tp_new", '__new__')
17115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            slot_func_cname = TypeSlots.get_slot_function(lenv.scope_class.type.scope, tp_slot)
17125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not slot_func_cname:
17135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                slot_func_cname = '%s->tp_new' % lenv.scope_class.type.typeptr_cname
17145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("%s = (%s)%s(%s, %s, NULL);" % (
17155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Naming.cur_scope_cname,
17165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                lenv.scope_class.type.declaration_code(''),
17175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                slot_func_cname,
17185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                lenv.scope_class.type.typeptr_cname,
17195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Naming.empty_tuple))
17205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("if (unlikely(!%s)) {" % Naming.cur_scope_cname)
17215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if is_getbuffer_slot:
17225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.getbuffer_error_cleanup(code)
17235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if use_refnanny:
17255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_finish_refcount_context()
17265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if acquire_gil or acquire_gil_for_var_decls_only:
17275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put_release_ensured_gil()
17285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # FIXME: what if the error return value is a Python value?
17305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("return %s;" % self.error_value())
17315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("}")
17325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_gotref(Naming.cur_scope_cname)
17335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Note that it is unsafe to decref the scope at this point.
17345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.needs_outer_scope:
17355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.is_cyfunction:
17365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("%s = (%s) __Pyx_CyFunction_GetClosure(%s);" % (
17375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    outer_scope_cname,
17385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    cenv.scope_class.type.declaration_code(''),
17395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    Naming.self_cname))
17405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
17415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("%s = (%s) %s;" % (
17425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    outer_scope_cname,
17435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    cenv.scope_class.type.declaration_code(''),
17445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    Naming.self_cname))
17455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if lenv.is_passthrough:
17465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("%s = %s;" % (Naming.cur_scope_cname, outer_scope_cname))
17475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif self.needs_closure:
17485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # inner closures own a reference to their outer parent
17495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_incref(outer_scope_cname, cenv.scope_class.type)
17505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_giveref(outer_scope_cname)
17515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Trace function call
17525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if profile or linetrace:
17535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # this looks a bit late, but if we don't get here due to a
17545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # fatal error before hand, it's not really worth tracing
17555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_trace_call(self.entry.name, self.pos)
17565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.funcstate.can_trace = True
17575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Fetch arguments
17585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_argument_parsing_code(env, code)
17595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # If an argument is assigned to in the body, we must
17605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # incref it to properly keep track of refcounts.
17615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        is_cdef = isinstance(self, CFuncDefNode)
17625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry in lenv.arg_entries:
17635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.type.is_pyobject:
17645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if ((acquire_gil or len(entry.cf_assignments) > 1) and
17655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    not entry.in_closure):
17665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put_var_incref(entry)
17675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Note: defaults are always incref-ed. For def functions, we
17695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            #       we aquire arguments from object converstion, so we have
17705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            #       new references. If we are a cdef function, we need to
17715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            #       incref our arguments
17725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif (is_cdef and entry.type.is_memoryviewslice and
17735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  len(entry.cf_assignments) > 1):
17745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_incref_memoryviewslice(entry.cname,
17755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                have_gil=not lenv.nogil)
17765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry in lenv.var_entries:
17775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.is_arg and len(entry.cf_assignments) > 1:
17785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_var_incref(entry)
17795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Initialise local buffer auxiliary variables
17815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry in lenv.var_entries + lenv.arg_entries:
17825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.type.is_buffer and entry.buffer_aux.buflocal_nd_var.used:
17835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Buffer.put_init_vars(entry, code)
17845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Check and convert arguments
17865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_argument_type_tests(code)
17875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Acquire buffer arguments
17885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry in lenv.arg_entries:
17895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.type.is_buffer:
17905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Buffer.put_acquire_arg_buffer(entry, code, self.pos)
17915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if acquire_gil_for_var_decls_only:
17935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_release_ensured_gil()
17945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # -------------------------
17965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Function body -----
17975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # -------------------------
17985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_function_body(env, code)
17995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.mark_pos(self.pos)
18015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("")
18025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("/* function exit code */")
18035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Default return value
18055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.body.is_terminator:
18065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.return_type.is_pyobject:
18075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                #if self.return_type.is_extension_type:
18085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                #    lhs = "(PyObject *)%s" % Naming.retval_cname
18095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                #else:
18105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                lhs = Naming.retval_cname
18115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_init_to_py_none(lhs, self.return_type)
18125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
18135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                val = self.return_type.default_value
18145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if val:
18155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln("%s = %s;" % (Naming.retval_cname, val))
18165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Error cleanup
18175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if code.error_label in code.labels_used:
18185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.body.is_terminator:
18195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(code.return_label)
18205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_label(code.error_label)
18215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for cname, type in code.funcstate.all_managed_temps():
18225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_xdecref(cname, type, have_gil=not lenv.nogil)
18235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Clean up buffers -- this calls a Python function
18255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # so need to save and restore error state
18265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            buffers_present = len(lenv.buffer_entries) > 0
18275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            memslice_entries = [e for e in lenv.entries.itervalues()
18285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      if e.type.is_memoryviewslice]
18295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if buffers_present:
18305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.globalstate.use_utility_code(restore_exception_utility_code)
18315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
18325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
18335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for entry in lenv.buffer_entries:
18345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    Buffer.put_release_buffer_code(code, entry)
18355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    #code.putln("%s = 0;" % entry.cname)
18365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
18375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.return_type.is_memoryviewslice:
18395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                MemoryView.put_init_entry(Naming.retval_cname, code)
18405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                err_val = Naming.retval_cname
18415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
18425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                err_val = self.error_value()
18435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            exc_check = self.caller_will_check_exceptions()
18455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if err_val is not None or exc_check:
18465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # TODO: Fix exception tracing (though currently unused by cProfile).
18475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # code.globalstate.use_utility_code(get_exception_tuple_utility_code)
18485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # code.put_trace_exception()
18495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if lenv.nogil and not lenv.has_with_gil_block:
18515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln("{")
18525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put_ensure_gil()
18535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_add_traceback(self.entry.qualified_name)
18555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if lenv.nogil and not lenv.has_with_gil_block:
18575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put_release_ensured_gil()
18585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln("}")
18595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
18605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                warning(self.entry.pos,
18615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        "Unraisable exception in function '%s'." %
18625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        self.entry.qualified_name, 0)
18635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_unraisable(self.entry.qualified_name)
18645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            default_retval = self.return_type.default_value
18655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if err_val is None and default_retval:
18665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                err_val = default_retval
18675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if err_val is not None:
18685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("%s = %s;" % (Naming.retval_cname, err_val))
18695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if is_getbuffer_slot:
18715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.getbuffer_error_cleanup(code)
18725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # If we are using the non-error cleanup section we should
18745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # jump past it if we have an error. The if-test below determine
18755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # whether this section is used.
18765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if buffers_present or is_getbuffer_slot or self.return_type.is_memoryviewslice:
18775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(code.return_from_error_cleanup_label)
18785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Non-error return cleanup
18805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_label(code.return_label)
18815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry in lenv.buffer_entries:
18825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.used:
18835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Buffer.put_release_buffer_code(code, entry)
18845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if is_getbuffer_slot:
18855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.getbuffer_normal_cleanup(code)
18865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.return_type.is_memoryviewslice:
18885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # See if our return value is uninitialized on non-error return
18895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # import MemoryView
18905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # MemoryView.err_if_nogil_initialized_check(self.pos, env)
18915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cond = code.unlikely(self.return_type.error_condition(
18925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                    Naming.retval_cname))
18935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
18945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                'if (%s) {' % cond)
18955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if env.nogil:
18965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_ensure_gil()
18975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
18985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    'PyErr_SetString('
18995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        'PyExc_TypeError,'
19005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        '"Memoryview return value is not initialized");')
19015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if env.nogil:
19025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_release_ensured_gil()
19035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
19045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                '}')
19055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Return cleanup for both error and no-error return
19075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_label(code.return_from_error_cleanup_label)
19085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry in lenv.var_entries:
19105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not entry.used or entry.in_closure:
19115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                continue
19125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.type.is_memoryviewslice:
19145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_xdecref_memoryviewslice(entry.cname,
19155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                 have_gil=not lenv.nogil)
19165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif entry.type.is_pyobject:
19175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not entry.is_arg or len(entry.cf_assignments) > 1:
19185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put_var_decref(entry)
19195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Decref any increfed args
19215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry in lenv.arg_entries:
19225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.type.is_pyobject:
19235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if ((acquire_gil or len(entry.cf_assignments) > 1) and
19245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    not entry.in_closure):
19255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put_var_decref(entry)
19265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif (entry.type.is_memoryviewslice and
19275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  (not is_cdef or len(entry.cf_assignments) > 1)):
19285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # decref slices of def functions and acquired slices from cdef
19295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # functions, but not borrowed slices from cdef functions.
19305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_xdecref_memoryviewslice(entry.cname,
19315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                 have_gil=not lenv.nogil)
19325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.needs_closure:
19335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_decref(Naming.cur_scope_cname, lenv.scope_class.type)
19345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Return
19365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # This code is duplicated in ModuleNode.generate_module_init_func
19375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not lenv.nogil:
19385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            default_retval = self.return_type.default_value
19395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            err_val = self.error_value()
19405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if err_val is None and default_retval:
19415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                err_val = default_retval  # FIXME: why is err_val not used?
19425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.return_type.is_pyobject:
19435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
19445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.entry.is_special and self.entry.name == "__hash__":
19465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Returning -1 for __hash__ is supposed to signal an error
19475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # We do as Python instances and coerce -1 into -2.
19485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("if (unlikely(%s == -1) && !PyErr_Occurred()) %s = -2;" % (
19495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    Naming.retval_cname, Naming.retval_cname))
19505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if profile or linetrace:
19525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.funcstate.can_trace = False
19535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.return_type.is_pyobject:
19545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_trace_return(Naming.retval_cname)
19555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
19565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_trace_return("Py_None")
19575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not lenv.nogil:
19595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # GIL holding function
19605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_finish_refcount_context()
19615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if acquire_gil or (lenv.nogil and lenv.has_with_gil_block):
19635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # release the GIL (note that with-gil blocks acquire it on exit in their EnsureGILNode)
19645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_release_ensured_gil()
19655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.return_type.is_void:
19675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("return %s;" % Naming.retval_cname)
19685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
19705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if preprocessor_guard:
19725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("#endif /*!(%s)*/" % preprocessor_guard)
19735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Go back and insert temp variable declarations
19755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        tempvardecl_code.put_temp_declarations(code.funcstate)
19765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Python version
19785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.exit_cfunc_scope()
19795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.py_func:
19805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.py_func.generate_function_definitions(env, code)
19815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_wrapper_functions(code)
19825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def declare_argument(self, env, arg):
19845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if arg.type.is_void:
19855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(arg.pos, "Invalid use of 'void'")
19865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif not arg.type.is_complete() and not (arg.type.is_array or arg.type.is_memoryviewslice):
19875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(arg.pos,
19885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "Argument type '%s' is incomplete" % arg.type)
19895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return env.declare_arg(arg.name, arg.type, arg.pos)
19905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_arg_type_test(self, arg, code):
19925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Generate type test for one argument.
19935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if arg.type.typeobj_is_available():
19945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.globalstate.use_utility_code(
19955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                UtilityCode.load_cached("ArgTypeTest", "FunctionArguments.c"))
19965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            typeptr_cname = arg.type.typeptr_cname
19975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_code = "((PyObject *)%s)" % arg.entry.cname
19985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
19995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
20005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg_code,
20015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    typeptr_cname,
20025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.accept_none,
20035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.name,
20045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.type.is_builtin_type,
20055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.error_goto(arg.pos)))
20065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
20075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(arg.pos, "Cannot test type of extern C class "
20085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "without type object name specification")
20095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_arg_none_check(self, arg, code):
20115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Generate None check for one argument.
20125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if arg.type.is_memoryviewslice:
20135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cname = "%s.memview" % arg.entry.cname
20145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
20155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cname = arg.entry.cname
20165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('if (unlikely(((PyObject *)%s) == Py_None)) {' % cname)
20185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('''PyErr_Format(PyExc_TypeError, "Argument '%%.%ds' must not be None", "%s"); %s''' % (
20195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            max(200, len(arg.name)), arg.name,
20205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.error_goto(arg.pos)))
20215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('}')
20225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_wrapper_functions(self, code):
20245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
20255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
20275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Evaluate and store argument default values
20285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
20295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not arg.is_dynamic:
20305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg.generate_assignment_code(code)
20315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
20335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Special code for the __getbuffer__ function
20345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
20355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def getbuffer_init(self, code):
20365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        info = self.local_scope.arg_entries[1].cname
20375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Python 3.0 betas have a bug in memoryview which makes it call
20385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # getbuffer with a NULL parameter. For now we work around this;
20395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # the following block should be removed when this bug is fixed.
20405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("if (%s != NULL) {" % info)
20415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
20425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
20435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
20445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def getbuffer_error_cleanup(self, code):
20465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        info = self.local_scope.arg_entries[1].cname
20475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("if (%s != NULL && %s->obj != NULL) {"
20485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   % (info, info))
20495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_gotref("%s->obj" % info)
20505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;"
20515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   % (info, info))
20525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
20535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def getbuffer_normal_cleanup(self, code):
20555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        info = self.local_scope.arg_entries[1].cname
20565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("if (%s != NULL && %s->obj == Py_None) {" % (info, info))
20575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_gotref("Py_None")
20585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
20595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
20605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def get_preprocessor_guard(self):
20625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.entry.is_special:
20635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
20645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        name = self.entry.name
20655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        slot = TypeSlots.method_name_to_slot.get(name)
20665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not slot:
20675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
20685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if name == '__long__' and not self.entry.scope.lookup_here('__int__'):
20695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
20705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if name in ("__getbuffer__", "__releasebuffer__") and self.entry.scope.is_c_class_scope:
20715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
20725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return slot.preprocessor_guard_code()
20735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CFuncDefNode(FuncDefNode):
20765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  C function definition.
20775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
20785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  modifiers     ['inline']
20795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  visibility    'private' or 'public' or 'extern'
20805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  base_type     CBaseTypeNode
20815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  declarator    CDeclaratorNode
20825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  cfunc_declarator  the CFuncDeclarator of this function
20835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #                    (this is also available through declarator or a
20845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #                     base thereof)
20855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  body          StatListNode
20865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  api           boolean
20875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  decorators    [DecoratorNode]        list of decorators
20885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
20895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  with_gil      boolean    Acquire GIL around body
20905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  type          CFuncType
20915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  py_func       wrapper for calling from Python
20925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  overridable   whether or not this is a cpdef function
20935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  inline_in_pxd whether this is an inline function in a pxd file
20945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  template_declaration  String or None   Used for c++ class methods
20955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  is_const_method whether this is a const method
20965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["base_type", "declarator", "body", "py_func"]
20985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    inline_in_pxd = False
21005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    decorators = None
21015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    directive_locals = None
21025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    directive_returns = None
21035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    override = None
21045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    template_declaration = None
21055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_const_method = False
21065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def unqualified_name(self):
21085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.entry.name
21095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
21115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.directive_locals is None:
21125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.directive_locals = {}
21135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.directive_locals.update(env.directives['locals'])
21145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.directive_returns is not None:
21155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            base_type = self.directive_returns.analyse_as_type(env)
21165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if base_type is None:
21175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.directive_returns.pos, "Not a type")
21185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                base_type = PyrexTypes.error_type
21195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
21205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            base_type = self.base_type.analyse(env)
21215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # The 2 here is because we need both function and argument names.
21225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(self.declarator, CFuncDeclaratorNode):
21235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            name_declarator, type = self.declarator.analyse(base_type, env,
21245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                            nonempty = 2 * (self.body is not None),
21255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                            directive_locals = self.directive_locals)
21265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
21275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
21285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not type.is_cfunction:
21295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos,
21305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "Suite attached to non-function declaration")
21315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Remember the actual type according to the function header
21325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # written here, because the type in the symbol table entry
21335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # may be different if we're overriding a C method inherited
21345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # from the base type of an extension type.
21355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.type = type
21365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        type.is_overridable = self.overridable
21375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        declarator = self.declarator
21385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        while not hasattr(declarator, 'args'):
21395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            declarator = declarator.base
21405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.cfunc_declarator = declarator
21425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.args = declarator.args
21435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        opt_arg_count = self.cfunc_declarator.optional_arg_count
21455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (self.visibility == 'public' or self.api) and opt_arg_count:
21465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.cfunc_declarator.pos,
21475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  "Function with optional arguments may not be declared "
21485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  "public or api")
21495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (type.exception_check == '+' and self.visibility != 'extern'):
21515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            warning(self.cfunc_declarator.pos,
21525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    "Only extern functions can throw C++ exceptions.")
21535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for formal_arg, type_arg in zip(self.args, type.args):
21555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.align_argument_type(env, type_arg)
21565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            formal_arg.type = type_arg.type
21575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            formal_arg.name = type_arg.name
21585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            formal_arg.cname = type_arg.cname
21595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self._validate_type_visibility(type_arg.type, type_arg.pos, env)
21615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if type_arg.type.is_fused:
21635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.has_fused_arguments = True
21645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if type_arg.type.is_buffer and 'inline' in self.modifiers:
21665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                warning(formal_arg.pos, "Buffer unpacking not optimized away.", 1)
21675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if type_arg.type.is_buffer:
21695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.type.nogil:
21705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(formal_arg.pos,
21715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          "Buffer may not be acquired without the GIL. "
21725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          "Consider using memoryview slices instead.")
21735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif 'inline' in self.modifiers:
21745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    warning(formal_arg.pos, "Buffer unpacking not optimized away.", 1)
21755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self._validate_type_visibility(type.return_type, self.pos, env)
21775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        name = name_declarator.name
21795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cname = name_declarator.cname
21805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        type.is_const_method = self.is_const_method
21825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry = env.declare_cfunction(
21835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            name, type, self.pos,
21845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cname = cname, visibility = self.visibility, api = self.api,
21855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            defining = self.body is not None, modifiers = self.modifiers)
21865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry.inline_func_in_pxd = self.inline_in_pxd
21875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.return_type = type.return_type
21885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.return_type.is_array and self.visibility != 'extern':
21895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos,
21905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "Function cannot return an array")
21915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.return_type.is_cpp_class:
21925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.return_type.check_nullary_constructor(self.pos, "used as a return value")
21935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.overridable and not env.is_module_scope:
21955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if len(self.args) < 1 or not self.args[0].type.is_pyobject:
21965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # An error will be produced in the cdef function
21975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.overridable = False
21985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.declare_cpdef_wrapper(env)
22005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.create_local_scope(env)
22015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def declare_cpdef_wrapper(self, env):
22035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.overridable:
22045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            name = self.entry.name
22055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
22065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.py_func = DefNode(pos = self.pos,
22075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   name = self.entry.name,
22085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   args = self.args,
22095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   star_arg = None,
22105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   starstar_arg = None,
22115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   doc = self.doc,
22125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   body = py_func_body,
22135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   is_wrapper = 1)
22145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.py_func.is_module_scope = env.is_module_scope
22155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.py_func.analyse_declarations(env)
22165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.entry.as_variable = self.py_func.entry
22175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.entry.used = self.entry.as_variable.used = True
22185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Reset scope entry the above cfunction
22195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.entries[name] = self.entry
22205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (not self.entry.is_final_cmethod and
22215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                (not env.is_module_scope or Options.lookup_module_cpdef)):
22225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
22235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.body = StatListNode(self.pos, stats=[self.override, self.body])
22245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _validate_type_visibility(self, type, pos, env):
22265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
22275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Ensure that types used in cdef functions are public or api, or
22285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        defined in a C header.
22295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
22305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        public_or_api = (self.visibility == 'public' or self.api)
22315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry = getattr(type, 'entry', None)
22325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if public_or_api and entry and env.is_module_scope:
22335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not (entry.visibility in ('public', 'extern') or
22345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    entry.api or entry.in_cinclude):
22355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(pos, "Function declared public or api may not have "
22365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           "private types")
22375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def call_self_node(self, omit_optional_args=0, is_module_scope=0):
22395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import ExprNodes
22405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        args = self.type.args
22415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if omit_optional_args:
22425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            args = args[:len(args) - self.type.optional_arg_count]
22435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        arg_names = [arg.name for arg in args]
22445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if is_module_scope:
22455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
22465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
22475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
22485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
22495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
22505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        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)
22515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
22525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def declare_arguments(self, env):
22545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.type.args:
22555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not arg.name:
22565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(arg.pos, "Missing argument name")
22575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.declare_argument(env, arg)
22585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def need_gil_acquisition(self, lenv):
22605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.type.with_gil
22615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def nogil_check(self, env):
22635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        type = self.type
22645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        with_gil = type.with_gil
22655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if type.nogil and not with_gil:
22665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if type.return_type.is_pyobject:
22675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos,
22685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      "Function with Python return type cannot be declared nogil")
22695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for entry in self.local_scope.var_entries:
22705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if entry.type.is_pyobject and not entry.in_with_gil_block:
22715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(self.pos, "Function declared nogil has Python locals or temporaries")
22725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
22745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.local_scope.directives = env.directives
22755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.py_func is not None:
22765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # this will also analyse the default values
22775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.py_func = self.py_func.analyse_expressions(env)
22785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
22795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.analyse_default_values(env)
22805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.acquire_gil = self.need_gil_acquisition(self.local_scope)
22815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
22825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def needs_assignment_synthesis(self, env, code=None):
22845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return False
22855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
22875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        scope = self.local_scope
22885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        arg_decls = []
22895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        type = self.type
22905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in type.args[:len(type.args)-type.optional_arg_count]:
22915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_decl = arg.declaration_code()
22925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry = scope.lookup(arg.name)
22935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not entry.cf_used:
22945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg_decl = 'CYTHON_UNUSED %s' % arg_decl
22955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_decls.append(arg_decl)
22965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if with_dispatch and self.overridable:
22975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            dispatch_arg = PyrexTypes.c_int_type.declaration_code(
22985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Naming.skip_dispatch_cname)
22995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.override:
23005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg_decls.append(dispatch_arg)
23015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
23025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg_decls.append('CYTHON_UNUSED %s' % dispatch_arg)
23035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if type.optional_arg_count and with_opt_args:
23045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
23055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if type.has_varargs:
23065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_decls.append("...")
23075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not arg_decls:
23085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_decls = ["void"]
23095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if cname is None:
23105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cname = self.entry.func_cname
23115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entity = type.function_header_code(cname, ', '.join(arg_decls))
23125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.entry.visibility == 'private' and '::' not in cname:
23135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            storage_class = "static "
23145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
23155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            storage_class = ""
23165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        dll_linkage = None
23175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        modifiers = code.build_function_modifiers(self.entry.func_modifiers)
23185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        header = self.return_type.declaration_code(entity, dll_linkage=dll_linkage)
23205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #print (storage_class, modifiers, header)
23215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.template_declaration:
23225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(self.template_declaration)
23235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("%s%s%s {" % (storage_class, modifiers, header))
23245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_argument_declarations(self, env, code):
23265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        scope = self.local_scope
23275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
23285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.default:
23295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                entry = scope.lookup(arg.name)
23305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.override or entry.cf_used:
23315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    result = arg.calculate_default_value_code(code)
23325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln('%s = %s;' % (
23335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        arg.type.declaration_code(arg.cname), result))
23345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_keyword_list(self, code):
23365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
23375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_argument_parsing_code(self, env, code):
23395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        i = 0
23405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        used = 0
23415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.type.optional_arg_count:
23425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            scope = self.local_scope
23435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('if (%s) {' % Naming.optional_args_cname)
23445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for arg in self.args:
23455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.default:
23465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    entry = scope.lookup(arg.name)
23475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if self.override or entry.cf_used:
23485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.putln('if (%s->%sn > %s) {' %
23495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   (Naming.optional_args_cname,
23505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    Naming.pyrex_prefix, i))
23515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        declarator = arg.declarator
23525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        while not hasattr(declarator, 'name'):
23535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            declarator = declarator.base
23545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.putln('%s = %s->%s;' %
23555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   (arg.cname, Naming.optional_args_cname,
23565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    self.type.opt_arg_cname(declarator.name)))
23575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        used += 1
23585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    i += 1
23595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for _ in range(used):
23605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('}')
23615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('}')
23625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_argument_conversion_code(self, code):
23645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
23655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_argument_type_tests(self, code):
23675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Generate type tests for args whose type in a parent
23685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # class is a supertype of the declared type.
23695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.type.args:
23705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.needs_type_test:
23715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.generate_arg_type_test(arg, code)
23725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif arg.type.is_pyobject and not arg.accept_none:
23735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.generate_arg_none_check(arg, code)
23745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def error_value(self):
23765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.return_type.is_pyobject:
23775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return "0"
23785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
23795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            #return None
23805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.entry.type.exception_value
23815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def caller_will_check_exceptions(self):
23835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.entry.type.exception_check
23845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_wrapper_functions(self, code):
23865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # If the C signature of a function has changed, we need to generate
23875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # wrappers to put in the slots here.
23885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        k = 0
23895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry = self.entry
23905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        func_type = entry.type
23915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        while entry.prev_entry is not None:
23925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            k += 1
23935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry = entry.prev_entry
23945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
23955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln()
23965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.generate_function_header(code,
23975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          0,
23985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          with_dispatch = entry.type.is_overridable,
23995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          with_opt_args = entry.type.optional_arg_count,
24005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          cname = entry.func_cname)
24015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.return_type.is_void:
24025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put('return ')
24035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            args = self.type.args
24045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
24055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.type.is_overridable:
24065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arglist.append(Naming.skip_dispatch_cname)
24075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif func_type.is_overridable:
24085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arglist.append('0')
24095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.type.optional_arg_count:
24105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arglist.append(Naming.optional_args_cname)
24115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif func_type.optional_arg_count:
24125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arglist.append('NULL')
24135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
24145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('}')
24155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class PyArgDeclNode(Node):
24185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Argument which must be a Python object (used
24195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # for * and ** arguments).
24205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
24215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # name        string
24225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # entry       Symtab.Entry
24235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # annotation  ExprNode or None   Py3 argument annotation
24245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = []
24255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_self_arg = False
24265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_type_arg = False
24275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
24295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry.generate_function_definitions(env, code)
24305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class DecoratorNode(Node):
24325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # A decorator
24335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
24345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # decorator    NameNode or CallNode or AttributeNode
24355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ['decorator']
24365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class DefNode(FuncDefNode):
24395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # A Python function definition.
24405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
24415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # name          string                 the Python name of the function
24425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # lambda_name   string                 the internal name of a lambda 'function'
24435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # decorators    [DecoratorNode]        list of decorators
24445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # args          [CArgDeclNode]         formal arguments
24455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # doc           EncodedString or None
24465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # body          StatListNode
24475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # return_type_annotation
24485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #               ExprNode or None       the Py3 return type annotation
24495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
24505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  The following subnode is constructed internally
24515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  when the def statement is inside a Python class definition.
24525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
24535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  fused_py_func        DefNode     The original fused cpdef DefNode
24545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #                                   (in case this is a specialization)
24555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  specialized_cpdefs   [DefNode]   list of specialized cpdef DefNodes
24565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  py_cfunc_node  PyCFunctionNode/InnerFunctionNode   The PyCFunction to create and assign
24575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
24585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # decorator_indirection IndirectionNode Used to remove __Pyx_Method_ClassMethod for fused functions
24595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
24615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    lambda_name = None
24635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    reqd_kw_flags_cname = "0"
24645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_wrapper = 0
24655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    no_assignment_synthesis = 0
24665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    decorators = None
24675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return_type_annotation = None
24685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    entry = None
24695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    acquire_gil = 0
24705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    self_in_stararg = 0
24715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    py_cfunc_node = None
24725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    requires_classobj = False
24735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    defaults_struct = None # Dynamic kwrds structure name
24745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    doc = None
24755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    fused_py_func = False
24775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    specialized_cpdefs = None
24785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    py_wrapper = None
24795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    py_wrapper_required = True
24805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    func_cname = None
24815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    defaults_getter = None
24835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, pos, **kwds):
24855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        FuncDefNode.__init__(self, pos, **kwds)
24865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        k = rk = r = 0
24875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
24885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.kw_only:
24895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                k += 1
24905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not arg.default:
24915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    rk += 1
24925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not arg.default:
24935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                r += 1
24945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.num_kwonly_args = k
24955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.num_required_kw_args = rk
24965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.num_required_args = r
24975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def as_cfunction(self, cfunc=None, scope=None, overridable=True, returns=None):
24995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.star_arg:
25005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.star_arg.pos, "cdef function cannot have star argument")
25015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.starstar_arg:
25025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
25035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if cfunc is None:
25045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cfunc_args = []
25055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for formal_arg in self.args:
25065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                name_declarator, type = formal_arg.analyse(scope, nonempty=1)
25075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
25085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                          cname = None,
25095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                          type = py_object_type,
25105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                          pos = formal_arg.pos))
25115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
25125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              args = cfunc_args,
25135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              has_varargs = False,
25145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              exception_value = None,
25155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              exception_check = False,
25165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              nogil = False,
25175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              with_gil = False,
25185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              is_overridable = overridable)
25195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cfunc = CVarDefNode(self.pos, type=cfunc_type)
25205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
25215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if scope is None:
25225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                scope = cfunc.scope
25235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cfunc_type = cfunc.type
25245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
25255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "wrong number of arguments")
25265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(cfunc.pos, "previous declaration here")
25275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for i, (formal_arg, type_arg) in enumerate(zip(self.args, cfunc_type.args)):
25285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                name_declarator, type = formal_arg.analyse(scope, nonempty=1,
25295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                           is_self_arg = (i == 0 and scope.is_c_class_scope))
25305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if type is None or type is PyrexTypes.py_object_type:
25315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    formal_arg.type = type_arg.type
25325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    formal_arg.name_declarator = name_declarator
25335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import ExprNodes
25345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if cfunc_type.exception_value is None:
25355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            exception_value = None
25365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
25375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
25385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        declarator = CFuncDeclaratorNode(self.pos,
25395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
25405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         args = self.args,
25415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         has_varargs = False,
25425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         exception_check = cfunc_type.exception_check,
25435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         exception_value = exception_value,
25445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         with_gil = cfunc_type.with_gil,
25455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         nogil = cfunc_type.nogil)
25465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return CFuncDefNode(self.pos,
25475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            modifiers = [],
25485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
25495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            declarator = declarator,
25505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            body = self.body,
25515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            doc = self.doc,
25525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            overridable = cfunc_type.is_overridable,
25535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            type = cfunc_type,
25545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            with_gil = cfunc_type.with_gil,
25555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            nogil = cfunc_type.nogil,
25565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            visibility = 'private',
25575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            api = False,
25585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            directive_locals = getattr(cfunc, 'directive_locals', {}),
25595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            directive_returns = returns)
25605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def is_cdef_func_compatible(self):
25625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """Determines if the function's signature is compatible with a
25635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cdef function.  This can be used before calling
25645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        .as_cfunction() to see if that will be successful.
25655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
25665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.needs_closure:
25675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return False
25685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.star_arg or self.starstar_arg:
25695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return False
25705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return True
25715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
25735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.is_classmethod = self.is_staticmethod = False
25745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.decorators:
25755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for decorator in self.decorators:
25765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                func = decorator.decorator
25775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if func.is_name:
25785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.is_classmethod |= func.name == 'classmethod'
25795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.is_staticmethod |= func.name == 'staticmethod'
25805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_classmethod and env.lookup_here('classmethod'):
25825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # classmethod() was overridden - not much we can do here ...
25835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.is_classmethod = False
25845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_staticmethod and env.lookup_here('staticmethod'):
25855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # staticmethod() was overridden - not much we can do here ...
25865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.is_staticmethod = False
25875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.name == '__new__' and env.is_py_class_scope:
25895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.is_staticmethod = 1
25905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.analyse_argument_types(env)
25925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.name == '<lambda>':
25935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.declare_lambda_function(env)
25945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
25955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.declare_pyfunction(env)
25965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.analyse_signature(env)
25985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.return_type = self.entry.signature.return_type()
25995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.create_local_scope(env)
26005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
26015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.py_wrapper = DefNodeWrapper(
26025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.pos,
26035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            target=self,
26045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            name=self.entry.name,
26055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            args=self.args,
26065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            star_arg=self.star_arg,
26075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            starstar_arg=self.starstar_arg,
26085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return_type=self.return_type)
26095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.py_wrapper.analyse_declarations(env)
26105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
26115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_argument_types(self, env):
26125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.directive_locals = env.directives['locals']
26135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        allow_none_for_extension_args = env.directives['allow_none_for_extension_args']
26145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
26155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        f2s = env.fused_to_specific
26165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.fused_to_specific = None
26175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
26185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
26195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if hasattr(arg, 'name'):
26205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                name_declarator = None
26215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
26225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                base_type = arg.base_type.analyse(env)
26235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                name_declarator, type = \
26245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.declarator.analyse(base_type, env)
26255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg.name = name_declarator.name
26265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg.type = type
26275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
26285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if type.is_fused:
26295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.has_fused_arguments = True
26305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
26315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.align_argument_type(env, arg)
26325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if name_declarator and name_declarator.cname:
26335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos,
26345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    "Python function argument cannot have C name specification")
26355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.type = arg.type.as_argument_type()
26365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.hdr_type = None
26375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.needs_conversion = 0
26385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.needs_type_test = 0
26395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.is_generic = 1
26405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.type.is_pyobject or arg.type.is_buffer or arg.type.is_memoryviewslice:
26415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.or_none:
26425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.accept_none = True
26435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif arg.not_none:
26445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.accept_none = False
26455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif (arg.type.is_extension_type or arg.type.is_builtin_type
26465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      or arg.type.is_buffer or arg.type.is_memoryviewslice):
26475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if arg.default and arg.default.constant_result is None:
26485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        # special case: def func(MyType obj = None)
26495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        arg.accept_none = True
26505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    else:
26515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        # default depends on compiler directive
26525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        arg.accept_none = allow_none_for_extension_args
26535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
26545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    # probably just a plain 'object'
26555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.accept_none = True
26565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
26575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg.accept_none = True # won't be used, but must be there
26585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.not_none:
26595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(arg.pos, "Only Python type arguments can have 'not None'")
26605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.or_none:
26615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(arg.pos, "Only Python type arguments can have 'or None'")
26625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
26635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.fused_to_specific = f2s
26645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
26655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_signature(self, env):
26665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.entry.is_special:
26675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.decorators:
26685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "special functions of cdef classes cannot have decorators")
26695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
26705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
26715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Use the simpler calling signature for zero- and one-argument functions.
26725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.entry.signature is TypeSlots.pyfunction_signature:
26735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if len(self.args) == 0:
26745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.entry.signature = TypeSlots.pyfunction_noargs
26755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif len(self.args) == 1:
26765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if self.args[0].default is None and not self.args[0].kw_only:
26775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        self.entry.signature = TypeSlots.pyfunction_onearg
26785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif self.entry.signature is TypeSlots.pymethod_signature:
26795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if len(self.args) == 1:
26805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.entry.signature = TypeSlots.unaryfunc
26815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif len(self.args) == 2:
26825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if self.args[1].default is None and not self.args[1].kw_only:
26835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        self.entry.signature = TypeSlots.ibinaryfunc
26845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
26855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        sig = self.entry.signature
26865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        nfixed = sig.num_fixed_args()
26875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if sig is TypeSlots.pymethod_signature and nfixed == 1 \
26885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               and len(self.args) == 0 and self.star_arg:
26895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # this is the only case where a diverging number of
26905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # arguments is not an error - when we have no explicit
26915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # 'self' parameter as in method(*args)
26925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            sig = self.entry.signature = TypeSlots.pyfunction_signature # self is not 'really' used
26935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.self_in_stararg = 1
26945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            nfixed = 0
26955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
26965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_staticmethod and env.is_c_class_scope:
26975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            nfixed = 0
26985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.self_in_stararg = True  # FIXME: why for staticmethods?
26995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.entry.signature = sig = copy.copy(sig)
27015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            sig.fixed_arg_format = "*"
27025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            sig.is_staticmethod = True
27035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            sig.has_generic_args = True
27045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if ((self.is_classmethod or self.is_staticmethod) and
27065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.has_fused_arguments and env.is_c_class_scope):
27075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            del self.decorator_indirection.stats[:]
27085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i in range(min(nfixed, len(self.args))):
27105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg = self.args[i]
27115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.is_generic = 0
27125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if sig.is_self_arg(i) and not self.is_staticmethod:
27135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.is_classmethod:
27145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.is_type_arg = 1
27155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.hdr_type = arg.type = Builtin.type_type
27165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
27175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.is_self_arg = 1
27185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.hdr_type = arg.type = env.parent_type
27195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg.needs_conversion = 0
27205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
27215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg.hdr_type = sig.fixed_arg_type(i)
27225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not arg.type.same_as(arg.hdr_type):
27235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
27245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        arg.needs_type_test = 1
27255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    else:
27265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        arg.needs_conversion = 1
27275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.needs_conversion:
27285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg.hdr_cname = Naming.arg_prefix + arg.name
27295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
27305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg.hdr_cname = Naming.var_prefix + arg.name
27315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if nfixed > len(self.args):
27335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.bad_signature()
27345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
27355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif nfixed < len(self.args):
27365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not sig.has_generic_args:
27375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.bad_signature()
27385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for arg in self.args:
27395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.is_generic and \
27405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        (arg.type.is_extension_type or arg.type.is_builtin_type):
27415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.needs_type_test = 1
27425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def bad_signature(self):
27445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        sig = self.entry.signature
27455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        expected_str = "%d" % sig.num_fixed_args()
27465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if sig.has_generic_args:
27475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            expected_str += " or more"
27485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        name = self.name
27495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if name.startswith("__") and name.endswith("__"):
27505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            desc = "Special method"
27515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
27525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            desc = "Method"
27535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        error(self.pos,
27545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "%s %s has wrong number of arguments "
27555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "(%d declared, %s expected)" % (
27565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                desc, self.name, len(self.args), expected_str))
27575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def declare_pyfunction(self, env):
27595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #print "DefNode.declare_pyfunction:", self.name, "in", env ###
27605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        name = self.name
27615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry = env.lookup_here(name)
27625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if entry:
27635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.is_final_cmethod and not env.parent_type.is_final_type:
27645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "Only final types can have final Python (def/cpdef) methods")
27655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (entry.type.is_cfunction and not entry.is_builtin_cmethod
27665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                and not self.is_wrapper):
27675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                warning(self.pos, "Overriding cdef method with def method.", 5)
27685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry = env.declare_pyfunction(name, self.pos, allow_redefine=not self.is_wrapper)
27695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry = entry
27705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        prefix = env.next_id(env.scope_prefix)
27715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry.pyfunc_cname = Naming.pyfunc_prefix + prefix + name
27725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if Options.docstrings:
27735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry.doc = embed_position(self.pos, self.doc)
27745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry.doc_cname = Naming.funcdoc_prefix + prefix + name
27755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.is_special:
27765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if entry.name in TypeSlots.invisible or not entry.doc or (entry.name in '__getattr__' and env.directives['fast_getattr']):
27775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    entry.wrapperbase_cname = None
27785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
27795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    entry.wrapperbase_cname = Naming.wrapperbase_prefix + prefix + name
27805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
27815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry.doc = None
27825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def declare_lambda_function(self, env):
27845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry = env.declare_lambda_function(self.lambda_name, self.pos)
27855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry.doc = None
27865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry = entry
27875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry.pyfunc_cname = entry.cname
27885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def declare_arguments(self, env):
27905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
27915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not arg.name:
27925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(arg.pos, "Missing argument name")
27935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.needs_conversion:
27945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
27955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.type.is_pyobject:
27965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.entry.init = "0"
27975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
27985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg.entry = self.declare_argument(env, arg)
27995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.entry.is_arg = 1
28005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.entry.used = 1
28015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.entry.is_self_arg = arg.is_self_arg
28025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.declare_python_arg(env, self.star_arg)
28035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.declare_python_arg(env, self.starstar_arg)
28045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def declare_python_arg(self, env, arg):
28065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if arg:
28075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if env.directives['infer_types'] != False:
28085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                type = PyrexTypes.unspecified_type
28095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
28105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                type = py_object_type
28115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry = env.declare_var(arg.name, type, arg.pos)
28125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry.is_arg = 1
28135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry.used = 1
28145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry.init = "0"
28155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry.xdecref_cleanup = 1
28165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.entry = entry
28175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
28195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.local_scope.directives = env.directives
28205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.analyse_default_values(env)
28215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.needs_assignment_synthesis(env) and self.decorators:
28235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for decorator in self.decorators[::-1]:
28245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                decorator.decorator = decorator.decorator.analyse_expressions(env)
28255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.py_wrapper.prepare_argument_coercion(env)
28275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
28285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def needs_assignment_synthesis(self, env, code=None):
28305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_wrapper or self.specialized_cpdefs or self.entry.is_fused_specialized:
28315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return False
28325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_staticmethod:
28335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return True
28345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.no_assignment_synthesis:
28355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return False
28365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Should enable for module level as well, that will require more testing...
28375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.entry.is_anonymous:
28385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return True
28395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if env.is_module_scope:
28405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if code is None:
28415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return env.directives['binding']
28425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
28435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return code.globalstate.directives['binding']
28445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return env.is_py_class_scope or env.is_closure_scope
28455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def error_value(self):
28475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.entry.signature.error_value
28485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def caller_will_check_exceptions(self):
28505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.entry.signature.exception_check
28515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
28535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.defaults_getter:
28545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.defaults_getter.generate_function_definitions(env, code)
28555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Before closure cnames are mangled
28575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.py_wrapper_required:
28585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # func_cname might be modified by @cname
28595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.py_wrapper.func_cname = self.entry.func_cname
28605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.py_wrapper.generate_function_definitions(env, code)
28615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        FuncDefNode.generate_function_definitions(self, env, code)
28625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_header(self, code, with_pymethdef, proto_only=0):
28645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if proto_only:
28655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.py_wrapper_required:
28665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.py_wrapper.generate_function_header(
28675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code, with_pymethdef, True)
28685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
28695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        arg_code_list = []
28705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.entry.signature.has_dummy_arg:
28715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self_arg = 'PyObject *%s' % Naming.self_cname
28725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.needs_outer_scope:
28735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self_arg = 'CYTHON_UNUSED ' + self_arg
28745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_code_list.append(self_arg)
28755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        def arg_decl_code(arg):
28775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry = arg.entry
28785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.in_closure:
28795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                cname = entry.original_cname
28805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
28815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                cname = entry.cname
28825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            decl = entry.type.declaration_code(cname)
28835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not entry.cf_used:
28845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                decl = 'CYTHON_UNUSED ' + decl
28855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return decl
28865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
28885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_code_list.append(arg_decl_code(arg))
28895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.star_arg:
28905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_code_list.append(arg_decl_code(self.star_arg))
28915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.starstar_arg:
28925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_code_list.append(arg_decl_code(self.starstar_arg))
28935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        arg_code = ', '.join(arg_code_list)
28945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        dc = self.return_type.declaration_code(self.entry.pyfunc_cname)
28955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        decls_code = code.globalstate['decls']
28975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        preprocessor_guard = self.get_preprocessor_guard()
28985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if preprocessor_guard:
28995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            decls_code.putln(preprocessor_guard)
29005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        decls_code.putln(
29015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "static %s(%s); /* proto */" % (dc, arg_code))
29025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if preprocessor_guard:
29035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            decls_code.putln("#endif")
29045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("static %s(%s) {" % (dc, arg_code))
29055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_argument_declarations(self, env, code):
29075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
29085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_keyword_list(self, code):
29105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
29115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_argument_parsing_code(self, env, code):
29135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Move arguments into closure if required
29145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        def put_into_closure(entry):
29155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.in_closure:
29165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('%s = %s;' % (entry.cname, entry.original_cname))
29175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_var_incref(entry)
29185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_var_giveref(entry)
29195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
29205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            put_into_closure(arg.entry)
29215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.star_arg, self.starstar_arg:
29225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg:
29235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                put_into_closure(arg.entry)
29245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_argument_type_tests(self, code):
29265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
29275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class DefNodeWrapper(FuncDefNode):
29305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # DefNode python wrapper code generator
29315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    defnode = None
29335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    target = None # Target DefNode
29345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, *args, **kwargs):
29365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        FuncDefNode.__init__(self, *args, **kwargs)
29375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.num_kwonly_args = self.target.num_kwonly_args
29385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.num_required_kw_args = self.target.num_required_kw_args
29395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.num_required_args = self.target.num_required_args
29405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.self_in_stararg = self.target.self_in_stararg
29415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.signature = None
29425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
29445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        target_entry = self.target.entry
29455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        name = self.name
29465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        prefix = env.next_id(env.scope_prefix)
29475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        target_entry.func_cname = Naming.pywrap_prefix + prefix + name
29485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        target_entry.pymethdef_cname = Naming.pymethdef_prefix + prefix + name
29495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.signature = target_entry.signature
29515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def prepare_argument_coercion(self, env):
29535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # This is only really required for Cython utility code at this time,
29545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # everything else can be done during code generation.  But we expand
29555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # all utility code here, simply because we cannot easily distinguish
29565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # different code types.
29575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
29585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not arg.type.is_pyobject:
29595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not arg.type.create_from_py_utility_code(env):
29605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    pass # will fail later
29615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif arg.hdr_type and not arg.hdr_type.is_pyobject:
29625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not arg.hdr_type.create_to_py_utility_code(env):
29635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    pass # will fail later
29645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def signature_has_nongeneric_args(self):
29665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        argcount = len(self.args)
29675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if argcount == 0 or (
29685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                argcount == 1 and (self.args[0].is_self_arg or
29695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   self.args[0].is_type_arg)):
29705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return 0
29715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return 1
29725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def signature_has_generic_args(self):
29745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.signature.has_generic_args
29755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_body(self, code):
29775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        args = []
29785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.signature.has_dummy_arg:
29795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            args.append(Naming.self_cname)
29805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
29815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.hdr_type and not (arg.type.is_memoryviewslice or
29825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     arg.type.is_struct or
29835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     arg.type.is_complex):
29845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                args.append(arg.type.cast_code(arg.entry.cname))
29855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
29865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                args.append(arg.entry.cname)
29875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.star_arg:
29885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            args.append(self.star_arg.entry.cname)
29895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.starstar_arg:
29905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            args.append(self.starstar_arg.entry.cname)
29915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        args = ', '.join(args)
29925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.return_type.is_void:
29935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put('%s = ' % Naming.retval_cname)
29945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('%s(%s);' % (
29955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.target.entry.pyfunc_cname, args))
29965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
29985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lenv = self.target.local_scope
29995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Generate C code for header and body of function
30005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.mark_pos(self.pos)
30015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("")
30025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("/* Python wrapper */")
30035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        preprocessor_guard = self.target.get_preprocessor_guard()
30045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if preprocessor_guard:
30055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(preprocessor_guard)
30065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
30075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.enter_cfunc_scope()
30085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.return_from_error_cleanup_label = code.new_label()
30095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
30105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        with_pymethdef = (self.target.needs_assignment_synthesis(env, code) or
30115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          self.target.pymethdef_required)
30125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_function_header(code, with_pymethdef)
30135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_argument_declarations(lenv, code)
30145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        tempvardecl_code = code.insertion_point()
30155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
30165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.return_type.is_pyobject:
30175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            retval_init = ' = 0'
30185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
30195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            retval_init = ''
30205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.return_type.is_void:
30215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('%s%s;' % (
30225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.return_type.declaration_code(Naming.retval_cname),
30235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                retval_init))
30245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_declare_refcount_context()
30255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_setup_refcount_context('%s (wrapper)' % self.name)
30265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
30275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_argument_parsing_code(lenv, code)
30285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_argument_type_tests(code)
30295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_function_body(code)
30305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
30315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Go back and insert temp variable declarations
30325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        tempvardecl_code.put_temp_declarations(code.funcstate)
30335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
30345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.mark_pos(self.pos)
30355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("")
30365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("/* function exit code */")
30375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
30385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Error cleanup
30395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if code.error_label in code.labels_used:
30405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_goto(code.return_label)
30415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_label(code.error_label)
30425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for cname, type in code.funcstate.all_managed_temps():
30435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_xdecref(cname, type)
30445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            err_val = self.error_value()
30455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if err_val is not None:
30465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("%s = %s;" % (Naming.retval_cname, err_val))
30475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
30485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Non-error return cleanup
30495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_label(code.return_label)
30505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry in lenv.var_entries:
30515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.is_arg and entry.type.is_pyobject:
30525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_var_decref(entry)
30535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
30545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_finish_refcount_context()
30555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.return_type.is_void:
30565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("return %s;" % Naming.retval_cname)
30575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('}')
30585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.exit_cfunc_scope()
30595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if preprocessor_guard:
30605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("#endif /*!(%s)*/" % preprocessor_guard)
30615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
30625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_header(self, code, with_pymethdef, proto_only=0):
30635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        arg_code_list = []
30645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        sig = self.signature
30655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
30665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if sig.has_dummy_arg or self.self_in_stararg:
30675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_code = "PyObject *%s" % Naming.self_cname
30685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not sig.has_dummy_arg:
30695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg_code = 'CYTHON_UNUSED ' + arg_code
30705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_code_list.append(arg_code)
30715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
30725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
30735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not arg.is_generic:
30745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.is_self_arg or arg.is_type_arg:
30755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg_code_list.append("PyObject *%s" % arg.hdr_cname)
30765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
30775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg_code_list.append(
30785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        arg.hdr_type.declaration_code(arg.hdr_cname))
30795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry = self.target.entry
30805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
30815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_code_list.append("CYTHON_UNUSED PyObject *unused")
30825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if entry.scope.is_c_class_scope and entry.name == "__ipow__":
30835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_code_list.append("CYTHON_UNUSED PyObject *unused")
30845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if sig.has_generic_args:
30855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_code_list.append(
30865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "PyObject *%s, PyObject *%s"
30875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    % (Naming.args_cname, Naming.kwds_cname))
30885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        arg_code = ", ".join(arg_code_list)
30895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
30905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Prevent warning: unused function '__pyx_pw_5numpy_7ndarray_1__getbuffer__'
30915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        mf = ""
30925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (entry.name in ("__getbuffer__", "__releasebuffer__")
30935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            and entry.scope.is_c_class_scope):
30945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            mf = "CYTHON_UNUSED "
30955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            with_pymethdef = False
30965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
30975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        dc = self.return_type.declaration_code(entry.func_cname)
30985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        header = "static %s%s(%s)" % (mf, dc, arg_code)
30995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("%s; /*proto*/" % header)
31005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if proto_only:
31025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.target.fused_py_func:
31035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # If we are the specialized version of the cpdef, we still
31045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # want the prototype for the "fused cpdef", in case we're
31055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # checking to see if our method was overridden in Python
31065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.target.fused_py_func.generate_function_header(
31075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    code, with_pymethdef, proto_only=True)
31085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
31095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (Options.docstrings and entry.doc and
31115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                not self.target.fused_py_func and
31125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                not entry.scope.is_property_scope and
31135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                (not entry.is_special or entry.wrapperbase_cname)):
31145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # h_code = code.globalstate['h_code']
31155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            docstr = entry.doc
31165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if docstr.is_unicode:
31185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                docstr = docstr.utf8encode()
31195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
31215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                'static char %s[] = "%s";' % (
31225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    entry.doc_cname,
31235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    split_string_literal(escape_byte_string(docstr))))
31245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.is_special:
31265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('#if CYTHON_COMPILING_IN_CPYTHON')
31275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln(
31285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    "struct wrapperbase %s;" % entry.wrapperbase_cname)
31295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('#endif')
31305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if with_pymethdef or self.target.fused_py_func:
31325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put(
31335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "static PyMethodDef %s = " %
31345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    entry.pymethdef_cname)
31355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_pymethoddef(self.target.entry, ";", allow_skip=False)
31365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("%s {" % header)
31375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_argument_declarations(self, env, code):
31395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
31405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.is_generic:
31415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.needs_conversion:
31425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln("PyObject *%s = 0;" % arg.hdr_cname)
31435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
31445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put_var_declaration(arg.entry)
31455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry in env.var_entries:
31465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.is_arg:
31475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_var_declaration(entry)
31485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_argument_parsing_code(self, env, code):
31505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Generate fast equivalent of PyArg_ParseTuple call for
31515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # generic arguments, if any, including args/kwargs
31525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_error_label = code.new_error_label()
31535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        our_error_label = code.error_label
31545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        end_label = code.new_label("argument_unpacking_done")
31555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        has_kwonly_args = self.num_kwonly_args > 0
31575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        has_star_or_kw_args = self.star_arg is not None \
31585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            or self.starstar_arg is not None or has_kwonly_args
31595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
31615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not arg.type.is_pyobject:
31625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not arg.type.create_from_py_utility_code(env):
31635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    pass # will fail later
31645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.signature_has_generic_args():
31665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if has_star_or_kw_args:
31675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "This method cannot have * or keyword arguments")
31685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.generate_argument_conversion_code(code)
31695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif not self.signature_has_nongeneric_args():
31715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # func(*args) or func(**kw) or func(*args, **kw)
31725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.generate_stararg_copy_code(code)
31735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
31755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.generate_tuple_and_keyword_parsing_code(self.args, end_label, code)
31765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.error_label = old_error_label
31785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if code.label_used(our_error_label):
31795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not code.label_used(end_label):
31805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(end_label)
31815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_label(our_error_label)
31825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if has_star_or_kw_args:
31835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.generate_arg_decref(self.star_arg, code)
31845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.starstar_arg:
31855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if self.starstar_arg.entry.xdecref_cleanup:
31865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.put_var_xdecref_clear(self.starstar_arg.entry)
31875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    else:
31885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.put_var_decref_clear(self.starstar_arg.entry)
31895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_add_traceback(self.target.entry.qualified_name)
31905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_finish_refcount_context()
31915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("return %s;" % self.error_value())
31925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if code.label_used(end_label):
31935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_label(end_label)
31945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_arg_xdecref(self, arg, code):
31965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if arg:
31975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_var_xdecref_clear(arg.entry)
31985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
31995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_arg_decref(self, arg, code):
32005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if arg:
32015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_var_decref_clear(arg.entry)
32025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
32035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_stararg_copy_code(self, code):
32045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.star_arg:
32055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.globalstate.use_utility_code(
32065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                UtilityCode.load_cached("RaiseArgTupleInvalid", "FunctionArguments.c"))
32075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
32085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       Naming.args_cname)
32095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
32105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.name, Naming.args_cname, self.error_value()))
32115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("}")
32125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
32135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.starstar_arg:
32145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.star_arg:
32155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                kwarg_check = "unlikely(%s)" % Naming.kwds_cname
32165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
32175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                kwarg_check = "%s" % Naming.kwds_cname
32185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
32195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
32205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Naming.kwds_cname, Naming.kwds_cname)
32215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.use_utility_code(
32225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            UtilityCode.load_cached("KeywordStringCheck", "FunctionArguments.c"))
32235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
32245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
32255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                kwarg_check, Naming.kwds_cname, self.name,
32265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                bool(self.starstar_arg), self.error_value()))
32275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
32285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.starstar_arg:
32295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
32305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.starstar_arg.entry.cname,
32315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    Naming.kwds_cname,
32325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    Naming.kwds_cname))
32335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("if (unlikely(!%s)) return %s;" % (
32345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.starstar_arg.entry.cname, self.error_value()))
32355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.starstar_arg.entry.xdecref_cleanup = 0
32365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_gotref(self.starstar_arg.entry.cname)
32375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
32385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.self_in_stararg and not self.target.is_staticmethod:
32395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # need to create a new tuple with 'self' inserted as first item
32405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put("%s = PyTuple_New(PyTuple_GET_SIZE(%s)+1); if (unlikely(!%s)) " % (
32415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.star_arg.entry.cname,
32425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    Naming.args_cname,
32435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.star_arg.entry.cname))
32445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.starstar_arg:
32455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("{")
32465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_decref_clear(self.starstar_arg.entry.cname, py_object_type)
32475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("return %s;" % self.error_value())
32485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("}")
32495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
32505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("return %s;" % self.error_value())
32515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_gotref(self.star_arg.entry.cname)
32525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_incref(Naming.self_cname, py_object_type)
32535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_giveref(Naming.self_cname)
32545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("PyTuple_SET_ITEM(%s, 0, %s);" % (
32555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.star_arg.entry.cname, Naming.self_cname))
32565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            temp = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False)
32575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("for (%s=0; %s < PyTuple_GET_SIZE(%s); %s++) {" % (
32585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                temp, temp, Naming.args_cname, temp))
32595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("PyObject* item = PyTuple_GET_ITEM(%s, %s);" % (
32605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Naming.args_cname, temp))
32615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_incref("item", py_object_type)
32625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_giveref("item")
32635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("PyTuple_SET_ITEM(%s, %s+1, item);" % (
32645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.star_arg.entry.cname, temp))
32655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("}")
32665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.funcstate.release_temp(temp)
32675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.star_arg.entry.xdecref_cleanup = 0
32685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif self.star_arg:
32695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_incref(Naming.args_cname, py_object_type)
32705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("%s = %s;" % (
32715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.star_arg.entry.cname,
32725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    Naming.args_cname))
32735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.star_arg.entry.xdecref_cleanup = 0
32745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
32755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_tuple_and_keyword_parsing_code(self, args, success_label, code):
32765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        argtuple_error_label = code.new_label("argtuple_error")
32775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
32785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        positional_args = []
32795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        required_kw_only_args = []
32805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        optional_kw_only_args = []
32815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in args:
32825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.is_generic:
32835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.default:
32845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if not arg.is_self_arg and not arg.is_type_arg:
32855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        if arg.kw_only:
32865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            optional_kw_only_args.append(arg)
32875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        else:
32885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            positional_args.append(arg)
32895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif arg.kw_only:
32905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    required_kw_only_args.append(arg)
32915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif not arg.is_self_arg and not arg.is_type_arg:
32925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    positional_args.append(arg)
32935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
32945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # sort required kw-only args before optional ones to avoid special
32955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # cases in the unpacking code
32965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        kw_only_args = required_kw_only_args + optional_kw_only_args
32975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
32985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        min_positional_args = self.num_required_args - self.num_required_kw_args
32995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if len(args) > 0 and (args[0].is_self_arg or args[0].is_type_arg):
33005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            min_positional_args -= 1
33015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        max_positional_args = len(positional_args)
33025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        has_fixed_positional_count = not self.star_arg and \
33035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            min_positional_args == max_positional_args
33045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        has_kw_only_args = bool(kw_only_args)
33055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
33065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.num_required_kw_args:
33075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.globalstate.use_utility_code(
33085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                UtilityCode.load_cached("RaiseKeywordRequired", "FunctionArguments.c"))
33095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
33105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.starstar_arg or self.star_arg:
33115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.generate_stararg_init_code(max_positional_args, code)
33125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
33135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('{')
33145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        all_args = tuple(positional_args) + tuple(kw_only_args)
33155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("static PyObject **%s[] = {%s,0};" % (
33165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            Naming.pykwdlist_cname,
33175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            ','.join([ '&%s' % code.intern_identifier(arg.name)
33185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        for arg in all_args ])))
33195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
33205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Before being converted and assigned to the target variables,
33215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # borrowed references to all unpacked argument values are
33225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # collected into a local PyObject* array called "values",
33235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # regardless if they were taken from default arguments,
33245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # positional arguments or keyword arguments.  Note that
33255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # C-typed default arguments are handled at conversion time,
33265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # so their array value is NULL in the end if no argument
33275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # was passed for them.
33285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_argument_values_setup_code(all_args, code)
33295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
33305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # --- optimised code when we receive keyword arguments
33315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("if (%s(%s)) {" % (
33325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            (self.num_required_kw_args > 0) and "likely" or "unlikely",
33335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            Naming.kwds_cname))
33345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_keyword_unpacking_code(
33355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            min_positional_args, max_positional_args,
33365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            has_fixed_positional_count, has_kw_only_args,
33375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            all_args, argtuple_error_label, code)
33385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
33395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # --- optimised code when we do not receive any keyword arguments
33405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
33415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Python raises arg tuple related errors first, so we must
33425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # check the length here
33435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if min_positional_args == max_positional_args and not self.star_arg:
33445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                compare = '!='
33455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
33465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                compare = '<'
33475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
33485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    Naming.args_cname, compare, min_positional_args))
33495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_goto(argtuple_error_label)
33505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
33515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.num_required_kw_args:
33525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # pure error case: keywords required but not passed
33535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if max_positional_args > min_positional_args and not self.star_arg:
33545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
33555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        Naming.args_cname, max_positional_args))
33565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(argtuple_error_label)
33575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('} else {')
33585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for i, arg in enumerate(kw_only_args):
33595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not arg.default:
33605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    pystring_cname = code.intern_identifier(arg.name)
33615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    # required keyword-only argument missing
33625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
33635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            self.name,
33645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            pystring_cname))
33655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln(code.error_goto(self.pos))
33665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    break
33675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
33685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
33695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # optimised tuple unpacking code
33705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('} else {')
33715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if min_positional_args == max_positional_args:
33725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # parse the exact number of positional arguments from
33735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # the args tuple
33745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for i, arg in enumerate(positional_args):
33755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (i, Naming.args_cname, i))
33765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
33775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # parse the positional arguments from the variable length
33785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # args tuple and reject illegal argument tuple sizes
33795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
33805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.star_arg:
33815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln('default:')
33825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                reversed_args = list(enumerate(positional_args))[::-1]
33835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for i, arg in reversed_args:
33845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if i >= min_positional_args-1:
33855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.put('case %2d: ' % (i+1))
33865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (i, Naming.args_cname, i))
33875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if min_positional_args == 0:
33885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put('case  0: ')
33895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('break;')
33905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.star_arg:
33915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if min_positional_args:
33925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        for i in range(min_positional_args-1, -1, -1):
33935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            code.putln('case %2d:' % i)
33945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.put_goto(argtuple_error_label)
33955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
33965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put('default: ')
33975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put_goto(argtuple_error_label)
33985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('}')
33995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
34005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('}') # end of the conditional unpacking blocks
34015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
34025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Convert arg values to their final type and assign them.
34035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Also inject non-Python default arguments, which do cannot
34045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # live in the values[] array.
34055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i, arg in enumerate(all_args):
34065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.generate_arg_assignment(arg, "values[%d]" % i, code)
34075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
34085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('}') # end of the whole argument unpacking block
34095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
34105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if code.label_used(argtuple_error_label):
34115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_goto(success_label)
34125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_label(argtuple_error_label)
34135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.globalstate.use_utility_code(
34145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                UtilityCode.load_cached("RaiseArgTupleInvalid", "FunctionArguments.c"))
34155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
34165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.name, has_fixed_positional_count,
34175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    min_positional_args, max_positional_args,
34185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    Naming.args_cname))
34195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(code.error_goto(self.pos))
34205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
34215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_arg_assignment(self, arg, item, code):
34225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if arg.type.is_pyobject:
34235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Python default arguments were already stored in 'item' at the very beginning
34245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.is_generic:
34255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
34265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry = arg.entry
34275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("%s = %s;" % (entry.cname, item))
34285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
34295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            func = arg.type.from_py_function
34305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if func:
34315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.default:
34325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    # C-typed default arguments must be handled here
34335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln('if (%s) {' % item)
34345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                rhs = "%s(%s)" % (func, item)
34355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.type.is_enum:
34365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    rhs = arg.type.cast_code(rhs)
34375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("%s = %s; %s" % (
34385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.entry.cname,
34395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    rhs,
34405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
34415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.default:
34425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln('} else {')
34435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln(
34445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        "%s = %s;" % (
34455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            arg.entry.cname,
34465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            arg.calculate_default_value_code(code)))
34475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if arg.type.is_memoryviewslice:
34485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.put_incref_memoryviewslice(arg.entry.cname,
34495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                        have_gil=True)
34505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln('}')
34515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
34525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
34535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
34545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_stararg_init_code(self, max_positional_args, code):
34555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.starstar_arg:
34565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.starstar_arg.entry.xdecref_cleanup = 0
34575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
34585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.starstar_arg.entry.cname,
34595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.starstar_arg.entry.cname,
34605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.error_value()))
34615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_gotref(self.starstar_arg.entry.cname)
34625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.star_arg:
34635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.star_arg.entry.xdecref_cleanup = 0
34645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
34655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    Naming.args_cname,
34665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    max_positional_args))
34675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s));' % (
34685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.star_arg.entry.cname, Naming.args_cname,
34695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    max_positional_args, Naming.args_cname))
34705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
34715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.starstar_arg:
34725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_decref_clear(self.starstar_arg.entry.cname, py_object_type)
34735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_finish_refcount_context()
34745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('return %s;' % self.error_value())
34755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('}')
34765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_gotref(self.star_arg.entry.cname)
34775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('} else {')
34785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
34795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_incref(Naming.empty_tuple, py_object_type)
34805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('}')
34815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
34825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_argument_values_setup_code(self, args, code):
34835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        max_args = len(args)
34845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # the 'values' array collects borrowed references to arguments
34855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # before doing any type coercion etc.
34865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("PyObject* values[%d] = {%s};" % (
34875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            max_args, ','.join('0'*max_args)))
34885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
34895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.target.defaults_struct:
34905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('%s *%s = __Pyx_CyFunction_Defaults(%s, %s);' % (
34915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.target.defaults_struct, Naming.dynamic_args_cname,
34925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.target.defaults_struct, Naming.self_cname))
34935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
34945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # assign borrowed Python default values to the values array,
34955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # so that they can be overwritten by received arguments below
34965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i, arg in enumerate(args):
34975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.default and arg.type.is_pyobject:
34985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                default_value = arg.calculate_default_value_code(code)
34995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('values[%d] = %s;' % (i, arg.type.as_pyobject(default_value)))
35005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
35015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
35025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        has_fixed_positional_count, has_kw_only_args,
35035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        all_args, argtuple_error_label, code):
35045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('Py_ssize_t kw_args;')
35055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('const Py_ssize_t pos_args = PyTuple_GET_SIZE(%s);' % Naming.args_cname)
35065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # copy the values from the args tuple and check that it's not too long
35075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('switch (pos_args) {')
35085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.star_arg:
35095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('default:')
35105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i in range(max_positional_args-1, -1, -1):
35115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put('case %2d: ' % (i+1))
35125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
35135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    i, Naming.args_cname, i))
35145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('case  0: break;')
35155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.star_arg:
35165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put('default: ') # more arguments than allowed
35175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_goto(argtuple_error_label)
35185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('}')
35195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
35205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # The code above is very often (but not always) the same as
35215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # the optimised non-kwargs tuple unpacking code, so we keep
35225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # the code block above at the very top, before the following
35235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # 'external' PyDict_Size() call, to make it easy for the C
35245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # compiler to merge the two separate tuple unpacking
35255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # implementations into one when they turn out to be identical.
35265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
35275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # If we received kwargs, fill up the positional/required
35285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # arguments with values from the kw dict
35295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('kw_args = PyDict_Size(%s);' % Naming.kwds_cname)
35305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.num_required_args or max_positional_args > 0:
35315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            last_required_arg = -1
35325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for i, arg in enumerate(all_args):
35335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not arg.default:
35345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    last_required_arg = i
35355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if last_required_arg < max_positional_args:
35365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                last_required_arg = max_positional_args-1
35375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if max_positional_args > 0:
35385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('switch (pos_args) {')
35395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for i, arg in enumerate(all_args[:last_required_arg+1]):
35405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if max_positional_args > 0 and i <= max_positional_args:
35415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if self.star_arg and i == max_positional_args:
35425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.putln('default:')
35435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    else:
35445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.putln('case %2d:' % i)
35455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pystring_cname = code.intern_identifier(arg.name)
35465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.default:
35475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if arg.kw_only:
35485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        # optional kw-only args are handled separately below
35495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        continue
35505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln('if (kw_args > 0) {')
35515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    # don't overwrite default argument
35525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
35535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        Naming.kwds_cname, pystring_cname))
35545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln('if (value) { values[%d] = value; kw_args--; }' % i)
35555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln('}')
35565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
35575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln('if (likely((values[%d] = PyDict_GetItem(%s, %s)) != 0)) kw_args--;' % (
35585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        i, Naming.kwds_cname, pystring_cname))
35595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if i < min_positional_args:
35605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        if i == 0:
35615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            # special case: we know arg 0 is missing
35625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            code.put('else ')
35635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            code.put_goto(argtuple_error_label)
35645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        else:
35655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            # print the correct number of values (args or
35665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            # kwargs) that were passed into positional
35675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            # arguments up to this point
35685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            code.putln('else {')
35695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            code.globalstate.use_utility_code(
35705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                UtilityCode.load_cached("RaiseArgTupleInvalid", "FunctionArguments.c"))
35715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
35725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    self.name, has_fixed_positional_count,
35735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    min_positional_args, max_positional_args, i))
35745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            code.putln(code.error_goto(self.pos))
35755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            code.putln('}')
35765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    elif arg.kw_only:
35775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.putln('else {')
35785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
35795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                self.name, pystring_cname))
35805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.putln(code.error_goto(self.pos))
35815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.putln('}')
35825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if max_positional_args > 0:
35835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('}')
35845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
35855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if has_kw_only_args:
35865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # unpack optional keyword-only arguments separately because
35875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # checking for interned strings in a dict is faster than iterating
35885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.generate_optional_kwonly_args_unpacking_code(all_args, code)
35895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
35905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('if (unlikely(kw_args > 0)) {')
35915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # non-positional/-required kw args left in dict: default args,
35925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # kw-only args, **kwargs or error
35935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #
35945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # This is sort of a catch-all: except for checking required
35955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # arguments, this will always do the right thing for unpacking
35965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # keyword arguments, so that we can concentrate on optimising
35975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # common cases above.
35985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if max_positional_args == 0:
35995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pos_arg_count = "0"
36005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif self.star_arg:
36015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("const Py_ssize_t used_pos_args = (pos_args < %d) ? pos_args : %d;" % (
36025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    max_positional_args, max_positional_args))
36035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pos_arg_count = "used_pos_args"
36045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
36055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pos_arg_count = "pos_args"
36065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.use_utility_code(
36075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            UtilityCode.load_cached("ParseKeywords", "FunctionArguments.c"))
36085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
36095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) %s' % (
36105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Naming.kwds_cname,
36115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Naming.pykwdlist_cname,
36125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.starstar_arg and self.starstar_arg.entry.cname or '0',
36135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pos_arg_count,
36145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.name,
36155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.error_goto(self.pos)))
36165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('}')
36175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
36185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_optional_kwonly_args_unpacking_code(self, all_args, code):
36195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        optional_args = []
36205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        first_optional_arg = -1
36215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i, arg in enumerate(all_args):
36225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not arg.kw_only or not arg.default:
36235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                continue
36245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not optional_args:
36255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                first_optional_arg = i
36265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            optional_args.append(arg.name)
36275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if optional_args:
36285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if len(optional_args) > 1:
36295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # if we receive more than the named kwargs, we either have **kwargs
36305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # (in which case we must iterate anyway) or it's an error (which we
36315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # also handle during iteration) => skip this part if there are more
36325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('if (kw_args > 0 && %s(kw_args <= %d)) {' % (
36335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    not self.starstar_arg and 'likely' or '',
36345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    len(optional_args)))
36355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('Py_ssize_t index;')
36365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # not unrolling the loop here reduces the C code overhead
36375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('for (index = %d; index < %d && kw_args > 0; index++) {' % (
36385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    first_optional_arg, first_optional_arg + len(optional_args)))
36395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
36405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('if (kw_args == 1) {')
36415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('const Py_ssize_t index = %d;' % first_optional_arg)
36425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('PyObject* value = PyDict_GetItem(%s, *%s[index]);' % (
36435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Naming.kwds_cname, Naming.pykwdlist_cname))
36445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('if (value) { values[index] = value; kw_args--; }')
36455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if len(optional_args) > 1:
36465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln('}')
36475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('}')
36485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
36495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_argument_conversion_code(self, code):
36505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Generate code to convert arguments from signature type to
36515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # declared type, if needed.  Also copies signature arguments
36525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # into closure fields.
36535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
36545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.needs_conversion:
36555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.generate_arg_conversion(arg, code)
36565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
36575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_arg_conversion(self, arg, code):
36585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Generate conversion code for one argument.
36595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_type = arg.hdr_type
36605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        new_type = arg.type
36615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if old_type.is_pyobject:
36625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.default:
36635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("if (%s) {" % arg.hdr_cname)
36645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
36655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("assert(%s); {" % arg.hdr_cname)
36665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.generate_arg_conversion_from_pyobject(arg, code)
36675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("}")
36685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif new_type.is_pyobject:
36695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.generate_arg_conversion_to_pyobject(arg, code)
36705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
36715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if new_type.assignable_from(old_type):
36725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln(
36735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
36745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
36755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(arg.pos,
36765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    "Cannot convert 1 argument from '%s' to '%s'" %
36775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        (old_type, new_type))
36785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
36795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_arg_conversion_from_pyobject(self, arg, code):
36805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        new_type = arg.type
36815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        func = new_type.from_py_function
36825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # copied from CoerceFromPyTypeNode
36835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if func:
36845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lhs = arg.entry.cname
36855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs = "%s(%s)" % (func, arg.hdr_cname)
36865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if new_type.is_enum:
36875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                rhs = PyrexTypes.typecast(new_type, PyrexTypes.c_long_type, rhs)
36885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("%s = %s; %s" % (
36895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                lhs,
36905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                rhs,
36915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
36925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
36935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(arg.pos,
36945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "Cannot convert Python object argument to type '%s'"
36955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    % new_type)
36965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
36975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_arg_conversion_to_pyobject(self, arg, code):
36985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_type = arg.hdr_type
36995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        func = old_type.to_py_function
37005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if func:
37015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("%s = %s(%s); %s" % (
37025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg.entry.cname,
37035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                func,
37045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg.hdr_cname,
37055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.error_goto_if_null(arg.entry.cname, arg.pos)))
37065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_var_gotref(arg.entry)
37075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
37085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(arg.pos,
37095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "Cannot convert argument of type '%s' to Python object"
37105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    % old_type)
37115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_argument_type_tests(self, code):
37135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Generate type tests for args whose signature
37145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # type is PyObject * and whose declared type is
37155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # a subtype thereof.
37165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
37175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.needs_type_test:
37185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.generate_arg_type_test(arg, code)
37195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif not arg.accept_none and (arg.type.is_pyobject or
37205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          arg.type.is_buffer or
37215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          arg.type.is_memoryviewslice):
37225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.generate_arg_none_check(arg, code)
37235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def error_value(self):
37255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.signature.error_value
37265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class GeneratorDefNode(DefNode):
37295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Generator function node that creates a new generator instance when called.
37305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
37315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # gbody          GeneratorBodyDefNode   the function implementing the generator
37325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
37335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_generator = True
37355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    needs_closure = True
37365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = DefNode.child_attrs + ["gbody"]
37385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, **kwargs):
37405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # XXX: don't actually needs a body
37415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        kwargs['body'] = StatListNode(kwargs['pos'], stats=[])
37425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(GeneratorDefNode, self).__init__(**kwargs)
37435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
37455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(GeneratorDefNode, self).analyse_declarations(env)
37465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.gbody.local_scope = self.local_scope
37475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.gbody.analyse_declarations(env)
37485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_body(self, env, code):
37505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        body_cname = self.gbody.entry.func_cname
37515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('{')
37535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('__pyx_GeneratorObject *gen = __Pyx_Generator_New('
37545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   '(__pyx_generator_body_t) %s, (PyObject *) %s); %s' % (
37555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       body_cname, Naming.cur_scope_cname,
37565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       code.error_goto_if_null('gen', self.pos)))
37575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_decref(Naming.cur_scope_cname, py_object_type)
37585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.requires_classobj:
37595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            classobj_cname = 'gen->classobj'
37605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('%s = __Pyx_CyFunction_GetClassObj(%s);' % (
37615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                classobj_cname, Naming.self_cname))
37625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_incref(classobj_cname, py_object_type)
37635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_giveref(classobj_cname)
37645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_finish_refcount_context()
37655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('return (PyObject *) gen;')
37665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('}')
37675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
37695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.use_utility_code(UtilityCode.load_cached("Generator", "Generator.c"))
37705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.gbody.generate_function_header(code, proto=True)
37725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(GeneratorDefNode, self).generate_function_definitions(env, code)
37735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.gbody.generate_function_definitions(env, code)
37745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class GeneratorBodyDefNode(DefNode):
37775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Main code body of a generator implemented as a DefNode.
37785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
37795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_generator_body = True
37815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, pos=None, name=None, body=None):
37835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(GeneratorBodyDefNode, self).__init__(
37845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pos=pos, body=body, name=name, doc=None,
37855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            args=[], star_arg=None, starstar_arg=None)
37865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def declare_generator_body(self, env):
37885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        prefix = env.next_id(env.scope_prefix)
37895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        name = env.next_id('generator')
37905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cname = Naming.genbody_prefix + prefix + name
37915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry = env.declare_var(None, py_object_type, self.pos,
37925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                cname=cname, visibility='private')
37935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry.func_cname = cname
37945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry.qualified_name = EncodedString(self.name)
37955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry = entry
37965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
37985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.analyse_argument_types(env)
37995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.declare_generator_body(env)
38005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
38015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_header(self, code, proto=False):
38025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        header = "static PyObject *%s(__pyx_GeneratorObject *%s, PyObject *%s)" % (
38035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.entry.func_cname,
38045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            Naming.generator_cname,
38055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            Naming.sent_value_cname)
38065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if proto:
38075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('%s; /* proto */' % header)
38085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
38095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('%s /* generator body */\n{' % header)
38105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
38115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
38125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lenv = self.local_scope
38135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
38145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Generate closure function definitions
38155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_function_definitions(lenv, code)
38165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
38175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Generate C code for header and body of function
38185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.enter_cfunc_scope()
38195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.return_from_error_cleanup_label = code.new_label()
38205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
38215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Top-level constants used by this function
38225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.mark_pos(self.pos)
38235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_cached_builtins_decls(lenv, code)
38245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Function header
38255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("")
38265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_function_header(code)
38275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        closure_init_code = code.insertion_point()
38285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Local variables
38295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("PyObject *%s = NULL;" % Naming.retval_cname)
38305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        tempvardecl_code = code.insertion_point()
38315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_declare_refcount_context()
38325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_setup_refcount_context(self.entry.name)
38335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
38345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Resume switch point.
38355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.funcstate.init_closure_temps(lenv.scope_class.type.scope)
38365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        resume_code = code.insertion_point()
38375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        first_run_label = code.new_label('first_run')
38385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.use_label(first_run_label)
38395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_label(first_run_label)
38405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('%s' %
38415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   (code.error_goto_if_null(Naming.sent_value_cname, self.pos)))
38425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
38435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Function body
38445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_function_body(env, code)
38455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Closure initialization
38465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if lenv.scope_class.type.scope.entries:
38475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            closure_init_code.putln('%s = %s;' % (
38485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                lenv.scope_class.type.declaration_code(Naming.cur_scope_cname),
38495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                lenv.scope_class.type.cast_code('%s->closure' %
38505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                Naming.generator_cname)))
38515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
38525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.mark_pos(self.pos)
38535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("")
38545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("/* function exit code */")
38555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
38565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # on normal generator termination, we do not take the exception propagation
38575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # path: no traceback info is required and not creating it is much faster
38585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.body.is_terminator:
38595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('PyErr_SetNone(PyExc_StopIteration);')
38605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Error cleanup
38615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if code.error_label in code.labels_used:
38625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.body.is_terminator:
38635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(code.return_label)
38645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_label(code.error_label)
38655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for cname, type in code.funcstate.all_managed_temps():
38665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_xdecref(cname, type)
38675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_add_traceback(self.entry.qualified_name)
38685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
38695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Non-error return cleanup
38705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_label(code.return_label)
38715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_xdecref(Naming.retval_cname, py_object_type)
38725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('%s->resume_label = -1;' % Naming.generator_cname)
38735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # clean up as early as possible to help breaking any reference cycles
38745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('__Pyx_Generator_clear((PyObject*)%s);' % Naming.generator_cname)
38755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_finish_refcount_context()
38765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('return NULL;')
38775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
38785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
38795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Go back and insert temp variable declarations
38805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        tempvardecl_code.put_temp_declarations(code.funcstate)
38815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ----- Generator resume code
38825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        resume_code.putln("switch (%s->resume_label) {" % (
38835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       Naming.generator_cname))
38845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        resume_code.putln("case 0: goto %s;" % first_run_label)
38855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
38865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i, label in code.yield_labels:
38875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            resume_code.putln("case %d: goto %s;" % (i, label))
38885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        resume_code.putln("default: /* CPython raises the right error here */")
38895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        resume_code.put_finish_refcount_context()
38905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        resume_code.putln("return NULL;")
38915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        resume_code.putln("}")
38925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
38935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.exit_cfunc_scope()
38945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
38955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
38965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class OverrideCheckNode(StatNode):
38975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # A Node for dispatching to the def method if it
38985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # is overriden.
38995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
39005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  py_func
39015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
39025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  args
39035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  func_temp
39045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  body
39055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
39065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ['body']
39075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
39085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    body = None
39095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
39105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
39115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.args = env.arg_entries
39125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.py_func.is_module_scope:
39135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            first_arg = 0
39145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
39155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            first_arg = 1
39165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import ExprNodes
39175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.func_node = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
39185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        call_node = ExprNodes.SimpleCallNode(
39195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.pos, function=self.func_node,
39205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            args=[ ExprNodes.NameNode(self.pos, name=arg.name)
39215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   for arg in self.args[first_arg:] ])
39225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = ReturnStatNode(self.pos, value=call_node)
39235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = self.body.analyse_expressions(env)
39245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
39255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
39265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
39275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
39285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Check to see if we are an extension type
39295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.py_func.is_module_scope:
39305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self_arg = "((PyObject *)%s)" % Naming.module_cname
39315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
39325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self_arg = "((PyObject *)%s)" % self.args[0].cname
39335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("/* Check if called by wrapper */")
39345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
39355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("/* Check if overridden in Python */")
39365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.py_func.is_module_scope:
39375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("else {")
39385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
39395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
39405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        func_node_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
39415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.func_node.set_cname(func_node_temp)
39425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # need to get attribute manually--scope would return cdef method
39435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.use_utility_code(
39445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            UtilityCode.load_cached("PyObjectGetAttrStr", "ObjectHandling.c"))
39455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        err = code.error_goto_if_null(func_node_temp, self.pos)
39465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("%s = __Pyx_PyObject_GetAttrStr(%s, %s); %s" % (
39475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            func_node_temp, self_arg, interned_attr_cname, err))
39485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_gotref(func_node_temp)
39495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        is_builtin_function_or_method = "PyCFunction_Check(%s)" % func_node_temp
39505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        is_overridden = "(PyCFunction_GET_FUNCTION(%s) != (PyCFunction)%s)" % (
39515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            func_node_temp, self.py_func.entry.func_cname)
39525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("if (!%s || %s) {" % (is_builtin_function_or_method, is_overridden))
39535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
39545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
39555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_decref_clear(func_node_temp, PyrexTypes.py_object_type)
39565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.funcstate.release_temp(func_node_temp)
39575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
39585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
39595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ClassDefNode(StatNode, BlockNode):
39605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    pass
39615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
39625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class PyClassDefNode(ClassDefNode):
39635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  A Python class definition.
39645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
39655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  name     EncodedString   Name of the class
39665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  doc      string or None
39675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  body     StatNode        Attribute definition code
39685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  entry    Symtab.Entry
39695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  scope    PyClassScope
39705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  decorators    [DecoratorNode]        list of decorators or None
39715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
39725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  The following subnodes are constructed internally:
39735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
39745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  dict     DictNode   Class dictionary or Py3 namespace
39755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  classobj ClassNode  Class object
39765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  target   NameNode   Variable to assign class object to
39775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
39785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["body", "dict", "metaclass", "mkw", "bases", "class_result",
39795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   "target", "class_cell", "decorators"]
39805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    decorators = None
39815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    class_result = None
39825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_py3_style_class = False  # Python3 style class (kwargs)
39835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    metaclass = None
39845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    mkw = None
39855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
39865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, pos, name, bases, doc, body, decorators=None,
39875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 keyword_args=None, starstar_arg=None, force_py3_semantics=False):
39885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        StatNode.__init__(self, pos)
39895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.name = name
39905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.doc = doc
39915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = body
39925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.decorators = decorators
39935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.bases = bases
39945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import ExprNodes
39955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.doc and Options.docstrings:
39965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            doc = embed_position(self.pos, self.doc)
39975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            doc_node = ExprNodes.StringNode(pos, value=doc)
39985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
39995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            doc_node = None
40005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
40015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        allow_py2_metaclass = not force_py3_semantics
40025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if keyword_args or starstar_arg:
40035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            allow_py2_metaclass = False
40045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.is_py3_style_class = True
40055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if keyword_args and not starstar_arg:
40065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for i, item in list(enumerate(keyword_args.key_value_pairs))[::-1]:
40075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if item.key.value == 'metaclass':
40085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        if self.metaclass is not None:
40095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            error(item.pos, "keyword argument 'metaclass' passed multiple times")
40105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        # special case: we already know the metaclass,
40115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        # so we don't need to do the "build kwargs,
40125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        # find metaclass" dance at runtime
40135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        self.metaclass = item.value
40145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        del keyword_args.key_value_pairs[i]
40155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if starstar_arg:
40165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.mkw = ExprNodes.KeywordArgsNode(
40175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    pos, keyword_args=keyword_args and keyword_args.key_value_pairs or [],
40185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    starstar_arg=starstar_arg)
40195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif keyword_args.key_value_pairs:
40205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.mkw = keyword_args
40215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
40225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                assert self.metaclass is not None
40235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
40245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if force_py3_semantics or self.bases or self.mkw or self.metaclass:
40255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.metaclass is None:
40265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if starstar_arg:
40275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    # **kwargs may contain 'metaclass' arg
40285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    mkdict = self.mkw
40295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
40305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    mkdict = None
40315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if (not mkdict and
40325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        self.bases.is_sequence_constructor and
40335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        not self.bases.args):
40345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    pass  # no base classes => no inherited metaclass
40355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
40365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.metaclass = ExprNodes.PyClassMetaclassNode(
40375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        pos, mkw=mkdict, bases=self.bases)
40385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                needs_metaclass_calculation = False
40395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
40405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                needs_metaclass_calculation = True
40415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
40425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.dict = ExprNodes.PyClassNamespaceNode(
40435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pos, name=name, doc=doc_node,
40445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                metaclass=self.metaclass, bases=self.bases, mkw=self.mkw)
40455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.classobj = ExprNodes.Py3ClassNode(
40465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pos, name=name,
40475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                bases=self.bases, dict=self.dict, doc=doc_node,
40485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                metaclass=self.metaclass, mkw=self.mkw,
40495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                calculate_metaclass=needs_metaclass_calculation,
40505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                allow_py2_metaclass=allow_py2_metaclass)
40515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
40525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # no bases, no metaclass => old style class creation
40535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.dict = ExprNodes.DictNode(pos, key_value_pairs=[])
40545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.classobj = ExprNodes.ClassNode(
40555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pos, name=name,
40565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                bases=bases, dict=self.dict, doc=doc_node)
40575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
40585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.target = ExprNodes.NameNode(pos, name=name)
40595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.class_cell = ExprNodes.ClassCellInjectorNode(self.pos)
40605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
40615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def as_cclass(self):
40625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
40635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Return this node as if it were declared as an extension class
40645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
40655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_py3_style_class:
40665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.classobj.pos, "Python3 style class could not be represented as C class")
40675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
40685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        bases = self.classobj.bases.args
40695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if len(bases) == 0:
40705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            base_class_name = None
40715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            base_class_module = None
40725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif len(bases) == 1:
40735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            base = bases[0]
40745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            path = []
40755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            from ExprNodes import AttributeNode, NameNode
40765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            while isinstance(base, AttributeNode):
40775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                path.insert(0, base.attribute)
40785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                base = base.obj
40795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if isinstance(base, NameNode):
40805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                path.insert(0, base.name)
40815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                base_class_name = path[-1]
40825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if len(path) > 1:
40835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    base_class_module = u'.'.join(path[:-1])
40845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
40855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    base_class_module = None
40865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
40875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.classobj.bases.args.pos, "Invalid base class")
40885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
40895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.classobj.bases.args.pos, "C class may only have one base class")
40905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
40915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
40925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return CClassDefNode(self.pos,
40935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             visibility = 'private',
40945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             module_name = None,
40955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             class_name = self.name,
40965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             base_class_module = base_class_module,
40975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             base_class_name = base_class_name,
40985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             decorators = self.decorators,
40995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             body = self.body,
41005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             in_pxd = False,
41015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             doc = self.doc)
41025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
41035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def create_scope(self, env):
41045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        genv = env
41055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        while genv.is_py_class_scope or genv.is_c_class_scope:
41065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            genv = genv.outer_scope
41075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
41085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return cenv
41095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
41105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
41115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        class_result = self.classobj
41125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.decorators:
41135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            from ExprNodes import SimpleCallNode
41145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for decorator in self.decorators[::-1]:
41155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                class_result = SimpleCallNode(
41165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    decorator.pos,
41175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    function = decorator.decorator,
41185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    args = [class_result])
41195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.decorators = None
41205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.class_result = class_result
41215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.class_result.analyse_declarations(env)
41225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.target.analyse_target_declaration(env)
41235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cenv = self.create_scope(env)
41245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cenv.directives = env.directives
41255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cenv.class_obj_cname = self.target.entry.cname
41265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.analyse_declarations(cenv)
41275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
41285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
41295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.bases:
41305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.bases = self.bases.analyse_expressions(env)
41315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.metaclass:
41325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.metaclass = self.metaclass.analyse_expressions(env)
41335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.mkw:
41345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.mkw = self.mkw.analyse_expressions(env)
41355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.dict = self.dict.analyse_expressions(env)
41365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.class_result = self.class_result.analyse_expressions(env)
41375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        genv = env.global_scope()
41385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cenv = self.scope
41395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = self.body.analyse_expressions(cenv)
41405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.target.analyse_target_expression(env, self.classobj)
41415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.class_cell = self.class_cell.analyse_expressions(cenv)
41425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
41435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
41445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
41455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_lambda_definitions(self.scope, code)
41465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_function_definitions(self.scope, code)
41475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
41485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
41495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.pyclass_stack.append(self)
41505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cenv = self.scope
41515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.bases:
41525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.bases.generate_evaluation_code(code)
41535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.mkw:
41545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.mkw.generate_evaluation_code(code)
41555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.metaclass:
41565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.metaclass.generate_evaluation_code(code)
41575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.dict.generate_evaluation_code(code)
41585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cenv.namespace_cname = cenv.class_obj_cname = self.dict.result()
41595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.class_cell.generate_evaluation_code(code)
41605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
41615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.class_result.generate_evaluation_code(code)
41625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.class_cell.generate_injection_code(
41635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code, self.class_result.result())
41645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.class_cell.generate_disposal_code(code)
41655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
41665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.target.generate_assignment_code(self.class_result, code)
41675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.dict.generate_disposal_code(code)
41685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.dict.free_temps(code)
41695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.metaclass:
41705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.metaclass.generate_disposal_code(code)
41715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.metaclass.free_temps(code)
41725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.mkw:
41735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.mkw.generate_disposal_code(code)
41745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.mkw.free_temps(code)
41755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.bases:
41765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.bases.generate_disposal_code(code)
41775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.bases.free_temps(code)
41785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.pyclass_stack.pop()
41795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
41805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CClassDefNode(ClassDefNode):
41815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  An extension type definition.
41825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
41835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  visibility         'private' or 'public' or 'extern'
41845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  typedef_flag       boolean
41855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  api                boolean
41865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  module_name        string or None    For import of extern type objects
41875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  class_name         string            Unqualified name of class
41885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  as_name            string or None    Name to declare as in this scope
41895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  base_class_module  string or None    Module containing the base class
41905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  base_class_name    string or None    Name of the base class
41915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  objstruct_name     string or None    Specified C name of object struct
41925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  typeobj_name       string or None    Specified C name of type object
41935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  in_pxd             boolean           Is in a .pxd file
41945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  decorators         [DecoratorNode]   list of decorators or None
41955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  doc                string or None
41965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  body               StatNode or None
41975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  entry              Symtab.Entry
41985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  base_type          PyExtensionType or None
41995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  buffer_defaults_node DictNode or None Declares defaults for a buffer
42005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  buffer_defaults_pos
42015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
42025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["body"]
42035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    buffer_defaults_node = None
42045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    buffer_defaults_pos = None
42055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    typedef_flag = False
42065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    api = False
42075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    objstruct_name = None
42085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    typeobj_name = None
42095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    decorators = None
42105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    shadow = False
42115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
42125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def buffer_defaults(self, env):
42135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not hasattr(self, '_buffer_defaults'):
42145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            import Buffer
42155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.buffer_defaults_node:
42165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self._buffer_defaults = Buffer.analyse_buffer_options(
42175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.buffer_defaults_pos,
42185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    env, [], self.buffer_defaults_node,
42195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    need_complete=False)
42205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
42215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self._buffer_defaults = None
42225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self._buffer_defaults
42235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
42245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def declare(self, env):
42255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.module_name and self.visibility != 'extern':
42265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            module_path = self.module_name.split(".")
42275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            home_scope = env.find_imported_module(module_path, self.pos)
42285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not home_scope:
42295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return None
42305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
42315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            home_scope = env
42325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
42335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry = home_scope.declare_c_class(
42345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            name = self.class_name,
42355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pos = self.pos,
42365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            defining = 0,
42375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            implementing = 0,
42385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            module_name = self.module_name,
42395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            base_type = None,
42405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            objstruct_cname = self.objstruct_name,
42415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            typeobj_cname = self.typeobj_name,
42425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            visibility = self.visibility,
42435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            typedef_flag = self.typedef_flag,
42445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            api = self.api,
42455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            buffer_defaults = self.buffer_defaults(env),
42465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            shadow = self.shadow)
42475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
42485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
42495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #print "CClassDefNode.analyse_declarations:", self.class_name
42505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #print "...visibility =", self.visibility
42515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #print "...module_name =", self.module_name
42525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
42535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if env.in_cinclude and not self.objstruct_name:
42545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "Object struct name specification required for "
42555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "C class defined in 'extern from' block")
42565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.decorators:
42575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos,
42585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  "Decorators not allowed on cdef classes (used on type '%s')" % self.class_name)
42595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.base_type = None
42605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Now that module imports are cached, we need to
42615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # import the modules for extern classes.
42625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.module_name:
42635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.module = None
42645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for module in env.cimported_modules:
42655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if module.name == self.module_name:
42665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.module = module
42675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.module is None:
42685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.module = ModuleScope(self.module_name, None, env.context)
42695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.module.has_extern_class = 1
42705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                env.add_imported_module(self.module)
42715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
42725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.base_class_name:
42735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.base_class_module:
42745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                base_class_scope = env.find_module(self.base_class_module, self.pos)
42755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
42765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                base_class_scope = env
42775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.base_class_name == 'object':
42785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # extension classes are special and don't need to inherit from object
42795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if base_class_scope is None or base_class_scope.lookup('object') is None:
42805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.base_class_name = None
42815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.base_class_module = None
42825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    base_class_scope = None
42835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if base_class_scope:
42845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
42855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if base_class_entry:
42865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if not base_class_entry.is_type:
42875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(self.pos, "'%s' is not a type name" % self.base_class_name)
42885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    elif not base_class_entry.type.is_extension_type and \
42895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             not (base_class_entry.type.is_builtin_type and
42905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  base_class_entry.type.objstruct_cname):
42915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(self.pos, "'%s' is not an extension type" % self.base_class_name)
42925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    elif not base_class_entry.type.is_complete():
42935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(self.pos, "Base class '%s' of type '%s' is incomplete" % (
42945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            self.base_class_name, self.class_name))
42955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    elif base_class_entry.type.scope and base_class_entry.type.scope.directives and \
42965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             base_class_entry.type.is_final_type:
42975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(self.pos, "Base class '%s' of type '%s' is final" % (
42985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            self.base_class_name, self.class_name))
42995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    elif base_class_entry.type.is_builtin_type and \
43005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             base_class_entry.type.name in ('tuple', 'str', 'bytes'):
43015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(self.pos, "inheritance from PyVarObject types like '%s' is not currently supported"
43025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              % base_class_entry.type.name)
43035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    else:
43045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        self.base_type = base_class_entry.type
43055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if env.directives.get('freelist', 0) > 0:
43065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    warning(self.pos, "freelists cannot be used on subtypes, only the base class can manage them", 1)
43075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        has_body = self.body is not None
43095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if has_body and self.base_type and not self.base_type.scope:
43105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # To properly initialize inherited attributes, the base type must
43115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # be analysed before this type.
43125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.base_type.defered_declarations.append(lambda : self.analyse_declarations(env))
43135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
43145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.module_name and self.visibility != 'extern':
43165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            module_path = self.module_name.split(".")
43175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            home_scope = env.find_imported_module(module_path, self.pos)
43185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not home_scope:
43195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return
43205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
43215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            home_scope = env
43225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.visibility == 'extern':
43245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (self.module_name == '__builtin__' and
43255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.class_name in Builtin.builtin_types and
43265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                env.qualified_name[:8] != 'cpython.'): # allow overloaded names for cimporting from cpython
43275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
43285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry = home_scope.declare_c_class(
43305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            name = self.class_name,
43315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pos = self.pos,
43325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            defining = has_body and self.in_pxd,
43335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            implementing = has_body and not self.in_pxd,
43345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            module_name = self.module_name,
43355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            base_type = self.base_type,
43365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            objstruct_cname = self.objstruct_name,
43375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            typeobj_cname = self.typeobj_name,
43385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            visibility = self.visibility,
43395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            typedef_flag = self.typedef_flag,
43405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            api = self.api,
43415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            buffer_defaults = self.buffer_defaults(env),
43425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            shadow = self.shadow)
43435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.shadow:
43455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            home_scope.lookup(self.class_name).as_variable = self.entry
43465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if home_scope is not env and self.visibility == 'extern':
43475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.add_imported_entry(self.class_name, self.entry, self.pos)
43485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.scope = scope = self.entry.type.scope
43495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if scope is not None:
43505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            scope.directives = env.directives
43515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.doc and Options.docstrings:
43535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            scope.doc = embed_position(self.pos, self.doc)
43545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if has_body:
43565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.body.analyse_declarations(scope)
43575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.in_pxd:
43585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                scope.defined = 1
43595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
43605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                scope.implemented = 1
43615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.allocate_vtable_names(self.entry)
43625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for thunk in self.entry.type.defered_declarations:
43645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            thunk()
43655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
43675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.body:
43685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            scope = self.entry.type.scope
43695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.body = self.body.analyse_expressions(scope)
43705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
43715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
43735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.body:
43745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.generate_lambda_definitions(self.scope, code)
43755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.body.generate_function_definitions(self.scope, code)
43765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
43785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # This is needed to generate evaluation code for
43795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # default values of method arguments.
43805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.body:
43815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.body.generate_execution_code(code)
43825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
43845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.body:
43855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.body.annotate(code)
43865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class PropertyNode(StatNode):
43895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  Definition of a property in an extension type.
43905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
43915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  name   string
43925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  doc    EncodedString or None    Doc string
43935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  entry  Symtab.Entry
43945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  body   StatListNode
43955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["body"]
43975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
43985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
43995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry = env.declare_property(self.name, self.doc, self.pos)
44005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.entry.scope.directives = env.directives
44015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.analyse_declarations(self.entry.scope)
44025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
44045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = self.body.analyse_expressions(env)
44055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
44065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
44085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_function_definitions(env, code)
44095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
44115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
44125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
44145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.annotate(code)
44155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class GlobalNode(StatNode):
44185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Global variable declaration.
44195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
44205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # names    [string]
44215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = []
44235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
44255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for name in self.names:
44265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.declare_global(name, self.pos)
44275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
44295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
44305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
44325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
44335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class NonlocalNode(StatNode):
44365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Nonlocal variable declaration via the 'nonlocal' keyword.
44375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
44385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # names    [string]
44395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = []
44415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
44435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for name in self.names:
44445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.declare_nonlocal(name, self.pos)
44455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
44475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
44485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
44505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
44515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ExprStatNode(StatNode):
44545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  Expression used as a statement.
44555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
44565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  expr   ExprNode
44575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["expr"]
44595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
44615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import ExprNodes
44625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(self.expr, ExprNodes.GeneralCallNode):
44635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            func = self.expr.function.as_cython_attribute()
44645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if func == u'declare':
44655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                args, kwds = self.expr.explicit_args_kwds()
44665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if len(args):
44675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(self.expr.pos, "Variable names must be specified.")
44685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for var, type_node in kwds.key_value_pairs:
44695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    type = type_node.analyse_as_type(env)
44705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if type is None:
44715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(type_node.pos, "Unknown type")
44725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    else:
44735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        env.declare_var(var.value, type, var.pos, is_cdef = True)
44745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.__class__ = PassStatNode
44755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
44775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.expr.result_is_used = False # hint that .result() may safely be left empty
44785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.expr = self.expr.analyse_expressions(env)
44795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
44805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def nogil_check(self, env):
44825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.expr.type.is_pyobject and self.expr.is_temp:
44835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.gil_error()
44845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gil_message = "Discarding owned Python object"
44865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
44885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.expr.generate_evaluation_code(code)
44895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.expr.is_temp and self.expr.result():
44905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("%s;" % self.expr.result())
44915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.expr.generate_disposal_code(code)
44925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.expr.free_temps(code)
44935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
44955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.expr.generate_function_definitions(env, code)
44965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
44975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
44985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.expr.annotate(code)
44995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
45005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
45015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class AssignmentNode(StatNode):
45025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  Abstract base class for assignment nodes.
45035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
45045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  The analyse_expressions and generate_execution_code
45055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  phases of assignments are split into two sub-phases
45065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  each, to enable all the right hand sides of a
45075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  parallel assignment to be evaluated before assigning
45085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  to any of the left hand sides.
45095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
45105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
45115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.analyse_types(env)
45125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
45135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#       def analyse_expressions(self, env):
45145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#           self.analyse_expressions_1(env)
45155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#           self.analyse_expressions_2(env)
45165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
45175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
45185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_rhs_evaluation_code(code)
45195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_assignment_code(code)
45205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
45215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
45225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class SingleAssignmentNode(AssignmentNode):
45235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  The simplest case:
45245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
45255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #    a = b
45265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
45275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  lhs      ExprNode      Left hand side
45285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  rhs      ExprNode      Right hand side
45295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  first    bool          Is this guaranteed the first assignment to lhs?
45305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
45315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["lhs", "rhs"]
45325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    first = False
45335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    declaration_only = False
45345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
45355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
45365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import ExprNodes
45375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
45385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # handle declarations of the form x = cython.foo()
45395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(self.rhs, ExprNodes.CallNode):
45405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            func_name = self.rhs.function.as_cython_attribute()
45415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if func_name:
45425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                args, kwds = self.rhs.explicit_args_kwds()
45435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
45445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if func_name in ['declare', 'typedef']:
45455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if len(args) > 2 or kwds is not None:
45465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(self.rhs.pos, "Can only declare one type at a time.")
45475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        return
45485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
45495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    type = args[0].analyse_as_type(env)
45505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if type is None:
45515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(args[0].pos, "Unknown type")
45525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        return
45535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    lhs = self.lhs
45545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if func_name == 'declare':
45555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        if isinstance(lhs, ExprNodes.NameNode):
45565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            vars = [(lhs.name, lhs.pos)]
45575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        elif isinstance(lhs, ExprNodes.TupleNode):
45585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            vars = [(var.name, var.pos) for var in lhs.args]
45595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        else:
45605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            error(lhs.pos, "Invalid declaration")
45615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            return
45625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        for var, pos in vars:
45635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            env.declare_var(var, type, pos, is_cdef = True)
45645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        if len(args) == 2:
45655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            # we have a value
45665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            self.rhs = args[1]
45675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        else:
45685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            self.declaration_only = True
45695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    else:
45705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        self.declaration_only = True
45715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        if not isinstance(lhs, ExprNodes.NameNode):
45725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            error(lhs.pos, "Invalid declaration.")
45735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        env.declare_typedef(lhs.name, type, self.pos, visibility='private')
45745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
45755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif func_name in ['struct', 'union']:
45765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.declaration_only = True
45775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if len(args) > 0 or kwds is None:
45785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(self.rhs.pos, "Struct or union members must be given by name.")
45795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        return
45805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    members = []
45815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    for member, type_node in kwds.key_value_pairs:
45825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        type = type_node.analyse_as_type(env)
45835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        if type is None:
45845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            error(type_node.pos, "Unknown type")
45855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        else:
45865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            members.append((member.value, type, member.pos))
45875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if len(members) < len(kwds.key_value_pairs):
45885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        return
45895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if not isinstance(self.lhs, ExprNodes.NameNode):
45905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(self.lhs.pos, "Invalid declaration.")
45915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    name = self.lhs.name
45925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    scope = StructOrUnionScope(name)
45935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
45945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    for member, type, pos in members:
45955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        scope.declare_var(member, type, pos)
45965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
45975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif func_name == 'fused_type':
45985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    # dtype = cython.fused_type(...)
45995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.declaration_only = True
46005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if kwds:
46015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(self.rhs.function.pos,
46025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              "fused_type does not take keyword arguments")
46035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    fusednode = FusedTypeNode(self.rhs.pos,
46055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              name = self.lhs.name, types=args)
46065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    fusednode.analyse_declarations(env)
46075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.declaration_only:
46095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
46105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
46115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.lhs.analyse_target_declaration(env)
46125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_types(self, env, use_temp = 0):
46145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import ExprNodes
46155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs = self.rhs.analyse_types(env)
46175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lhs = self.lhs.analyse_target_types(env)
46185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lhs.gil_assignment_check(env)
46195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.lhs.memslice_broadcast or self.rhs.memslice_broadcast:
46215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.lhs.memslice_broadcast = True
46225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.rhs.memslice_broadcast = True
46235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        is_index_node = isinstance(self.lhs, ExprNodes.IndexNode)
46255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (is_index_node and not self.rhs.type.is_memoryviewslice and
46265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            (self.lhs.memslice_slice or self.lhs.is_memslice_copy) and
46275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            (self.lhs.type.dtype.assignable_from(self.rhs.type) or
46285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             self.rhs.type.is_pyobject)):
46295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # scalar slice assignment
46305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.lhs.is_memslice_scalar_assignment = True
46315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            dtype = self.lhs.type.dtype
46325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
46335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            dtype = self.lhs.type
46345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        rhs = self.rhs.coerce_to(dtype, env)
46365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if use_temp or rhs.is_attribute or (
46375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                not rhs.is_name and not rhs.is_literal and
46385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                rhs.type.is_pyobject):
46395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # things like (cdef) attribute access are not safe (traverses pointers)
46405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs = rhs.coerce_to_temp(env)
46415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif rhs.type.is_pyobject:
46425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs = rhs.coerce_to_simple(env)
46435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs = rhs
46445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
46455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_rhs_evaluation_code(self, code):
46475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs.generate_evaluation_code(code)
46485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_assignment_code(self, code):
46505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lhs.generate_assignment_code(self.rhs, code)
46515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
46535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs.generate_function_definitions(env, code)
46545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
46565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lhs.annotate(code)
46575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs.annotate(code)
46585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CascadedAssignmentNode(AssignmentNode):
46615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  An assignment with multiple left hand sides:
46625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
46635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #    a = b = c
46645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
46655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  lhs_list   [ExprNode]   Left hand sides
46665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  rhs        ExprNode     Right hand sides
46675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
46685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  Used internally:
46695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
46705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  coerced_rhs_list   [ExprNode]   RHS coerced to type of each LHS
46715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
46735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    coerced_rhs_list = None
46745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
46765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for lhs in self.lhs_list:
46775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lhs.analyse_target_declaration(env)
46785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_types(self, env, use_temp = 0):
46805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        from ExprNodes import CloneNode, ProxyNode
46815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        rhs = self.rhs.analyse_types(env)
46835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if use_temp or rhs.is_attribute or (
46845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                not rhs.is_name and not rhs.is_literal and
46855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                rhs.type.is_pyobject):
46865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs = rhs.coerce_to_temp(env)
46875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
46885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs = rhs.coerce_to_simple(env)
46895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs = ProxyNode(rhs)
46905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
46915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.coerced_rhs_list = []
46925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for lhs in self.lhs_list:
46935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lhs.analyse_target_types(env)
46945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lhs.gil_assignment_check(env)
46955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs = CloneNode(self.rhs)
46965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs = rhs.coerce_to(lhs.type, env)
46975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.coerced_rhs_list.append(rhs)
46985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
46995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_rhs_evaluation_code(self, code):
47015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs.generate_evaluation_code(code)
47025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_assignment_code(self, code):
47045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i in range(len(self.lhs_list)):
47055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lhs = self.lhs_list[i]
47065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs = self.coerced_rhs_list[i]
47075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs.generate_evaluation_code(code)
47085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lhs.generate_assignment_code(rhs, code)
47095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Assignment has disposed of the cloned RHS
47105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs.generate_disposal_code(code)
47115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs.free_temps(code)
47125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
47145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs.generate_function_definitions(env, code)
47155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
47175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i in range(len(self.lhs_list)):
47185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.lhs_list[i].annotate(code)
47195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.coerced_rhs_list[i].annotate(code)
47205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs.annotate(code)
47215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ParallelAssignmentNode(AssignmentNode):
47245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  A combined packing/unpacking assignment:
47255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
47265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #    a, b, c =  d, e, f
47275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
47285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  This has been rearranged by the parser into
47295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
47305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #    a = d ; b = e ; c = f
47315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
47325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  but we must evaluate all the right hand sides
47335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  before assigning to any of the left hand sides.
47345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
47355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  stats     [AssignmentNode]   The constituent assignments
47365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["stats"]
47385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
47405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for stat in self.stats:
47415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            stat.analyse_declarations(env)
47425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
47445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.stats = [ stat.analyse_types(env, use_temp = 1)
47455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       for stat in self.stats ]
47465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
47475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#    def analyse_expressions(self, env):
47495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#        for stat in self.stats:
47505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#            stat.analyse_expressions_1(env, use_temp = 1)
47515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#        for stat in self.stats:
47525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#            stat.analyse_expressions_2(env)
47535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
47555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for stat in self.stats:
47565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            stat.generate_rhs_evaluation_code(code)
47575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for stat in self.stats:
47585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            stat.generate_assignment_code(code)
47595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
47615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for stat in self.stats:
47625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            stat.generate_function_definitions(env, code)
47635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
47655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for stat in self.stats:
47665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            stat.annotate(code)
47675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class InPlaceAssignmentNode(AssignmentNode):
47705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  An in place arithmetic operand:
47715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
47725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #    a += b
47735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #    a -= b
47745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #    ...
47755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
47765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  lhs      ExprNode      Left hand side
47775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  rhs      ExprNode      Right hand side
47785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  operator char          one of "+-*/%^&|"
47795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
47805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  This code is a bit tricky because in order to obey Python
47815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  semantics the sub-expressions (e.g. indices) of the lhs must
47825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  not be evaluated twice. So we must re-use the values calculated
47835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  in evaluation phase for the assignment phase as well.
47845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  Fortunately, the type of the lhs node is fairly constrained
47855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  (it must be a NameNode, AttributeNode, or IndexNode).
47865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["lhs", "rhs"]
47885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
47905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lhs.analyse_target_declaration(env)
47915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_types(self, env):
47935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs = self.rhs.analyse_types(env)
47945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lhs = self.lhs.analyse_target_types(env)
47955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # When assigning to a fully indexed buffer or memoryview, coerce the rhs
47975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (self.lhs.is_subscript and
47985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                (self.lhs.memslice_index or self.lhs.is_buffer_access)):
47995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.rhs = self.rhs.coerce_to(self.lhs.type, env)
48005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif self.lhs.type.is_string and self.operator in '+-':
48015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # use pointer arithmetic for char* LHS instead of string concat
48025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.rhs = self.rhs.coerce_to(PyrexTypes.c_py_ssize_t_type, env)
48035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
48045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
48055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
48065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs.generate_evaluation_code(code)
48075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lhs.generate_subexpr_evaluation_code(code)
48085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        c_op = self.operator
48095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if c_op == "//":
48105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            c_op = "/"
48115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif c_op == "**":
48125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "No C inplace power operator")
48135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.lhs.is_subscript and self.lhs.is_buffer_access:
48145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.lhs.type.is_pyobject:
48155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "In-place operators not allowed on object buffers in this release.")
48165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (c_op in ('/', '%') and self.lhs.type.is_int
48175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                and not code.globalstate.directives['cdivision']):
48185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "In-place non-c divide operators not allowed on int buffers.")
48195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
48205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
48215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # C++
48225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # TODO: make sure overload is declared
48235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()))
48245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lhs.generate_subexpr_disposal_code(code)
48255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lhs.free_subexpr_temps(code)
48265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs.generate_disposal_code(code)
48275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs.free_temps(code)
48285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
48295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
48305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lhs.annotate(code)
48315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs.annotate(code)
48325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
48335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def create_binop_node(self):
48345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import ExprNodes
48355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return ExprNodes.binop_node(self.pos, self.operator, self.lhs, self.rhs)
48365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
48375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
48385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class PrintStatNode(StatNode):
48395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  print statement
48405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
48415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  arg_tuple         TupleNode
48425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  stream            ExprNode or None (stdout)
48435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  append_newline    boolean
48445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
48455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["arg_tuple", "stream"]
48465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
48475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
48485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.stream:
48495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            stream = self.stream.analyse_expressions(env)
48505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.stream = stream.coerce_to_pyobject(env)
48515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        arg_tuple = self.arg_tuple.analyse_expressions(env)
48525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.arg_tuple = arg_tuple.coerce_to_pyobject(env)
48535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.use_utility_code(printing_utility_code)
48545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if len(self.arg_tuple.args) == 1 and self.append_newline:
48555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.use_utility_code(printing_one_utility_code)
48565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
48575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
48585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    nogil_check = Node.gil_error
48595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gil_message = "Python print statement"
48605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
48615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
48625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.stream:
48635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.stream.generate_evaluation_code(code)
48645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            stream_result = self.stream.py_result()
48655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
48665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            stream_result = '0'
48675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if len(self.arg_tuple.args) == 1 and self.append_newline:
48685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg = self.arg_tuple.args[0]
48695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.generate_evaluation_code(code)
48705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
48715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
48725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "if (__Pyx_PrintOne(%s, %s) < 0) %s" % (
48735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    stream_result,
48745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.py_result(),
48755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.error_goto(self.pos)))
48765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.generate_disposal_code(code)
48775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.free_temps(code)
48785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
48795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.arg_tuple.generate_evaluation_code(code)
48805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
48815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "if (__Pyx_Print(%s, %s, %d) < 0) %s" % (
48825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    stream_result,
48835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.arg_tuple.py_result(),
48845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.append_newline,
48855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.error_goto(self.pos)))
48865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.arg_tuple.generate_disposal_code(code)
48875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.arg_tuple.free_temps(code)
48885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
48895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.stream:
48905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.stream.generate_disposal_code(code)
48915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.stream.free_temps(code)
48925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
48935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
48945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.stream:
48955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.stream.generate_function_definitions(env, code)
48965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.arg_tuple.generate_function_definitions(env, code)
48975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
48985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
48995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.stream:
49005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.stream.annotate(code)
49015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.arg_tuple.annotate(code)
49025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ExecStatNode(StatNode):
49055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  exec statement
49065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
49075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  args     [ExprNode]
49085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["args"]
49105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
49125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i, arg in enumerate(self.args):
49135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg = arg.analyse_expressions(env)
49145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg = arg.coerce_to_pyobject(env)
49155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.args[i] = arg
49165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.use_utility_code(Builtin.pyexec_utility_code)
49175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
49185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    nogil_check = Node.gil_error
49205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gil_message = "Python exec statement"
49215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
49235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        args = []
49245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
49255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.generate_evaluation_code(code)
49265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            args.append( arg.py_result() )
49275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        args = tuple(args + ['0', '0'][:3-len(args)])
49285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        temp_result = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
49295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("%s = __Pyx_PyExec3(%s, %s, %s);" % (
49305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                (temp_result,) + args))
49315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
49325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.generate_disposal_code(code)
49335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.free_temps(code)
49345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
49355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.error_goto_if_null(temp_result, self.pos))
49365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_gotref(temp_result)
49375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_decref_clear(temp_result, py_object_type)
49385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.funcstate.release_temp(temp_result)
49395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
49415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
49425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.annotate(code)
49435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class DelStatNode(StatNode):
49465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  del statement
49475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
49485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  args     [ExprNode]
49495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["args"]
49515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ignore_nonexisting = False
49525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
49545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
49555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.analyse_target_declaration(env)
49565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
49585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i, arg in enumerate(self.args):
49595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg = self.args[i] = arg.analyse_target_expression(env, None)
49605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.type.is_pyobject or (arg.is_name and
49615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        arg.type.is_memoryviewslice):
49625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.is_name and arg.entry.is_cglobal:
49635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(arg.pos, "Deletion of global C variable")
49645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif arg.type.is_ptr and arg.type.base_type.is_cpp_class:
49655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.cpp_check(env)
49665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif arg.type.is_cpp_class:
49675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(arg.pos, "Deletion of non-heap C++ object")
49685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif arg.is_subscript and arg.base.type is Builtin.bytearray_type:
49695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pass  # del ba[i]
49705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
49715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(arg.pos, "Deletion of non-Python, non-C++ object")
49725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            #arg.release_target_temp(env)
49735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
49745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def nogil_check(self, env):
49765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
49775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.type.is_pyobject:
49785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.gil_error()
49795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gil_message = "Deleting Python object"
49815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
49835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
49845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (arg.type.is_pyobject or
49855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.type.is_memoryviewslice or
49865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.is_subscript and arg.base.type is Builtin.bytearray_type):
49875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg.generate_deletion_code(
49885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code, ignore_nonexisting=self.ignore_nonexisting)
49895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif arg.type.is_ptr and arg.type.base_type.is_cpp_class:
49905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg.generate_result_code(code)
49915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("delete %s;" % arg.result())
49925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # else error reported earlier
49935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
49955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in self.args:
49965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.annotate(code)
49975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class PassStatNode(StatNode):
50005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  pass statement
50015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = []
50035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
50055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
50065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
50085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
50095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class IndirectionNode(StatListNode):
50125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
50135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    This adds an indirection so that the node can be shared and a subtree can
50145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    be removed at any time by clearing self.stats.
50155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
50165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, stats):
50185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(IndirectionNode, self).__init__(stats[0].pos, stats=stats)
50195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class BreakStatNode(StatNode):
50215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = []
50235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_terminator = True
50245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
50265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
50275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
50295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not code.break_label:
50305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "break statement not inside loop")
50315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
50325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_goto(code.break_label)
50335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ContinueStatNode(StatNode):
50365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = []
50385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_terminator = True
50395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
50415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
50425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
50445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if code.funcstate.in_try_finally:
50455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "continue statement inside try of try...finally")
50465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif not code.continue_label:
50475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "continue statement not inside loop")
50485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
50495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_goto(code.continue_label)
50505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ReturnStatNode(StatNode):
50535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  return statement
50545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
50555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  value         ExprNode or None
50565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  return_type   PyrexType
50575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  in_generator  return inside of generator => raise StopIteration
50585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["value"]
50605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_terminator = True
50615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    in_generator = False
50625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Whether we are in a parallel section
50645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    in_parallel = False
50655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
50675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return_type = env.return_type
50685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.return_type = return_type
50695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not return_type:
50705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "Return not inside a function body")
50715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self
50725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.value:
50735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.value = self.value.analyse_types(env)
50745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if return_type.is_void or return_type.is_returncode:
50755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.value.pos,
50765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    "Return with value in void function")
50775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
50785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.value = self.value.coerce_to(env.return_type, env)
50795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
50805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (not return_type.is_void
50815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                and not return_type.is_pyobject
50825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                and not return_type.is_returncode):
50835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(self.pos, "Return value required")
50845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
50855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def nogil_check(self, env):
50875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.return_type.is_pyobject:
50885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.gil_error()
50895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gil_message = "Returning Python object"
50915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
50925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
50935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.mark_pos(self.pos)
50945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.return_type:
50955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # error reported earlier
50965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
50975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.return_type.is_pyobject:
50985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_xdecref(Naming.retval_cname,
50995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             self.return_type)
51005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
51015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.value:
51025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.value.generate_evaluation_code(code)
51035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.return_type.is_memoryviewslice:
51045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                import MemoryView
51055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                MemoryView.put_acquire_memoryviewslice(
51065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        lhs_cname=Naming.retval_cname,
51075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        lhs_type=self.return_type,
51085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        lhs_pos=self.value.pos,
51095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        rhs=self.value,
51105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code=code,
51115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        have_gil=self.in_nogil_context)
51125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif self.in_generator:
51135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # return value == raise StopIteration(value), but uncatchable
51145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln(
51155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    "%s = NULL; PyErr_SetObject(PyExc_StopIteration, %s);" % (
51165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        Naming.retval_cname,
51175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        self.value.result_as(self.return_type)))
51185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.value.generate_disposal_code(code)
51195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
51205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.value.make_owned_reference(code)
51215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln(
51225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    "%s = %s;" % (
51235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        Naming.retval_cname,
51245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        self.value.result_as(self.return_type)))
51255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.value.generate_post_assignment_code(code)
51265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.value.free_temps(code)
51275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
51285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.return_type.is_pyobject:
51295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_init_to_py_none(Naming.retval_cname, self.return_type)
51305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif self.return_type.is_returncode:
51315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.put_return(code, self.return_type.default_value)
51325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
51335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for cname, type in code.funcstate.temps_holding_reference():
51345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_decref_clear(cname, type)
51355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
51365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_goto(code.return_label)
51375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
51385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def put_return(self, code, value):
51395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.in_parallel:
51405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln_openmp("#pragma omp critical(__pyx_returning)")
51415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("%s = %s;" % (Naming.retval_cname, value))
51425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
51435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
51445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.value is not None:
51455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.value.generate_function_definitions(env, code)
51465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
51475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
51485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.value:
51495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.value.annotate(code)
51505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
51515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
51525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class RaiseStatNode(StatNode):
51535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  raise statement
51545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
51555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  exc_type    ExprNode or None
51565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  exc_value   ExprNode or None
51575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  exc_tb      ExprNode or None
51585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  cause       ExprNode or None
51595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
51605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["exc_type", "exc_value", "exc_tb", "cause"]
51615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_terminator = True
51625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
51635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
51645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.exc_type:
51655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            exc_type = self.exc_type.analyse_types(env)
51665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exc_type = exc_type.coerce_to_pyobject(env)
51675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.exc_value:
51685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            exc_value = self.exc_value.analyse_types(env)
51695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exc_value = exc_value.coerce_to_pyobject(env)
51705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.exc_tb:
51715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            exc_tb = self.exc_tb.analyse_types(env)
51725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exc_tb = exc_tb.coerce_to_pyobject(env)
51735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.cause:
51745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cause = self.cause.analyse_types(env)
51755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.cause = cause.coerce_to_pyobject(env)
51765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # special cases for builtin exceptions
51775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.builtin_exc_name = None
51785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.exc_type and not self.exc_value and not self.exc_tb:
51795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            exc = self.exc_type
51805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            import ExprNodes
51815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (isinstance(exc, ExprNodes.SimpleCallNode) and
51825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                not (exc.args or (exc.arg_tuple is not None and
51835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  exc.arg_tuple.args))):
51845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                exc = exc.function # extract the exception type
51855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if exc.is_name and exc.entry.is_builtin:
51865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.builtin_exc_name = exc.name
51875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.builtin_exc_name == 'MemoryError':
51885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.exc_type = None # has a separate implementation
51895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
51905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
51915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    nogil_check = Node.gil_error
51925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gil_message = "Raising exception"
51935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
51945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
51955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.builtin_exc_name == 'MemoryError':
51965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('PyErr_NoMemory(); %s' % code.error_goto(self.pos))
51975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
51985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
51995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.exc_type:
52005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exc_type.generate_evaluation_code(code)
52015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            type_code = self.exc_type.py_result()
52025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
52035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            type_code = "0"
52045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.exc_value:
52055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exc_value.generate_evaluation_code(code)
52065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            value_code = self.exc_value.py_result()
52075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
52085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            value_code = "0"
52095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.exc_tb:
52105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exc_tb.generate_evaluation_code(code)
52115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            tb_code = self.exc_tb.py_result()
52125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
52135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            tb_code = "0"
52145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.cause:
52155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.cause.generate_evaluation_code(code)
52165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cause_code = self.cause.py_result()
52175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
52185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cause_code = "0"
52195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.use_utility_code(raise_utility_code)
52205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
52215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "__Pyx_Raise(%s, %s, %s, %s);" % (
52225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                type_code,
52235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                value_code,
52245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                tb_code,
52255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                cause_code))
52265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for obj in (self.exc_type, self.exc_value, self.exc_tb, self.cause):
52275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if obj:
52285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                obj.generate_disposal_code(code)
52295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                obj.free_temps(code)
52305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
52315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.error_goto(self.pos))
52325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
52335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
52345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.exc_type is not None:
52355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exc_type.generate_function_definitions(env, code)
52365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.exc_value is not None:
52375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exc_value.generate_function_definitions(env, code)
52385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.exc_tb is not None:
52395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exc_tb.generate_function_definitions(env, code)
52405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.cause is not None:
52415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.cause.generate_function_definitions(env, code)
52425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
52435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
52445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.exc_type:
52455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exc_type.annotate(code)
52465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.exc_value:
52475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exc_value.annotate(code)
52485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.exc_tb:
52495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exc_tb.annotate(code)
52505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.cause:
52515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.cause.annotate(code)
52525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
52535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
52545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ReraiseStatNode(StatNode):
52555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
52565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = []
52575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_terminator = True
52585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
52595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
52605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
52615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
52625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    nogil_check = Node.gil_error
52635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gil_message = "Raising exception"
52645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
52655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
52665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        vars = code.funcstate.exc_vars
52675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if vars:
52685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.globalstate.use_utility_code(restore_exception_utility_code)
52695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_giveref(vars[0])
52705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_giveref(vars[1])
52715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # fresh exceptions may not have a traceback yet (-> finally!)
52725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_xgiveref(vars[2])
52735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("__Pyx_ErrRestore(%s, %s, %s);" % tuple(vars))
52745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for varname in vars:
52755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put("%s = 0; " % varname)
52765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln()
52775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(code.error_goto(self.pos))
52785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
52795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.globalstate.use_utility_code(
52805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                UtilityCode.load_cached("ReRaiseException", "Exceptions.c"))
52815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("__Pyx_ReraiseException(); %s" % code.error_goto(self.pos))
52825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
52835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class AssertStatNode(StatNode):
52845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  assert statement
52855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
52865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  cond    ExprNode
52875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  value   ExprNode or None
52885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
52895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["cond", "value"]
52905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
52915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
52925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.cond = self.cond.analyse_boolean_expression(env)
52935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.value:
52945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            value = self.value.analyse_types(env)
52955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if value.type is Builtin.tuple_type or not value.type.is_builtin_type:
52965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # prevent tuple values from being interpreted as argument value tuples
52975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                from ExprNodes import TupleNode
52985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                value = TupleNode(value.pos, args=[value], slow=True)
52995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.value = value.analyse_types(env, skip_children=True)
53005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
53015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.value = value.coerce_to_pyobject(env)
53025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
53035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    nogil_check = Node.gil_error
53055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gil_message = "Raising exception"
53065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
53085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("#ifndef CYTHON_WITHOUT_ASSERTIONS")
53095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("if (unlikely(!Py_OptimizeFlag)) {")
53105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.cond.generate_evaluation_code(code)
53115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
53125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "if (unlikely(!%s)) {" %
53135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.cond.result())
53145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.value:
53155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.value.generate_evaluation_code(code)
53165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
53175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "PyErr_SetObject(PyExc_AssertionError, %s);" %
53185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.value.py_result())
53195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.value.generate_disposal_code(code)
53205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.value.free_temps(code)
53215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
53225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
53235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "PyErr_SetNone(PyExc_AssertionError);")
53245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
53255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.error_goto(self.pos))
53265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
53275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "}")
53285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.cond.generate_disposal_code(code)
53295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.cond.free_temps(code)
53305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
53315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "}")
53325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("#endif")
53335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
53355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.cond.generate_function_definitions(env, code)
53365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.value is not None:
53375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.value.generate_function_definitions(env, code)
53385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
53405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.cond.annotate(code)
53415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.value:
53425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.value.annotate(code)
53435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class IfStatNode(StatNode):
53465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  if statement
53475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
53485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  if_clauses   [IfClauseNode]
53495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  else_clause  StatNode or None
53505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["if_clauses", "else_clause"]
53525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
53545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for if_clause in self.if_clauses:
53555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if_clause.analyse_declarations(env)
53565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
53575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.analyse_declarations(env)
53585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
53605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.if_clauses = [ if_clause.analyse_expressions(env)
53615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            for if_clause in self.if_clauses ]
53625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
53635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause = self.else_clause.analyse_expressions(env)
53645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
53655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
53675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.mark_pos(self.pos)
53685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        end_label = code.new_label()
53695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for if_clause in self.if_clauses:
53705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if_clause.generate_execution_code(code, end_label)
53715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
53725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("/*else*/ {")
53735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.generate_execution_code(code)
53745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("}")
53755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_label(end_label)
53765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
53785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for clause in self.if_clauses:
53795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            clause.generate_function_definitions(env, code)
53805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause is not None:
53815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.generate_function_definitions(env, code)
53825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
53845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for if_clause in self.if_clauses:
53855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if_clause.annotate(code)
53865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
53875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.annotate(code)
53885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class IfClauseNode(Node):
53915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  if or elif clause in an if statement
53925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
53935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  condition   ExprNode
53945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  body        StatNode
53955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["condition", "body"]
53975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
53985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
53995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.analyse_declarations(env)
54005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
54025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.condition = \
54035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.condition.analyse_temp_boolean_expression(env)
54045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = self.body.analyse_expressions(env)
54055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
54065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code, end_label):
54085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.condition.generate_evaluation_code(code)
54095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
54105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "if (%s) {" %
54115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.condition.result())
54125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.condition.generate_disposal_code(code)
54135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.condition.free_temps(code)
54145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
54155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.body.is_terminator:
54165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_goto(end_label)
54175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
54185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
54205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.condition.generate_function_definitions(env, code)
54215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_function_definitions(env, code)
54225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
54245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.condition.annotate(code)
54255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.annotate(code)
54265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class SwitchCaseNode(StatNode):
54295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Generated in the optimization of an if-elif-else node
54305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
54315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # conditions    [ExprNode]
54325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # body          StatNode
54335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ['conditions', 'body']
54355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
54375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for cond in self.conditions:
54385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.mark_pos(cond.pos)
54395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cond.generate_evaluation_code(code)
54405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("case %s:" % cond.result())
54415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
54425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("break;")
54435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
54455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for cond in self.conditions:
54465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cond.generate_function_definitions(env, code)
54475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_function_definitions(env, code)
54485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
54505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for cond in self.conditions:
54515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cond.annotate(code)
54525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.annotate(code)
54535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class SwitchStatNode(StatNode):
54555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Generated in the optimization of an if-elif-else node
54565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
54575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # test          ExprNode
54585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # cases         [SwitchCaseNode]
54595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # else_clause   StatNode or None
54605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ['test', 'cases', 'else_clause']
54625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
54645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.test.generate_evaluation_code(code)
54655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("switch (%s) {" % self.test.result())
54665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for case in self.cases:
54675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            case.generate_execution_code(code)
54685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause is not None:
54695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("default:")
54705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.generate_execution_code(code)
54715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("break;")
54725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
54735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Always generate a default clause to prevent C compiler warnings
54745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # about unmatched enum values (it was not the user who decided to
54755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # generate the switch statement, so shouldn't be bothered).
54765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("default: break;")
54775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
54785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
54805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.test.generate_function_definitions(env, code)
54815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for case in self.cases:
54825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            case.generate_function_definitions(env, code)
54835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause is not None:
54845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.generate_function_definitions(env, code)
54855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
54875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.test.annotate(code)
54885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for case in self.cases:
54895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            case.annotate(code)
54905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause is not None:
54915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.annotate(code)
54925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class LoopNode(object):
54945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    pass
54955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
54975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class WhileStatNode(LoopNode, StatNode):
54985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  while statement
54995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
55005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  condition    ExprNode
55015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  body         StatNode
55025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  else_clause  StatNode
55035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["condition", "body", "else_clause"]
55055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
55075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.analyse_declarations(env)
55085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
55095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.analyse_declarations(env)
55105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
55125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.condition:
55135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.condition = self.condition.analyse_temp_boolean_expression(env)
55145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = self.body.analyse_expressions(env)
55155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
55165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause = self.else_clause.analyse_expressions(env)
55175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
55185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
55205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_loop_labels = code.new_loop_labels()
55215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
55225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "while (1) {")
55235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.condition:
55245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.condition.generate_evaluation_code(code)
55255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.condition.generate_disposal_code(code)
55265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
55275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "if (!%s) break;" %
55285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.condition.result())
55295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.condition.free_temps(code)
55305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
55315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_label(code.continue_label)
55325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
55335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        break_label = code.break_label
55345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.set_loop_labels(old_loop_labels)
55355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
55365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.mark_pos(self.else_clause.pos)
55375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("/*else*/ {")
55385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.generate_execution_code(code)
55395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("}")
55405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_label(break_label)
55415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
55435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.condition:
55445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.condition.generate_function_definitions(env, code)
55455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_function_definitions(env, code)
55465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause is not None:
55475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.generate_function_definitions(env, code)
55485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
55505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.condition:
55515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.condition.annotate(code)
55525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.annotate(code)
55535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
55545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.annotate(code)
55555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class DictIterationNextNode(Node):
55585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Helper node for calling PyDict_Next() inside of a WhileStatNode
55595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # and checking the dictionary size for changes.  Created in
55605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Optimize.py.
55615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ['dict_obj', 'expected_size', 'pos_index_var',
55625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   'coerced_key_var', 'coerced_value_var', 'coerced_tuple_var',
55635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   'key_target', 'value_target', 'tuple_target', 'is_dict_flag']
55645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    coerced_key_var = key_ref = None
55665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    coerced_value_var = value_ref = None
55675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    coerced_tuple_var = tuple_ref = None
55685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, dict_obj, expected_size, pos_index_var,
55705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 key_target, value_target, tuple_target, is_dict_flag):
55715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Node.__init__(
55725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self, dict_obj.pos,
55735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            dict_obj = dict_obj,
55745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            expected_size = expected_size,
55755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pos_index_var = pos_index_var,
55765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            key_target = key_target,
55775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            value_target = value_target,
55785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            tuple_target = tuple_target,
55795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            is_dict_flag = is_dict_flag,
55805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            is_temp = True,
55815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            type = PyrexTypes.c_bint_type)
55825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
55845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import ExprNodes
55855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.dict_obj = self.dict_obj.analyse_types(env)
55865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.expected_size = self.expected_size.analyse_types(env)
55875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.pos_index_var:
55885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.pos_index_var = self.pos_index_var.analyse_types(env)
55895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.key_target:
55905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.key_target = self.key_target.analyse_target_types(env)
55915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.key_ref = ExprNodes.TempNode(self.key_target.pos, PyrexTypes.py_object_type)
55925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.coerced_key_var = self.key_ref.coerce_to(self.key_target.type, env)
55935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.value_target:
55945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.value_target = self.value_target.analyse_target_types(env)
55955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.value_ref = ExprNodes.TempNode(self.value_target.pos, type=PyrexTypes.py_object_type)
55965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.coerced_value_var = self.value_ref.coerce_to(self.value_target.type, env)
55975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.tuple_target:
55985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.tuple_target = self.tuple_target.analyse_target_types(env)
55995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.tuple_ref = ExprNodes.TempNode(self.tuple_target.pos, PyrexTypes.py_object_type)
56005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.coerced_tuple_var = self.tuple_ref.coerce_to(self.tuple_target.type, env)
56015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.is_dict_flag = self.is_dict_flag.analyse_types(env)
56025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
56035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
56045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
56055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.dict_obj.generate_function_definitions(env, code)
56065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
56075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
56085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.use_utility_code(UtilityCode.load_cached("dict_iter", "Optimize.c"))
56095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.dict_obj.generate_evaluation_code(code)
56105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
56115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        assignments = []
56125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        temp_addresses = []
56135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for var, result, target in [(self.key_ref, self.coerced_key_var, self.key_target),
56145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    (self.value_ref, self.coerced_value_var, self.value_target),
56155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    (self.tuple_ref, self.coerced_tuple_var, self.tuple_target)]:
56165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if target is None:
56175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                addr = 'NULL'
56185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
56195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                assignments.append((var, result, target))
56205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                var.allocate(code)
56215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                addr = '&%s' % var.result()
56225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            temp_addresses.append(addr)
56235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
56245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        result_temp = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
56255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("%s = __Pyx_dict_iter_next(%s, %s, &%s, %s, %s, %s, %s);" % (
56265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            result_temp,
56275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.dict_obj.py_result(),
56285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.expected_size.result(),
56295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.pos_index_var.result(),
56305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            temp_addresses[0],
56315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            temp_addresses[1],
56325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            temp_addresses[2],
56335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.is_dict_flag.result()
56345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ))
56355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("if (unlikely(%s == 0)) break;" % result_temp)
56365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(code.error_goto_if("%s == -1" % result_temp, self.pos))
56375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.funcstate.release_temp(result_temp)
56385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
56395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # evaluate all coercions before the assignments
56405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for var, result, target in assignments:
56415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_gotref(var.result())
56425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for var, result, target in assignments:
56435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            result.generate_evaluation_code(code)
56445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for var, result, target in assignments:
56455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            target.generate_assignment_code(result, code)
56465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            var.release(code)
56475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
56485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def ForStatNode(pos, **kw):
56495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if 'iterator' in kw:
56505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return ForInStatNode(pos, **kw)
56515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    else:
56525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return ForFromStatNode(pos, **kw)
56535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
56545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ForInStatNode(LoopNode, StatNode):
56555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  for statement
56565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
56575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  target        ExprNode
56585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  iterator      IteratorNode
56595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  body          StatNode
56605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  else_clause   StatNode
56615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  item          NextNode       used internally
56625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
56635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["target", "iterator", "body", "else_clause"]
56645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    item = None
56655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
56665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
56675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import ExprNodes
56685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.target.analyse_target_declaration(env)
56695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.analyse_declarations(env)
56705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
56715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.analyse_declarations(env)
56725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.item = ExprNodes.NextNode(self.iterator)
56735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
56745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
56755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.target = self.target.analyse_target_types(env)
56765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.iterator = self.iterator.analyse_expressions(env)
56775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import ExprNodes
56785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.item = ExprNodes.NextNode(self.iterator)  # must rewrap after analysis
56795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.item = self.item.analyse_expressions(env)
56805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (self.iterator.type.is_ptr or self.iterator.type.is_array) and \
56815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.target.type.assignable_from(self.iterator.type):
56825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # C array slice optimization.
56835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pass
56845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
56855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.item = self.item.coerce_to(self.target.type, env)
56865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = self.body.analyse_expressions(env)
56875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
56885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause = self.else_clause.analyse_expressions(env)
56895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
56905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
56915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
56925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_loop_labels = code.new_loop_labels()
56935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.iterator.generate_evaluation_code(code)
56945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("for (;;) {")
56955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.item.generate_evaluation_code(code)
56965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.target.generate_assignment_code(self.item, code)
56975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
56985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_label(code.continue_label)
56995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
57005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        break_label = code.break_label
57015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.set_loop_labels(old_loop_labels)
57025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
57035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
57045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # in nested loops, the 'else' block can contain a
57055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # 'continue' statement for the outer loop, but we may need
57065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # to generate cleanup code before taking that path, so we
57075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # intercept it here
57085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            orig_continue_label = code.continue_label
57095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.continue_label = code.new_label('outer_continue')
57105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
57115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("/*else*/ {")
57125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.generate_execution_code(code)
57135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("}")
57145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
57155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if code.label_used(code.continue_label):
57165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(break_label)
57175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_label(code.continue_label)
57185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.iterator.generate_disposal_code(code)
57195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(orig_continue_label)
57205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.set_loop_labels(old_loop_labels)
57215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
57225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if code.label_used(break_label):
57235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_label(break_label)
57245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.iterator.generate_disposal_code(code)
57255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.iterator.free_temps(code)
57265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
57275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
57285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.target.generate_function_definitions(env, code)
57295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.iterator.generate_function_definitions(env, code)
57305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_function_definitions(env, code)
57315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause is not None:
57325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.generate_function_definitions(env, code)
57335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
57345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
57355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.target.annotate(code)
57365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.iterator.annotate(code)
57375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.annotate(code)
57385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
57395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.annotate(code)
57405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.item.annotate(code)
57415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
57425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
57435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ForFromStatNode(LoopNode, StatNode):
57445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  for name from expr rel name rel expr
57455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
57465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  target        NameNode
57475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  bound1        ExprNode
57485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  relation1     string
57495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  relation2     string
57505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  bound2        ExprNode
57515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  step          ExprNode or None
57525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  body          StatNode
57535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  else_clause   StatNode or None
57545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
57555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  Used internally:
57565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
57575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  from_range         bool
57585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  is_py_target       bool
57595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  loopvar_node       ExprNode (usually a NameNode or temp node)
57605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  py_loopvar_node    PyTempNode or None
57615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
57625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
57635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_py_target = False
57645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    loopvar_node = None
57655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    py_loopvar_node = None
57665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    from_range = False
57675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
57685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gil_message = "For-loop using object bounds or target"
57695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
57705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def nogil_check(self, env):
57715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for x in (self.target, self.bound1, self.bound2):
57725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if x.type.is_pyobject:
57735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.gil_error()
57745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
57755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
57765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.target.analyse_target_declaration(env)
57775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.analyse_declarations(env)
57785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
57795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.analyse_declarations(env)
57805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
57815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
57825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import ExprNodes
57835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.target = self.target.analyse_target_types(env)
57845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.bound1 = self.bound1.analyse_types(env)
57855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.bound2 = self.bound2.analyse_types(env)
57865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.step is not None:
57875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if isinstance(self.step, ExprNodes.UnaryMinusNode):
57885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                warning(self.step.pos, "Probable infinite loop in for-from-by statement. Consider switching the directions of the relations.", 2)
57895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.step = self.step.analyse_types(env)
57905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
57915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.target.type.is_numeric:
57925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            loop_type = self.target.type
57935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
57945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            loop_type = PyrexTypes.c_int_type
57955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.bound1.type.is_pyobject:
57965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
57975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.bound2.type.is_pyobject:
57985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
57995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.step is not None and not self.step.type.is_pyobject:
58005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
58015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.bound1 = self.bound1.coerce_to(loop_type, env)
58025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.bound2 = self.bound2.coerce_to(loop_type, env)
58035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.bound2.is_literal:
58045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.bound2 = self.bound2.coerce_to_temp(env)
58055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.step is not None:
58065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.step = self.step.coerce_to(loop_type, env)
58075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.step.is_literal:
58085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.step = self.step.coerce_to_temp(env)
58095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
58105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        target_type = self.target.type
58115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not (target_type.is_pyobject or target_type.is_numeric):
58125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.target.pos,
58135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "for-from loop variable must be c numeric type or Python object")
58145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if target_type.is_numeric:
58155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.is_py_target = False
58165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
58175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                raise error(self.pos, "Buffer indexing not allowed as for loop target.")
58185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.loopvar_node = self.target
58195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.py_loopvar_node = None
58205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
58215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.is_py_target = True
58225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
58235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.loopvar_node = c_loopvar_node
58245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.py_loopvar_node = \
58255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
58265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = self.body.analyse_expressions(env)
58275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
58285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause = self.else_clause.analyse_expressions(env)
58295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
58305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
58315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
58325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_loop_labels = code.new_loop_labels()
58335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        from_range = self.from_range
58345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.bound1.generate_evaluation_code(code)
58355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.bound2.generate_evaluation_code(code)
58365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        offset, incop = self.relation_table[self.relation1]
58375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.step is not None:
58385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.step.generate_evaluation_code(code)
58395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            step = self.step.result()
58405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            incop = "%s=%s" % (incop[0], step)
58415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import ExprNodes
58425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(self.loopvar_node, ExprNodes.TempNode):
58435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.loopvar_node.allocate(code)
58445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
58455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.py_loopvar_node.allocate(code)
58465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if from_range:
58475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
58485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
58495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            loopvar_name = self.loopvar_node.result()
58505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
58515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "for (%s = %s%s; %s %s %s; %s%s) {" % (
58525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                loopvar_name,
58535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.bound1.result(), offset,
58545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                loopvar_name, self.relation2, self.bound2.result(),
58555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                loopvar_name, incop))
58565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.py_loopvar_node:
58575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.py_loopvar_node.generate_evaluation_code(code)
58585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.target.generate_assignment_code(self.py_loopvar_node, code)
58595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif from_range:
58605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("%s = %s;" % (
58615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            self.target.result(), loopvar_name))
58625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
58635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_label(code.continue_label)
58645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.py_loopvar_node:
58655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # This mess is to make for..from loops with python targets behave
58665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # exactly like those with C targets with regards to re-assignment
58675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # of the loop variable.
58685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            import ExprNodes
58695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.target.entry.is_pyglobal:
58705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # We know target is a NameNode, this is the only ugly case.
58715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                target_node = ExprNodes.PyTempNode(self.target.pos, None)
58725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                target_node.allocate(code)
58735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                interned_cname = code.intern_identifier(self.target.entry.name)
58745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.target.entry.scope.is_module_scope:
58755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.globalstate.use_utility_code(
58765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c"))
58775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    lookup_func = '__Pyx_GetModuleGlobalName(%s)'
58785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
58795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.globalstate.use_utility_code(
58805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        UtilityCode.load_cached("GetNameInClass", "ObjectHandling.c"))
58815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    lookup_func = '__Pyx_GetNameInClass(%s, %%s)' % (
58825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        self.target.entry.scope.namespace_cname)
58835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("%s = %s; %s" % (
58845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    target_node.result(),
58855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    lookup_func % interned_cname,
58865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.error_goto_if_null(target_node.result(), self.target.pos)))
58875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_gotref(target_node.result())
58885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
58895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                target_node = self.target
58905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            from_py_node = ExprNodes.CoerceFromPyTypeNode(
58915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.loopvar_node.type, target_node, self.target.entry.scope)
58925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            from_py_node.temp_code = loopvar_name
58935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            from_py_node.generate_result_code(code)
58945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.target.entry.is_pyglobal:
58955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_decref(target_node.result(), target_node.type)
58965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                target_node.release(code)
58975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
58985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.py_loopvar_node:
58995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # This is potentially wasteful, but we don't want the semantics to
59005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # depend on whether or not the loop is a python type.
59015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.py_loopvar_node.generate_evaluation_code(code)
59025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.target.generate_assignment_code(self.py_loopvar_node, code)
59035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if from_range:
59045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.funcstate.release_temp(loopvar_name)
59055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        break_label = code.break_label
59065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.set_loop_labels(old_loop_labels)
59075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
59085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("/*else*/ {")
59095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.generate_execution_code(code)
59105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("}")
59115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_label(break_label)
59125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.bound1.generate_disposal_code(code)
59135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.bound1.free_temps(code)
59145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.bound2.generate_disposal_code(code)
59155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.bound2.free_temps(code)
59165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(self.loopvar_node, ExprNodes.TempNode):
59175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.loopvar_node.release(code)
59185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
59195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.py_loopvar_node.release(code)
59205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.step is not None:
59215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.step.generate_disposal_code(code)
59225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.step.free_temps(code)
59235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
59245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    relation_table = {
59255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # {relop : (initial offset, increment op)}
59265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        '<=': ("",   "++"),
59275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        '<' : ("+1", "++"),
59285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        '>=': ("",   "--"),
59295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        '>' : ("-1", "--")
59305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
59315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
59325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
59335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.target.generate_function_definitions(env, code)
59345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.bound1.generate_function_definitions(env, code)
59355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.bound2.generate_function_definitions(env, code)
59365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.step is not None:
59375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.step.generate_function_definitions(env, code)
59385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_function_definitions(env, code)
59395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause is not None:
59405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.generate_function_definitions(env, code)
59415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
59425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
59435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.target.annotate(code)
59445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.bound1.annotate(code)
59455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.bound2.annotate(code)
59465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.step:
59475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.step.annotate(code)
59485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.annotate(code)
59495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
59505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.annotate(code)
59515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
59525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
59535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class WithStatNode(StatNode):
59545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
59555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Represents a Python with statement.
59565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
59575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Implemented by the WithTransform as follows:
59585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
59595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        MGR = EXPR
59605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        EXIT = MGR.__exit__
59615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        VALUE = MGR.__enter__()
59625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        EXC = True
59635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        try:
59645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            try:
59655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                TARGET = VALUE  # optional
59665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                BODY
59675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            except:
59685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                EXC = False
59695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not EXIT(*EXCINFO):
59705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    raise
59715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        finally:
59725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if EXC:
59735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                EXIT(None, None, None)
59745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            MGR = EXIT = VALUE = None
59755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
59765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  manager          The with statement manager object
59775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  target           ExprNode  the target lhs of the __enter__() call
59785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  body             StatNode
59795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  enter_call       ExprNode  the call to the __enter__() method
59805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  exit_var         String    the cname of the __exit__() method reference
59815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
59825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["manager", "enter_call", "target", "body"]
59835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
59845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    enter_call = None
59855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
59865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
59875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.manager.analyse_declarations(env)
59885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.enter_call.analyse_declarations(env)
59895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.analyse_declarations(env)
59905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
59915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
59925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.manager = self.manager.analyse_types(env)
59935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.enter_call = self.enter_call.analyse_types(env)
59945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = self.body.analyse_expressions(env)
59955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
59965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
59975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
59985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.manager.generate_function_definitions(env, code)
59995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.enter_call.generate_function_definitions(env, code)
60005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_function_definitions(env, code)
60015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
60035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("/*with:*/ {")
60045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.manager.generate_evaluation_code(code)
60055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.exit_var = code.funcstate.allocate_temp(py_object_type, manage_ref=False)
60065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.use_utility_code(
60075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            UtilityCode.load_cached("PyObjectLookupSpecial", "ObjectHandling.c"))
60085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("%s = __Pyx_PyObject_LookupSpecial(%s, %s); %s" % (
60095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exit_var,
60105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.manager.py_result(),
60115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.intern_identifier(EncodedString('__exit__')),
60125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.error_goto_if_null(self.exit_var, self.pos),
60135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            ))
60145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_gotref(self.exit_var)
60155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # need to free exit_var in the face of exceptions during setup
60175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_error_label = code.new_error_label()
60185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        intermediate_error_label = code.error_label
60195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.enter_call.generate_evaluation_code(code)
60215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.target:
60225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.enter_call.generate_disposal_code(code)
60235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.enter_call.free_temps(code)
60245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
60255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Otherwise, the node will be cleaned up by the
60265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # WithTargetAssignmentStatNode after assigning its result
60275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # to the target of the 'with' statement.
60285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pass
60295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.manager.generate_disposal_code(code)
60305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.manager.free_temps(code)
60315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.error_label = old_error_label
60335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
60345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if code.label_used(intermediate_error_label):
60365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            step_over_label = code.new_label()
60375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_goto(step_over_label)
60385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_label(intermediate_error_label)
60395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_decref_clear(self.exit_var, py_object_type)
60405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_goto(old_error_label)
60415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_label(step_over_label)
60425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.funcstate.release_temp(self.exit_var)
60445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln('}')
60455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class WithTargetAssignmentStatNode(AssignmentNode):
60475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # The target assignment of the 'with' statement value (return
60485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # value of the __enter__() call).
60495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
60505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # This is a special cased assignment that steals the RHS reference
60515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # and frees its temp.
60525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
60535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # lhs       ExprNode   the assignment target
60545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # rhs       CloneNode  a (coerced) CloneNode for the orig_rhs (not owned by this node)
60555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # orig_rhs  ExprNode   the original ExprNode of the rhs. this node will clean up the
60565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #                      temps of the orig_rhs. basically, it takes ownership of the node
60575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #                      when the WithStatNode is done with it.
60585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["lhs"]
60605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
60625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lhs.analyse_target_declaration(env)
60635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
60655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs = self.rhs.analyse_types(env)
60665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lhs = self.lhs.analyse_target_types(env)
60675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lhs.gil_assignment_check(env)
60685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs = self.rhs.coerce_to(self.lhs.type, env)
60695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
60705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
60725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.orig_rhs.type.is_pyobject:
60735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # make sure rhs gets freed on errors, see below
60745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            old_error_label = code.new_error_label()
60755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            intermediate_error_label = code.error_label
60765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs.generate_evaluation_code(code)
60785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lhs.generate_assignment_code(self.rhs, code)
60795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.orig_rhs.type.is_pyobject:
60815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.orig_rhs.generate_disposal_code(code)
60825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.error_label = old_error_label
60835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if code.label_used(intermediate_error_label):
60845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                step_over_label = code.new_label()
60855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(step_over_label)
60865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_label(intermediate_error_label)
60875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.orig_rhs.generate_disposal_code(code)
60885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(old_error_label)
60895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_label(step_over_label)
60905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.orig_rhs.free_temps(code)
60925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
60945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lhs.annotate(code)
60955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.rhs.annotate(code)
60965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
60985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class TryExceptStatNode(StatNode):
60995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  try .. except statement
61005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
61015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  body             StatNode
61025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  except_clauses   [ExceptClauseNode]
61035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  else_clause      StatNode or None
61045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
61055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["body", "except_clauses", "else_clause"]
61065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
61075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
61085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.analyse_declarations(env)
61095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for except_clause in self.except_clauses:
61105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            except_clause.analyse_declarations(env)
61115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
61125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.analyse_declarations(env)
61135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
61145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
61155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = self.body.analyse_expressions(env)
61165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        default_clause_seen = 0
61175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i, except_clause in enumerate(self.except_clauses):
61185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            except_clause = self.except_clauses[i] = except_clause.analyse_expressions(env)
61195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if default_clause_seen:
61205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(except_clause.pos, "default 'except:' must be last")
61215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not except_clause.pattern:
61225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                default_clause_seen = 1
61235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.has_default_clause = default_clause_seen
61245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
61255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause = self.else_clause.analyse_expressions(env)
61265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
61275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
61285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    nogil_check = Node.gil_error
61295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gil_message = "Try-except statement"
61305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
61315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
61325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_return_label = code.return_label
61335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_break_label = code.break_label
61345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_continue_label = code.continue_label
61355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_error_label = code.new_error_label()
61365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        our_error_label = code.error_label
61375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        except_end_label = code.new_label('exception_handled')
61385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        except_error_label = code.new_label('except_error')
61395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        except_return_label = code.new_label('except_return')
61405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        try_return_label = code.new_label('try_return')
61415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        try_break_label = code.new_label('try_break')
61425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        try_continue_label = code.new_label('try_continue')
61435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        try_end_label = code.new_label('try_end')
61445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
61455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        exc_save_vars = [code.funcstate.allocate_temp(py_object_type, False)
61465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         for _ in xrange(3)]
61475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("{")
61485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        save_exc = code.insertion_point()
61495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
61505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "/*try:*/ {")
61515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.return_label = try_return_label
61525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.break_label = try_break_label
61535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.continue_label = try_continue_label
61545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
61555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
61565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "}")
61575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        temps_to_clean_up = code.funcstate.all_free_managed_temps()
61585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        can_raise = code.label_used(our_error_label)
61595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
61605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if can_raise:
61615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # inject code before the try block to save away the exception state
61625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.globalstate.use_utility_code(reset_exception_utility_code)
61635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            save_exc.putln("__Pyx_ExceptionSave(%s);" %
61645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           ', '.join(['&%s' % var for var in exc_save_vars]))
61655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for var in exc_save_vars:
61665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                save_exc.put_xgotref(var)
61675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
61685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            def restore_saved_exception():
61695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for name in exc_save_vars:
61705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put_xgiveref(name)
61715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("__Pyx_ExceptionReset(%s);" %
61725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           ', '.join(exc_save_vars))
61735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
61745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # try block cannot raise exceptions, but we had to allocate the temps above,
61755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # so just keep the C compiler from complaining about them being unused
61765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            save_exc.putln("if (%s); else {/*mark used*/};" % '||'.join(exc_save_vars))
61775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
61785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            def restore_saved_exception():
61795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pass
61805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
61815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.error_label = except_error_label
61825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.return_label = except_return_label
61835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
61845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
61855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "/*else:*/ {")
61865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.generate_execution_code(code)
61875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
61885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "}")
61895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
61905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if can_raise:
61915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for var in exc_save_vars:
61925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_xdecref_clear(var, py_object_type)
61935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_goto(try_end_label)
61945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_label(our_error_label)
61955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for temp_name, temp_type in temps_to_clean_up:
61965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_xdecref_clear(temp_name, temp_type)
61975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for except_clause in self.except_clauses:
61985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                except_clause.generate_handling_code(code, except_end_label)
61995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.has_default_clause:
62005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(except_error_label)
62015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for exit_label, old_label in [(except_error_label, old_error_label),
62035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      (try_break_label, old_break_label),
62045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      (try_continue_label, old_continue_label),
62055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      (try_return_label, old_return_label),
62065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      (except_return_label, old_return_label)]:
62075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if code.label_used(exit_label):
62085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not code.label_used(try_end_label):
62095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put_goto(try_end_label)
62105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_label(exit_label)
62115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                restore_saved_exception()
62125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(old_label)
62135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if code.label_used(except_end_label):
62155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not code.label_used(try_end_label):
62165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(try_end_label)
62175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_label(except_end_label)
62185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            restore_saved_exception()
62195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if code.label_used(try_end_label):
62205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_label(try_end_label)
62215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
62225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for cname in exc_save_vars:
62245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.funcstate.release_temp(cname)
62255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.return_label = old_return_label
62275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.break_label = old_break_label
62285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.continue_label = old_continue_label
62295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.error_label = old_error_label
62305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
62325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_function_definitions(env, code)
62335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for except_clause in self.except_clauses:
62345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            except_clause.generate_function_definitions(env, code)
62355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause is not None:
62365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.generate_function_definitions(env, code)
62375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
62395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.annotate(code)
62405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for except_node in self.except_clauses:
62415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            except_node.annotate(code)
62425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
62435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.annotate(code)
62445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ExceptClauseNode(Node):
62475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  Part of try ... except statement.
62485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
62495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  pattern        [ExprNode]
62505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  target         ExprNode or None
62515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  body           StatNode
62525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  excinfo_target TupleNode(3*ResultRefNode) or None   optional target for exception info (not owned here!)
62535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  match_flag     string             result of exception match
62545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  exc_value      ExcValueNode       used internally
62555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  function_name  string             qualified name of enclosing function
62565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  exc_vars       (string * 3)       local exception variables
62575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  is_except_as   bool               Py3-style "except ... as xyz"
62585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # excinfo_target is never set by the parser, but can be set by a transform
62605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # in order to extract more extensive information about the exception as a
62615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # sys.exc_info()-style tuple into a target variable
62625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["pattern", "target", "body", "exc_value"]
62645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    exc_value = None
62665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    excinfo_target = None
62675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_except_as = False
62685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
62705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.target:
62715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.target.analyse_target_declaration(env)
62725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.analyse_declarations(env)
62735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
62755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.function_name = env.qualified_name
62765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.pattern:
62775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # normalise/unpack self.pattern into a list
62785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for i, pattern in enumerate(self.pattern):
62795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pattern = pattern.analyse_expressions(env)
62805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.pattern[i] = pattern.coerce_to_pyobject(env)
62815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.target:
62835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            import ExprNodes
62845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exc_value = ExprNodes.ExcValueNode(self.pos)
62855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.target = self.target.analyse_target_expression(env, self.exc_value)
62865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = self.body.analyse_expressions(env)
62885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
62895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_handling_code(self, code, end_label):
62915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.mark_pos(self.pos)
62925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.pattern:
62935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            exc_tests = []
62945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for pattern in self.pattern:
62955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pattern.generate_evaluation_code(code)
62965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                exc_tests.append("PyErr_ExceptionMatches(%s)" % pattern.py_result())
62975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
62985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            match_flag = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
62995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
63005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "%s = %s;" % (match_flag, ' || '.join(exc_tests)))
63015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for pattern in self.pattern:
63025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pattern.generate_disposal_code(code)
63035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pattern.free_temps(code)
63045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
63055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "if (%s) {" %
63065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    match_flag)
63075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.funcstate.release_temp(match_flag)
63085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
63095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("/*except:*/ {")
63105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
63115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (not getattr(self.body, 'stats', True)
63125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                and self.excinfo_target is None
63135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                and self.target is None):
63145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # most simple case: no exception variable, empty body (pass)
63155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # => reset the exception state, done
63165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("PyErr_Restore(0,0,0);")
63175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_goto(end_label)
63185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("}")
63195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
63205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
63215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        exc_vars = [code.funcstate.allocate_temp(py_object_type,
63225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                 manage_ref=True)
63235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    for _ in xrange(3)]
63245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_add_traceback(self.function_name)
63255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # We always have to fetch the exception value even if
63265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # there is no target, because this also normalises the
63275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # exception and stores it in the thread state.
63285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.use_utility_code(get_exception_utility_code)
63295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
63305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
63315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.error_goto(self.pos)))
63325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for x in exc_vars:
63335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_gotref(x)
63345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.target:
63355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exc_value.set_var(exc_vars[1])
63365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exc_value.generate_evaluation_code(code)
63375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.target.generate_assignment_code(self.exc_value, code)
63385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.excinfo_target is not None:
63395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for tempvar, node in zip(exc_vars, self.excinfo_target.args):
63405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.set_var(tempvar)
63415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
63425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_break_label, old_continue_label = code.break_label, code.continue_label
63435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.break_label = code.new_label('except_break')
63445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.continue_label = code.new_label('except_continue')
63455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
63465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_exc_vars = code.funcstate.exc_vars
63475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.funcstate.exc_vars = exc_vars
63485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
63495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.funcstate.exc_vars = old_exc_vars
63505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for var in exc_vars:
63515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_decref_clear(var, py_object_type)
63525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_goto(end_label)
63535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
63545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for new_label, old_label in [(code.break_label, old_break_label),
63555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     (code.continue_label, old_continue_label)]:
63565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if code.label_used(new_label):
63575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_label(new_label)
63585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for var in exc_vars:
63595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put_decref_clear(var, py_object_type)
63605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(old_label)
63615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.break_label = old_break_label
63625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.continue_label = old_continue_label
63635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
63645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for temp in exc_vars:
63655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.funcstate.release_temp(temp)
63665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
63675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
63685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "}")
63695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
63705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
63715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.target is not None:
63725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.target.generate_function_definitions(env, code)
63735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_function_definitions(env, code)
63745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
63755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
63765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.pattern:
63775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for pattern in self.pattern:
63785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pattern.annotate(code)
63795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.target:
63805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.target.annotate(code)
63815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.annotate(code)
63825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
63835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
63845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class TryFinallyStatNode(StatNode):
63855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  try ... finally statement
63865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
63875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  body             StatNode
63885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  finally_clause   StatNode
63895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
63905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  The plan is that we funnel all continue, break
63915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  return and error gotos into the beginning of the
63925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  finally block, setting a variable to remember which
63935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  one we're doing. At the end of the finally block, we
63945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  switch on the variable to figure out where to go.
63955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  In addition, if we're doing an error, we save the
63965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  exception on entry to the finally block and restore
63975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  it on exit.
63985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
63995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["body", "finally_clause"]
64005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    preserve_exception = 1
64025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # handle exception case, in addition to return/break/continue
64045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    handle_error_case = True
64055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    func_return_type = None
64065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    disallow_continue_in_try_finally = 0
64085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # There doesn't seem to be any point in disallowing
64095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # continue in the try block, since we have no problem
64105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # handling it.
64115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_try_finally_in_nogil = False
64135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def create_analysed(pos, env, body, finally_clause):
64155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
64165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
64175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    create_analysed = staticmethod(create_analysed)
64185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
64205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.analyse_declarations(env)
64215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.finally_clause.analyse_declarations(env)
64225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
64245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = self.body.analyse_expressions(env)
64255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.finally_clause = self.finally_clause.analyse_expressions(env)
64265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if env.return_type and not env.return_type.is_void:
64275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.func_return_type = env.return_type
64285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
64295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    nogil_check = Node.gil_error
64315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gil_message = "Try-finally statement"
64325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
64345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_error_label = code.error_label
64355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_labels = code.all_new_labels()
64365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        new_labels = code.get_all_labels()
64375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        new_error_label = code.error_label
64385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.handle_error_case:
64395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.error_label = old_error_label
64405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        catch_label = code.new_label()
64415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("/*try:*/ {")
64435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.disallow_continue_in_try_finally:
64455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            was_in_try_finally = code.funcstate.in_try_finally
64465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.funcstate.in_try_finally = 1
64475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
64495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.disallow_continue_in_try_finally:
64515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.funcstate.in_try_finally = was_in_try_finally
64525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
64545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.set_all_labels(old_labels)
64555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        temps_to_clean_up = code.funcstate.all_free_managed_temps()
64575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.mark_pos(self.finally_clause.pos)
64585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("/*finally:*/ {")
64595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        def fresh_finally_clause(_next=[self.finally_clause]):
64615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # generate the original subtree once and always keep a fresh copy
64625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = _next[0]
64635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node_copy = copy.deepcopy(node)
64645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if node is self.finally_clause:
64655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                _next[0] = node_copy
64665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
64675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node = node_copy
64685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
64695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        preserve_error = self.preserve_exception and code.label_used(new_error_label)
64715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        needs_success_cleanup = not self.finally_clause.is_terminator
64725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.body.is_terminator:
64745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('/*normal exit:*/{')
64755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            fresh_finally_clause().generate_execution_code(code)
64765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.finally_clause.is_terminator:
64775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(catch_label)
64785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('}')
64795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if preserve_error:
64815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('/*exception exit:*/{')
64825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.is_try_finally_in_nogil:
64835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.declare_gilstate()
64845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if needs_success_cleanup:
64855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                exc_lineno_cnames = tuple([
64865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False)
64875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    for _ in range(2)])
64885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                exc_filename_cname = code.funcstate.allocate_temp(
64895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    PyrexTypes.CPtrType(PyrexTypes.c_const_type(PyrexTypes.c_char_type)),
64905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    manage_ref=False)
64915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
64925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                exc_lineno_cnames = exc_filename_cname = None
64935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            exc_vars = tuple([
64945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.funcstate.allocate_temp(py_object_type, manage_ref=False)
64955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for _ in range(6)])
64965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_label(new_error_label)
64975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.put_error_catcher(
64985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code, temps_to_clean_up, exc_vars, exc_lineno_cnames, exc_filename_cname)
64995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            finally_old_labels = code.all_new_labels()
65005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
65015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('{')
65025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            old_exc_vars = code.funcstate.exc_vars
65035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.funcstate.exc_vars = exc_vars[:3]
65045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            fresh_finally_clause().generate_execution_code(code)
65055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.funcstate.exc_vars = old_exc_vars
65065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('}')
65075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
65085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if needs_success_cleanup:
65095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.put_error_uncatcher(code, exc_vars, exc_lineno_cnames, exc_filename_cname)
65105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if exc_lineno_cnames:
65115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    for cname in exc_lineno_cnames:
65125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.funcstate.release_temp(cname)
65135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if exc_filename_cname:
65145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.funcstate.release_temp(exc_filename_cname)
65155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(old_error_label)
65165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
65175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for new_label, old_label in zip(code.get_all_labels(), finally_old_labels):
65185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not code.label_used(new_label):
65195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    continue
65205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_label(new_label)
65215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.put_error_cleaner(code, exc_vars)
65225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(old_label)
65235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
65245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for cname in exc_vars:
65255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.funcstate.release_temp(cname)
65265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('}')
65275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
65285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.set_all_labels(old_labels)
65295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return_label = code.return_label
65305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i, (new_label, old_label) in enumerate(zip(new_labels, old_labels)):
65315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not code.label_used(new_label):
65325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                continue
65335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if new_label == new_error_label and preserve_error:
65345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                continue  # handled above
65355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
65365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put('%s: ' % new_label)
65375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('{')
65385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            ret_temp = None
65395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if old_label == return_label and not self.finally_clause.is_terminator:
65405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # store away return value for later reuse
65415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if (self.func_return_type and
65425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        not self.is_try_finally_in_nogil and
65435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        not isinstance(self.finally_clause, GILExitNode)):
65445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    ret_temp = code.funcstate.allocate_temp(
65455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        self.func_return_type, manage_ref=False)
65465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln("%s = %s;" % (ret_temp, Naming.retval_cname))
65475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if self.func_return_type.is_pyobject:
65485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.putln("%s = 0;" % Naming.retval_cname)
65495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            fresh_finally_clause().generate_execution_code(code)
65505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if ret_temp:
65515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("%s = %s;" % (Naming.retval_cname, ret_temp))
65525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.func_return_type.is_pyobject:
65535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln("%s = 0;" % ret_temp)
65545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.funcstate.release_temp(ret_temp)
65555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ret_temp = None
65565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.finally_clause.is_terminator:
65575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(old_label)
65585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln('}')
65595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
65605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # End finally
65615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_label(catch_label)
65625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
65635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "}")
65645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
65655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
65665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_function_definitions(env, code)
65675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.finally_clause.generate_function_definitions(env, code)
65685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
65695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def put_error_catcher(self, code, temps_to_clean_up, exc_vars,
65705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          exc_lineno_cnames, exc_filename_cname):
65715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.use_utility_code(restore_exception_utility_code)
65725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.use_utility_code(get_exception_utility_code)
65735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.use_utility_code(swap_exception_utility_code)
65745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
65755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(' '.join(["%s = 0;"]*len(exc_vars)) % exc_vars)
65765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_try_finally_in_nogil:
65775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_ensure_gil(declare_gilstate=False)
65785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
65795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for temp_name, type in temps_to_clean_up:
65805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_xdecref_clear(temp_name, type)
65815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
65825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # not using preprocessor here to avoid warnings about
65835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # unused utility functions and/or temps
65845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("if (PY_MAJOR_VERSION >= 3)"
65855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   " __Pyx_ExceptionSwap(&%s, &%s, &%s);" % exc_vars[3:])
65865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("if ((PY_MAJOR_VERSION < 3) ||"
65875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   # if __Pyx_GetException() fails in Py3,
65885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   # store the newly raised exception instead
65895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   " unlikely(__Pyx_GetException(&%s, &%s, &%s) < 0)) "
65905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   "__Pyx_ErrFetch(&%s, &%s, &%s);" % (exc_vars[:3] * 2))
65915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for var in exc_vars:
65925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_xgotref(var)
65935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if exc_lineno_cnames:
65945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("%s = %s; %s = %s; %s = %s;" % (
65955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                exc_lineno_cnames[0], Naming.lineno_cname,
65965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                exc_lineno_cnames[1], Naming.clineno_cname,
65975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                exc_filename_cname, Naming.filename_cname))
65985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
65995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_try_finally_in_nogil:
66005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_release_ensured_gil()
66015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def put_error_uncatcher(self, code, exc_vars, exc_lineno_cnames, exc_filename_cname):
66035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.use_utility_code(restore_exception_utility_code)
66045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.use_utility_code(reset_exception_utility_code)
66055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_try_finally_in_nogil:
66075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_ensure_gil(declare_gilstate=False)
66085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # not using preprocessor here to avoid warnings about
66105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # unused utility functions and/or temps
66115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("if (PY_MAJOR_VERSION >= 3) {")
66125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for var in exc_vars[3:]:
66135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_xgiveref(var)
66145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("__Pyx_ExceptionReset(%s, %s, %s);" % exc_vars[3:])
66155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
66165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for var in exc_vars[:3]:
66175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_xgiveref(var)
66185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("__Pyx_ErrRestore(%s, %s, %s);" % exc_vars[:3])
66195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_try_finally_in_nogil:
66215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_release_ensured_gil()
66225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(' '.join(["%s = 0;"]*len(exc_vars)) % exc_vars)
66245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if exc_lineno_cnames:
66255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("%s = %s; %s = %s; %s = %s;" % (
66265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Naming.lineno_cname, exc_lineno_cnames[0],
66275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Naming.clineno_cname, exc_lineno_cnames[1],
66285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Naming.filename_cname, exc_filename_cname))
66295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def put_error_cleaner(self, code, exc_vars):
66315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.globalstate.use_utility_code(reset_exception_utility_code)
66325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_try_finally_in_nogil:
66335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_ensure_gil(declare_gilstate=False)
66345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # not using preprocessor here to avoid warnings about
66355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # unused utility functions and/or temps
66365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("if (PY_MAJOR_VERSION >= 3) {")
66375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for var in exc_vars[3:]:
66385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_xgiveref(var)
66395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("__Pyx_ExceptionReset(%s, %s, %s);" % exc_vars[3:])
66405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("}")
66415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for var in exc_vars[:3]:
66425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_xdecref_clear(var, py_object_type)
66435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_try_finally_in_nogil:
66445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_release_ensured_gil()
66455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(' '.join(["%s = 0;"]*3) % exc_vars[3:])
66465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def annotate(self, code):
66485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.annotate(code)
66495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.finally_clause.annotate(code)
66505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class NogilTryFinallyStatNode(TryFinallyStatNode):
66535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
66545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    A try/finally statement that may be used in nogil code sections.
66555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
66565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    preserve_exception = False
66585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    nogil_check = None
66595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class GILStatNode(NogilTryFinallyStatNode):
66625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  'with gil' or 'with nogil' statement
66635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
66645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #   state   string   'gil' or 'nogil'
66655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    state_temp = None
66675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, pos, state, body):
66695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.state = state
66705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.create_state_temp_if_needed(pos, state, body)
66715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        TryFinallyStatNode.__init__(self, pos,
66725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            body=body,
66735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            finally_clause=GILExitNode(
66745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pos, state=state, state_temp=self.state_temp))
66755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def create_state_temp_if_needed(self, pos, state, body):
66775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        from ParseTreeTransforms import YieldNodeCollector
66785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        collector = YieldNodeCollector()
66795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        collector.visitchildren(body)
66805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not collector.yields:
66815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
66825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if state == 'gil':
66845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            temp_type = PyrexTypes.c_gilstate_type
66855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
66865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            temp_type = PyrexTypes.c_threadstate_ptr_type
66875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import ExprNodes
66885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.state_temp = ExprNodes.TempNode(pos, temp_type)
66895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
66915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env._in_with_gil_block = (self.state == 'gil')
66925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.state == 'gil':
66935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.has_with_gil_block = True
66945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return super(GILStatNode, self).analyse_declarations(env)
66965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
66985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.use_utility_code(
66995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            UtilityCode.load_cached("ForceInitThreads", "ModuleSetupCode.c"))
67005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        was_nogil = env.nogil
67015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.nogil = self.state == 'nogil'
67025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node = TryFinallyStatNode.analyse_expressions(self, env)
67035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.nogil = was_nogil
67045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
67055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
67075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.mark_pos(self.pos)
67085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.begin_block()
67095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.state_temp:
67105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.state_temp.allocate(code)
67115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            variable = self.state_temp.result()
67125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
67135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            variable = None
67145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_trace_config = code.funcstate.can_trace
67165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.state == 'gil':
67175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_ensure_gil(variable=variable)
67185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # FIXME: not that easy, tracing may not be possible at all here
67195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            #code.funcstate.can_trace = True
67205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
67215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_release_gil(variable=variable)
67225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.funcstate.can_trace = False
67235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        TryFinallyStatNode.generate_execution_code(self, code)
67255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.state_temp:
67275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.state_temp.release(code)
67285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.funcstate.can_trace = old_trace_config
67305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.end_block()
67315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class GILExitNode(StatNode):
67345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
67355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Used as the 'finally' block in a GILStatNode
67365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    state   string   'gil' or 'nogil'
67385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
67395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = []
67415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    state_temp = None
67425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
67445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
67455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
67475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.state_temp:
67485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            variable = self.state_temp.result()
67495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
67505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            variable = None
67515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.state == 'gil':
67535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_release_ensured_gil(variable)
67545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
67555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_acquire_gil(variable)
67565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class EnsureGILNode(GILExitNode):
67595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
67605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Ensure the GIL in nogil functions for cleanup before returning.
67615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
67625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
67645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_ensure_gil(declare_gilstate=False)
67655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)utility_code_for_cimports = {
67675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # utility code (or inlining c) in a pxd (or pyx) file.
67685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # TODO: Consider a generic user-level mechanism for importing
67695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    'cpython.array'         : ("ArrayAPI", "arrayarray.h"),
67705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    'cpython.array.array'   : ("ArrayAPI", "arrayarray.h"),
67715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
67725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CImportStatNode(StatNode):
67745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  cimport statement
67755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
67765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  module_name   string           Qualified name of module being imported
67775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  as_name       string or None   Name specified in "as" clause, if any
67785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = []
67805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
67815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
67825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not env.is_module_scope:
67835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "cimport only allowed at module level")
67845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
67855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        module_scope = env.find_module(self.module_name, self.pos)
67865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if "." in self.module_name:
67875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            names = [EncodedString(name) for name in self.module_name.split(".")]
67885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            top_name = names[0]
67895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            top_module_scope = env.context.find_submodule(top_name)
67905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            module_scope = top_module_scope
67915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for name in names[1:]:
67925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                submodule_scope = module_scope.find_submodule(name)
67935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                module_scope.declare_module(name, submodule_scope, self.pos)
67945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                module_scope = submodule_scope
67955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.as_name:
67965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                env.declare_module(self.as_name, module_scope, self.pos)
67975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
67985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                env.add_imported_module(module_scope)
67995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                env.declare_module(top_name, top_module_scope, self.pos)
68005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
68015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            name = self.as_name or self.module_name
68025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.declare_module(name, module_scope, self.pos)
68035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.module_name in utility_code_for_cimports:
68045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.use_utility_code(UtilityCode.load_cached(
68055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                *utility_code_for_cimports[self.module_name]))
68065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
68075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
68085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
68095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
68105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
68115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
68125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
68135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
68145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class FromCImportStatNode(StatNode):
68155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  from ... cimport statement
68165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
68175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  module_name     string                        Qualified name of module
68185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  imported_names  [(pos, name, as_name, kind)]  Names to be imported
68195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
68205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = []
68215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
68225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
68235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not env.is_module_scope:
68245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "cimport only allowed at module level")
68255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
68265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        module_scope = env.find_module(self.module_name, self.pos)
68275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.add_imported_module(module_scope)
68285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for pos, name, as_name, kind in self.imported_names:
68295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if name == "*":
68305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for local_name, entry in module_scope.entries.items():
68315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    env.add_imported_entry(local_name, entry, pos)
68325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
68335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                entry = module_scope.lookup(name)
68345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if entry:
68355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if kind and not self.declaration_matches(entry, kind):
68365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        entry.redeclared(pos)
68375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    entry.used = 1
68385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
68395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if kind == 'struct' or kind == 'union':
68405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        entry = module_scope.declare_struct_or_union(name,
68415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            kind = kind, scope = None, typedef_flag = 0, pos = pos)
68425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    elif kind == 'class':
68435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        entry = module_scope.declare_c_class(name, pos = pos,
68445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            module_name = self.module_name)
68455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    else:
68465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
68475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        if submodule_scope.parent_module is module_scope:
68485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            env.declare_module(as_name or name, submodule_scope, self.pos)
68495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        else:
68505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            error(pos, "Name '%s' not declared in module '%s'"
68515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                % (name, self.module_name))
68525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
68535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if entry:
68545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    local_name = as_name or name
68555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    env.add_imported_entry(local_name, entry, pos)
68565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
68575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.module_name.startswith('cpython'): # enough for now
68585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.module_name in utility_code_for_cimports:
68595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                env.use_utility_code(UtilityCode.load_cached(
68605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    *utility_code_for_cimports[self.module_name]))
68615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for _, name, _, _ in self.imported_names:
68625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                fqname = '%s.%s' % (self.module_name, name)
68635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if fqname in utility_code_for_cimports:
68645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    env.use_utility_code(UtilityCode.load_cached(
68655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        *utility_code_for_cimports[fqname]))
68665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
68675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def declaration_matches(self, entry, kind):
68685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not entry.is_type:
68695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return 0
68705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        type = entry.type
68715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if kind == 'class':
68725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not type.is_extension_type:
68735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return 0
68745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
68755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not type.is_struct_or_union:
68765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return 0
68775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if kind != type.kind:
68785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return 0
68795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return 1
68805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
68815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
68825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
68835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
68845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
68855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
68865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
68875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
68885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class FromImportStatNode(StatNode):
68895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  from ... import statement
68905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
68915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  module           ImportNode
68925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  items            [(string, NameNode)]
68935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  interned_items   [(string, NameNode, ExprNode)]
68945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  item             PyTempNode            used internally
68955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  import_star      boolean               used internally
68965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
68975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ["module"]
68985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    import_star = 0
68995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
69005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
69015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for name, target in self.items:
69025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if name == "*":
69035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not env.is_module_scope:
69045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(self.pos, "import * only allowed at module level")
69055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    return
69065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                env.has_import_star = 1
69075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.import_star = 1
69085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
69095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                target.analyse_target_declaration(env)
69105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
69115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
69125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        import ExprNodes
69135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.module = self.module.analyse_expressions(env)
69145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.item = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
69155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.interned_items = []
69165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for name, target in self.items:
69175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if name == '*':
69185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for _, entry in env.entries.items():
69195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if not entry.is_type and entry.type.is_extension_type:
69205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        env.use_utility_code(UtilityCode.load_cached("ExtTypeTest", "ObjectHandling.c"))
69215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        break
69225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
69235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                entry =  env.lookup(target.name)
69245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # check whether or not entry is already cimported
69255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if (entry.is_type and entry.type.name == name
69265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        and hasattr(entry.type, 'module_name')):
69275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if entry.type.module_name == self.module.module_name.value:
69285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        # cimported with absolute name
69295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        continue
69305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    try:
69315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        # cimported with relative name
69325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        module = env.find_module(self.module.module_name.value,
69335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                 pos=None)
69345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        if entry.type.module_name == module.qualified_name:
69355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            continue
69365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    except AttributeError:
69375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        pass
69385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                target = target.analyse_target_expression(env, None)  # FIXME?
69395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if target.type is py_object_type:
69405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    coerced_item = None
69415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
69425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    coerced_item = self.item.coerce_to(target.type, env)
69435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.interned_items.append((name, target, coerced_item))
69445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
69455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
69465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
69475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.module.generate_evaluation_code(code)
69485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.import_star:
69495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
69505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                'if (%s(%s) < 0) %s;' % (
69515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    Naming.import_star,
69525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.module.py_result(),
69535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.error_goto(self.pos)))
69545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        item_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
69555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.item.set_cname(item_temp)
69565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.interned_items:
69575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.globalstate.use_utility_code(
69585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                UtilityCode.load_cached("ImportFrom", "ImportExport.c"))
69595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for name, target, coerced_item in self.interned_items:
69605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
69615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                '%s = __Pyx_ImportFrom(%s, %s); %s' % (
69625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    item_temp,
69635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.module.py_result(),
69645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.intern_identifier(name),
69655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.error_goto_if_null(item_temp, self.pos)))
69665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_gotref(item_temp)
69675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if coerced_item is None:
69685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                target.generate_assignment_code(self.item, code)
69695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
69705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                coerced_item.allocate_temp_result(code)
69715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                coerced_item.generate_result_code(code)
69725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                target.generate_assignment_code(coerced_item, code)
69735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_decref_clear(item_temp, py_object_type)
69745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.funcstate.release_temp(item_temp)
69755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.module.generate_disposal_code(code)
69765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.module.free_temps(code)
69775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
69785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
69795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ParallelNode(Node):
69805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
69815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Base class for cython.parallel constructs.
69825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
69835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
69845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    nogil_check = None
69855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
69865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
69875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ParallelStatNode(StatNode, ParallelNode):
69885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
69895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Base class for 'with cython.parallel.parallel():' and 'for i in prange():'.
69905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
69915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    assignments     { Entry(var) : (var.pos, inplace_operator_or_None) }
69925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    assignments to variables in this parallel section
69935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
69945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    parent          parent ParallelStatNode or None
69955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_parallel     indicates whether this node is OpenMP parallel
69965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    (true for #pragma omp parallel for and
69975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              #pragma omp parallel)
69985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
69995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_parallel is true for:
70005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #pragma omp parallel
70025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #pragma omp parallel for
70035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    sections, but NOT for
70055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #pragma omp for
70075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    We need this to determine the sharing attributes.
70095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    privatization_insertion_point   a code insertion point used to make temps
70115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    private (esp. the "nsteps" temp)
70125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    args         tuple          the arguments passed to the parallel construct
70145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    kwargs       DictNode       the keyword arguments passed to the parallel
70155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                construct (replaced by its compile time value)
70165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
70175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ['body', 'num_threads']
70195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    body = None
70215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_prange = False
70235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_nested_prange = False
70245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    error_label_used = False
70265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    num_threads = None
70285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    chunksize = None
70295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    parallel_exc = (
70315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Naming.parallel_exc_type,
70325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Naming.parallel_exc_value,
70335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Naming.parallel_exc_tb,
70345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    )
70355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    parallel_pos_info = (
70375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Naming.parallel_filename,
70385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Naming.parallel_lineno,
70395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Naming.parallel_clineno,
70405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    )
70415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    pos_info = (
70435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Naming.filename_cname,
70445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Naming.lineno_cname,
70455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Naming.clineno_cname,
70465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    )
70475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    critical_section_counter = 0
70495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, pos, **kwargs):
70515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(ParallelStatNode, self).__init__(pos, **kwargs)
70525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # All assignments in this scope
70545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.assignments = kwargs.get('assignments') or {}
70555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # All seen closure cnames and their temporary cnames
70575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.seen_closure_vars = set()
70585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Dict of variables that should be declared (first|last|)private or
70605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # reduction { Entry: (op, lastprivate) }.
70615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # If op is not None, it's a reduction.
70625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.privates = {}
70635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # [NameNode]
70655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.assigned_nodes = []
70665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
70685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.analyse_declarations(env)
70695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.num_threads = None
70715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.kwargs:
70735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Try to find num_threads and chunksize keyword arguments
70745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pairs = []
70755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for dictitem in self.kwargs.key_value_pairs:
70765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if dictitem.key.value == 'num_threads':
70775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.num_threads = dictitem.value
70785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif self.is_prange and dictitem.key.value == 'chunksize':
70795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.chunksize = dictitem.value
70805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
70815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    pairs.append(dictitem)
70825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.kwargs.key_value_pairs = pairs
70845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            try:
70865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.kwargs = self.kwargs.compile_time_value(env)
70875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            except Exception, e:
70885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.kwargs.pos, "Only compile-time values may be "
70895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                       "supplied as keyword arguments")
70905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
70915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.kwargs = {}
70925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for kw, val in self.kwargs.iteritems():
70945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if kw not in self.valid_keyword_arguments:
70955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "Invalid keyword argument: %s" % kw)
70965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
70975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                setattr(self, kw, val)
70985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
70995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
71005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.num_threads:
71015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.num_threads = self.num_threads.analyse_expressions(env)
71025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.chunksize:
71045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.chunksize = self.chunksize.analyse_expressions(env)
71055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body = self.body.analyse_expressions(env)
71075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.analyse_sharing_attributes(env)
71085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.num_threads is not None:
71105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (self.parent and self.parent.num_threads is not None and not
71115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                    self.parent.is_prange):
71125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos,
71135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      "num_threads already declared in outer section")
71145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif self.parent and not self.parent.is_prange:
71155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos,
71165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      "num_threads must be declared in the parent parallel section")
71175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif (self.num_threads.type.is_int and
71185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  self.num_threads.is_literal and
71195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  self.num_threads.compile_time_value(env) <= 0):
71205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos,
71215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      "argument to num_threads must be greater than 0")
71225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.num_threads.is_simple():
71245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.num_threads = self.num_threads.coerce_to(
71255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    PyrexTypes.c_int_type, env).coerce_to_temp(env)
71265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
71275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_sharing_attributes(self, env):
71295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
71305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Analyse the privates for this block and set them in self.privates.
71315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        This should be called in a post-order fashion during the
71325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        analyse_expressions phase
71335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
71345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry, (pos, op) in self.assignments.iteritems():
71355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.is_prange and not self.is_parallel:
71375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # closely nested prange in a with parallel block, disallow
71385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # assigning to privates in the with parallel block (we
71395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # consider it too implicit and magicky for users)
71405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if entry in self.parent.assignments:
71415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(pos,
71425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          "Cannot assign to private of outer parallel block")
71435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    continue
71445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.is_prange and op:
71465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # Again possible, but considered to magicky
71475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(pos, "Reductions not allowed for parallel blocks")
71485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                continue
71495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # By default all variables should have the same values as if
71515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # executed sequentially
71525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lastprivate = True
71535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.propagate_var_privatization(entry, pos, op, lastprivate)
71545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def propagate_var_privatization(self, entry, pos, op, lastprivate):
71565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
71575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Propagate the sharing attributes of a variable. If the privatization is
71585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        determined by a parent scope, done propagate further.
71595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        If we are a prange, we propagate our sharing attributes outwards to
71615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        other pranges. If we are a prange in parallel block and the parallel
71625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        block does not determine the variable private, we propagate to the
71635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        parent of the parent. Recursion stops at parallel blocks, as they have
71645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        no concept of lastprivate or reduction.
71655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        So the following cases propagate:
71675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            sum is a reduction for all loops:
71695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for i in prange(n):
71715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    for j in prange(n):
71725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        for k in prange(n):
71735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            sum += i * j * k
71745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            sum is a reduction for both loops, local_var is private to the
71765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            parallel with block:
71775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for i in prange(n):
71795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    with parallel:
71805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        local_var = ... # private to the parallel
71815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        for j in prange(n):
71825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            sum += i * j
71835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Nested with parallel blocks are disallowed, because they wouldn't
71855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        allow you to propagate lastprivates or reductions:
71865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            #pragma omp parallel for lastprivate(i)
71885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for i in prange(n):
71895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                sum = 0
71915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                #pragma omp parallel private(j, sum)
71935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                with parallel:
71945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    #pragma omp parallel
71965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    with parallel:
71975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
71985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        #pragma omp for lastprivate(j) reduction(+:sum)
71995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        for j in prange(n):
72005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            sum += i
72015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    # sum and j are well-defined here
72035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # sum and j are undefined here
72055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # sum and j are undefined here
72075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
72085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.privates[entry] = (op, lastprivate)
72095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if entry.type.is_memoryviewslice:
72115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(pos, "Memoryview slices can only be shared in parallel sections")
72125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
72135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_prange:
72155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.is_parallel and entry not in self.parent.assignments:
72165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # Parent is a parallel with block
72175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                parent = self.parent.parent
72185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
72195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                parent = self.parent
72205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # We don't need to propagate privates, only reductions and
72225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # lastprivates
72235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if parent and (op or lastprivate):
72245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                parent.propagate_var_privatization(entry, pos, op, lastprivate)
72255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _allocate_closure_temp(self, code, entry):
72275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
72285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Helper function that allocate a temporary for a closure variable that
72295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        is assigned to.
72305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
72315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.parent:
72325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.parent._allocate_closure_temp(code, entry)
72335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if entry.cname in self.seen_closure_vars:
72355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return entry.cname
72365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cname = code.funcstate.allocate_temp(entry.type, True)
72385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Add both the actual cname and the temp cname, as the actual cname
72405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # will be replaced with the temp cname on the entry
72415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.seen_closure_vars.add(entry.cname)
72425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.seen_closure_vars.add(cname)
72435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.modified_entries.append((entry, entry.cname))
72455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("%s = %s;" % (cname, entry.cname))
72465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry.cname = cname
72475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def initialize_privates_to_nan(self, code, exclude=None):
72495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        first = True
72505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry, (op, lastprivate) in self.privates.iteritems():
72525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not op and (not exclude or entry != exclude):
72535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                invalid_value = entry.type.invalid_value()
72545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if invalid_value:
72565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if first:
72575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        code.putln("/* Initialize private variables to "
72585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   "invalid values */")
72595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        first = False
72605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln("%s = %s;" % (entry.cname,
72615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                             entry.type.cast_code(invalid_value)))
72625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def evaluate_before_block(self, code, expr):
72645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        c = self.begin_of_parallel_control_block_point_after_decls
72655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # we need to set the owner to ourselves temporarily, as
72665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # allocate_temp may generate a comment in the middle of our pragma
72675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # otherwise when DebugFlags.debug_temp_code_comments is in effect
72685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        owner = c.funcstate.owner
72695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        c.funcstate.owner = c
72705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        expr.generate_evaluation_code(c)
72715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        c.funcstate.owner = owner
72725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return expr.result()
72745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def put_num_threads(self, code):
72765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
72775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Write self.num_threads if set as the num_threads OpenMP directive
72785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
72795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.num_threads is not None:
72805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put(" num_threads(%s)" % self.evaluate_before_block(code,
72815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                        self.num_threads))
72825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def declare_closure_privates(self, code):
72855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
72865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        If a variable is in a scope object, we need to allocate a temp and
72875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        assign the value from the temp to the variable in the scope object
72885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        after the parallel section. This kind of copying should be done only
72895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        in the outermost parallel section.
72905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
72915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.modified_entries = []
72925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry in self.assignments:
72945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.from_closure or entry.in_closure:
72955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self._allocate_closure_temp(code, entry)
72965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
72975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def release_closure_privates(self, code):
72985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
72995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Release any temps used for variables in scope objects. As this is the
73005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        outermost parallel block, we don't need to delete the cnames from
73015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.seen_closure_vars.
73025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
73035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry, original_cname in self.modified_entries:
73045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("%s = %s;" % (original_cname, entry.cname))
73055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.funcstate.release_temp(entry.cname)
73065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry.cname = original_cname
73075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def privatize_temps(self, code, exclude_temps=()):
73095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
73105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Make any used temporaries private. Before the relevant code block
73115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.start_collecting_temps() should have been called.
73125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
73135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_parallel:
73145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            c = self.privatization_insertion_point
73155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.temps = temps = code.funcstate.stop_collecting_temps()
73175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            privates, firstprivates = [], []
73185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for temp, type in temps:
73195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if type.is_pyobject or type.is_memoryviewslice:
73205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    firstprivates.append(temp)
73215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
73225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    privates.append(temp)
73235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if privates:
73255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                c.put(" private(%s)" % ", ".join(privates))
73265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if firstprivates:
73275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                c.put(" firstprivate(%s)" % ", ".join(firstprivates))
73285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.breaking_label_used:
73305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                shared_vars = [Naming.parallel_why]
73315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.error_label_used:
73325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    shared_vars.extend(self.parallel_exc)
73335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    c.put(" private(%s, %s, %s)" % self.pos_info)
73345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                c.put(" shared(%s)" % ', '.join(shared_vars))
73365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def cleanup_temps(self, code):
73385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Now clean up any memoryview slice and object temporaries
73395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_parallel and not self.is_nested_prange:
73405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("/* Clean up any temporaries */")
73415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for temp, type in self.temps:
73425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if type.is_memoryviewslice:
73435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put_xdecref_memoryviewslice(temp, have_gil=False)
73445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif type.is_pyobject:
73455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put_xdecref(temp, type)
73465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.putln("%s = NULL;" % temp)
73475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def setup_parallel_control_flow_block(self, code):
73495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
73505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Sets up a block that surrounds the parallel block to determine
73515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        how the parallel section was exited. Any kind of return is
73525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        trapped (break, continue, return, exceptions). This is the idea:
73535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        {
73555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            int why = 0;
73565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            #pragma omp parallel
73585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            {
73595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return # -> goto new_return_label;
73605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                goto end_parallel;
73615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            new_return_label:
73635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                why = 3;
73645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                goto end_parallel;
73655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            end_parallel:;
73675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                #pragma omp flush(why) # we need to flush for every iteration
73685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            }
73695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (why == 3)
73715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                goto old_return_label;
73725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        }
73735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
73745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.old_loop_labels = code.new_loop_labels()
73755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.old_error_label = code.new_error_label()
73765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.old_return_label = code.return_label
73775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.return_label = code.new_label(name="return")
73785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.begin_block() # parallel control flow block
73805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.begin_of_parallel_control_block_point = code.insertion_point()
73815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.begin_of_parallel_control_block_point_after_decls = code.insertion_point()
73825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.undef_builtin_expect_apple_gcc_bug(code)
73845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def begin_parallel_block(self, code):
73865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
73875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Each OpenMP thread in a parallel section that contains a with gil block
73885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        must have the thread-state initialized. The call to
73895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        PyGILState_Release() then deallocates our threadstate. If we wouldn't
73905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        do this, each with gil block would allocate and deallocate one, thereby
73915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        losing exception information before it can be saved before leaving the
73925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        parallel section.
73935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
73945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.begin_of_parallel_block = code.insertion_point()
73955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
73965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def end_parallel_block(self, code):
73975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
73985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        To ensure all OpenMP threads have thread states, we ensure the GIL
73995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        in each thread (which creates a thread state if it doesn't exist),
74005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        after which we release the GIL.
74015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        On exit, reacquire the GIL and release the thread state.
74025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        If compiled without OpenMP support (at the C level), then we still have
74045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        to acquire the GIL to decref any object temporaries.
74055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
74065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.error_label_used:
74075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            begin_code = self.begin_of_parallel_block
74085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            end_code = code
74095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            begin_code.putln("#ifdef _OPENMP")
74115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            begin_code.put_ensure_gil(declare_gilstate=True)
74125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            begin_code.putln("Py_BEGIN_ALLOW_THREADS")
74135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            begin_code.putln("#endif /* _OPENMP */")
74145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            end_code.putln("#ifdef _OPENMP")
74165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            end_code.putln("Py_END_ALLOW_THREADS")
74175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            end_code.putln("#else")
74185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            end_code.put_safe("{\n")
74195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            end_code.put_ensure_gil()
74205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            end_code.putln("#endif /* _OPENMP */")
74215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.cleanup_temps(end_code)
74225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            end_code.put_release_ensured_gil()
74235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            end_code.putln("#ifndef _OPENMP")
74245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            end_code.put_safe("}\n")
74255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            end_code.putln("#endif /* _OPENMP */")
74265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def trap_parallel_exit(self, code, should_flush=False):
74285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
74295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Trap any kind of return inside a parallel construct. 'should_flush'
74305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        indicates whether the variable should be flushed, which is needed by
74315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        prange to skip the loop. It also indicates whether we need to register
74325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        a continue (we need this for parallel blocks, but not for prange
74335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        loops, as it is a direct jump there).
74345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        It uses the same mechanism as try/finally:
74365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            1 continue
74375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            2 break
74385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            3 return
74395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            4 error
74405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
74415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        save_lastprivates_label = code.new_label()
74425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        dont_return_label = code.new_label()
74435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.any_label_used = False
74455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.breaking_label_used = False
74465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.error_label_used = False
74475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.parallel_private_temps = []
74495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        all_labels = code.get_all_labels()
74515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Figure this out before starting to generate any code
74535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for label in all_labels:
74545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if code.label_used(label):
74555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.breaking_label_used = (self.breaking_label_used or
74565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            label != code.continue_label)
74575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.any_label_used = True
74585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.any_label_used:
74605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_goto(dont_return_label)
74615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i, label in enumerate(all_labels):
74635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not code.label_used(label):
74645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                continue
74655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            is_continue_label = label == code.continue_label
74675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_label(label)
74695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not (should_flush and is_continue_label):
74715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if label == code.error_label:
74725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.error_label_used = True
74735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.fetch_parallel_exception(code)
74745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("%s = %d;" % (Naming.parallel_why, i + 1))
74765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (self.breaking_label_used and self.is_prange and not
74785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    is_continue_label):
74795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(save_lastprivates_label)
74805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
74815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(dont_return_label)
74825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.any_label_used:
74845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.is_prange and self.breaking_label_used:
74855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # Don't rely on lastprivate, save our lastprivates
74865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_label(save_lastprivates_label)
74875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.save_parallel_vars(code)
74885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_label(dont_return_label)
74905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if should_flush and self.breaking_label_used:
74925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln_openmp("#pragma omp flush(%s)" % Naming.parallel_why)
74935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
74945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def save_parallel_vars(self, code):
74955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
74965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        The following shenanigans are instated when we break, return or
74975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        propagate errors from a prange. In this case we cannot rely on
74985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lastprivate() to do its job, as no iterations may have executed yet
74995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        in the last thread, leaving the values undefined. It is most likely
75005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        that the breaking thread has well-defined values of the lastprivate
75015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        variables, so we keep those values.
75025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
75035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        section_name = ("__pyx_parallel_lastprivates%d" %
75045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            self.critical_section_counter)
75055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln_openmp("#pragma omp critical(%s)" % section_name)
75065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ParallelStatNode.critical_section_counter += 1
75075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.begin_block() # begin critical section
75095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        c = self.begin_of_parallel_control_block_point
75115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        temp_count = 0
75135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry, (op, lastprivate) in self.privates.iteritems():
75145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not lastprivate or entry.type.is_pyobject:
75155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                continue
75165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            type_decl = entry.type.declaration_code("")
75185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            temp_cname = "__pyx_parallel_temp%d" % temp_count
75195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            private_cname = entry.cname
75205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            temp_count += 1
75225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            invalid_value = entry.type.invalid_value()
75245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if invalid_value:
75255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                init = ' = ' + invalid_value
75265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
75275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                init = ''
75285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Declare the parallel private in the outer block
75295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            c.putln("%s %s%s;" % (type_decl, temp_cname, init))
75305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Initialize before escaping
75325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("%s = %s;" % (temp_cname, private_cname))
75335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.parallel_private_temps.append((temp_cname, private_cname))
75355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.end_block() # end critical section
75375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def fetch_parallel_exception(self, code):
75395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
75405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        As each OpenMP thread may raise an exception, we need to fetch that
75415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        exception from the threadstate and save it for after the parallel
75425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        section where it can be re-raised in the master thread.
75435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Although it would seem that __pyx_filename, __pyx_lineno and
75455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        __pyx_clineno are only assigned to under exception conditions (i.e.,
75465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        when we have the GIL), and thus should be allowed to be shared without
75475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        any race condition, they are in fact subject to the same race
75485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        conditions that they were previously when they were global variables
75495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        and functions were allowed to release the GIL:
75505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            thread A                thread B
75525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                acquire
75535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                set lineno
75545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                release
75555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        acquire
75565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        set lineno
75575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        release
75585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                acquire
75595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                fetch exception
75605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                release
75615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        skip the fetch
75625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                deallocate threadstate  deallocate threadstate
75645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
75655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.begin_block()
75665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_ensure_gil(declare_gilstate=True)
75675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln_openmp("#pragma omp flush(%s)" % Naming.parallel_exc_type)
75695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
75705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "if (!%s) {" % Naming.parallel_exc_type)
75715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("__Pyx_ErrFetch(&%s, &%s, &%s);" % self.parallel_exc)
75735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pos_info = chain(*zip(self.parallel_pos_info, self.pos_info))
75745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.funcstate.uses_error_indicator = True
75755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("%s = %s; %s = %s; %s = %s;" % tuple(pos_info))
75765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_gotref(Naming.parallel_exc_type)
75775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln(
75795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "}")
75805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_release_ensured_gil()
75825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.end_block()
75835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def restore_parallel_exception(self, code):
75855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        "Re-raise a parallel exception"
75865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.begin_block()
75875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_ensure_gil(declare_gilstate=True)
75885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_giveref(Naming.parallel_exc_type)
75905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("__Pyx_ErrRestore(%s, %s, %s);" % self.parallel_exc)
75915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pos_info = chain(*zip(self.pos_info, self.parallel_pos_info))
75925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("%s = %s; %s = %s; %s = %s;" % tuple(pos_info))
75935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put_release_ensured_gil()
75955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.end_block()
75965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def restore_labels(self, code):
75985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
75995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Restore all old labels. Call this before the 'else' clause to for
76005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        loops and always before ending the parallel control flow block.
76015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
76025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.set_all_labels(self.old_loop_labels + (self.old_return_label,
76035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                    self.old_error_label))
76045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def end_parallel_control_flow_block(self, code,
76065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        break_=False, continue_=False):
76075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
76085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        This ends the parallel control flow block and based on how the parallel
76095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        section was exited, takes the corresponding action. The break_ and
76105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        continue_ parameters indicate whether these should be propagated
76115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        outwards:
76125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for i in prange(...):
76145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                with cython.parallel.parallel():
76155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    continue
76165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Here break should be trapped in the parallel block, and propagated to
76185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        the for loop.
76195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
76205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        c = self.begin_of_parallel_control_block_point
76215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Firstly, always prefer errors over returning, continue or break
76235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.error_label_used:
76245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            c.putln("const char *%s = NULL; int %s = 0, %s = 0;" %
76255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                self.parallel_pos_info)
76265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            c.putln("PyObject *%s = NULL, *%s = NULL, *%s = NULL;" %
76285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                        self.parallel_exc)
76295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
76315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "if (%s) {" % Naming.parallel_exc_type)
76325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("/* This may have been overridden by a continue, "
76335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       "break or return in another thread. Prefer the error. */")
76345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("%s = 4;" % Naming.parallel_why)
76355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
76365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "}")
76375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if continue_:
76395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            any_label_used = self.any_label_used
76405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
76415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            any_label_used = self.breaking_label_used
76425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if any_label_used:
76445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # __pyx_parallel_why is used, declare and initialize
76455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            c.putln("int %s;" % Naming.parallel_why)
76465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            c.putln("%s = 0;" % Naming.parallel_why)
76475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
76495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "if (%s) {" % Naming.parallel_why)
76505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for temp_cname, private_cname in self.parallel_private_temps:
76525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("%s = %s;" % (private_cname, temp_cname))
76535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("switch (%s) {" % Naming.parallel_why)
76555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if continue_:
76565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put("    case 1: ")
76575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(code.continue_label)
76585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if break_:
76605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put("    case 2: ")
76615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(code.break_label)
76625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put("    case 3: ")
76645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put_goto(code.return_label)
76655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.error_label_used:
76675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.globalstate.use_utility_code(restore_exception_utility_code)
76685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("    case 4:")
76695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.restore_parallel_exception(code)
76705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put_goto(code.error_label)
76715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("}") # end switch
76735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln(
76745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                "}") # end if
76755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.end_block() # end parallel control flow block
76775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.redef_builtin_expect_apple_gcc_bug(code)
76785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # FIXME: improve with version number for OS X Lion
76805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    buggy_platform_macro_condition = "(defined(__APPLE__) || defined(__OSX__))"
76815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    have_expect_condition = "(defined(__GNUC__) && " \
76825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             "(__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))))"
76835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    redef_condition = "(%s && %s)" % (buggy_platform_macro_condition, have_expect_condition)
76845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def undef_builtin_expect_apple_gcc_bug(self, code):
76865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
76875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        A bug on OS X Lion disallows __builtin_expect macros. This code avoids them
76885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
76895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.parent:
76905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.undef_builtin_expect(self.redef_condition)
76915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def redef_builtin_expect_apple_gcc_bug(self, code):
76935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.parent:
76945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.redef_builtin_expect(self.redef_condition)
76955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ParallelWithBlockNode(ParallelStatNode):
76985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
76995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    This node represents a 'with cython.parallel.parallel():' block
77005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
77015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    valid_keyword_arguments = ['num_threads']
77035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    num_threads = None
77055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
77075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(ParallelWithBlockNode, self).analyse_declarations(env)
77085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.args:
77095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "cython.parallel.parallel() does not take "
77105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            "positional arguments")
77115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
77135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.declare_closure_privates(code)
77145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.setup_parallel_control_flow_block(code)
77155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("#ifdef _OPENMP")
77175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put("#pragma omp parallel ")
77185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.privates:
77205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            privates = [e.cname for e in self.privates
77215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    if not e.type.is_pyobject]
77225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put('private(%s)' % ', '.join(privates))
77235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.privatization_insertion_point = code.insertion_point()
77255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.put_num_threads(code)
77265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("")
77275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("#endif /* _OPENMP */")
77295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.begin_block() # parallel block
77315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.begin_parallel_block(code)
77325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.initialize_privates_to_nan(code)
77335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.funcstate.start_collecting_temps()
77345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
77355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.trap_parallel_exit(code)
77365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.privatize_temps(code)
77375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.end_parallel_block(code)
77385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.end_block() # end parallel block
77395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        continue_ = code.label_used(code.continue_label)
77415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        break_ = code.label_used(code.break_label)
77425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.restore_labels(code)
77445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.end_parallel_control_flow_block(code, break_=break_,
77455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                             continue_=continue_)
77465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.release_closure_privates(code)
77475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ParallelRangeNode(ParallelStatNode):
77505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
77515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    This node represents a 'for i in cython.parallel.prange():' construct.
77525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    target       NameNode       the target iteration variable
77545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    else_clause  Node or None   the else clause of this loop
77555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
77565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ['body', 'target', 'else_clause', 'args', 'num_threads',
77585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   'chunksize']
77595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    body = target = else_clause = args = None
77615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    start = stop = step = None
77635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_prange = True
77655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    nogil = None
77675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    schedule = None
77685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    valid_keyword_arguments = ['schedule', 'nogil', 'num_threads', 'chunksize']
77705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, pos, **kwds):
77725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(ParallelRangeNode, self).__init__(pos, **kwds)
77735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Pretend to be a ForInStatNode for control flow analysis
77745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.iterator = PassStatNode(pos)
77755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
77775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(ParallelRangeNode, self).analyse_declarations(env)
77785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.target.analyse_target_declaration(env)
77795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause is not None:
77805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.analyse_declarations(env)
77815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.args or len(self.args) > 3:
77835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "Invalid number of positional arguments to prange")
77845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
77855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if len(self.args) == 1:
77875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.stop, = self.args
77885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif len(self.args) == 2:
77895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.start, self.stop = self.args
77905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
77915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.start, self.stop, self.step = self.args
77925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if hasattr(self.schedule, 'decode'):
77945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.schedule = self.schedule.decode('ascii')
77955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
77965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.schedule not in (None, 'static', 'dynamic', 'guided',
77975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 'runtime'):
77985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "Invalid schedule argument to prange: %s" %
77995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                        (self.schedule,))
78005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
78025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        was_nogil = env.nogil
78035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.nogil:
78045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.nogil = True
78055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.target is None:
78075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(self.pos, "prange() can only be used as part of a for loop")
78085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self
78095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.target = self.target.analyse_target_types(env)
78115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.target.type.is_numeric:
78135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Not a valid type, assume one for now anyway
78145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.target.type.is_pyobject:
78165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # nogil_check will catch the is_pyobject case
78175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.target.pos,
78185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      "Must be of numeric type, not %s" % self.target.type)
78195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.index_type = PyrexTypes.c_py_ssize_t_type
78215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
78225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.index_type = self.target.type
78235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.index_type.signed:
78245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                warning(self.target.pos,
78255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        "Unsigned index type not allowed before OpenMP 3.0",
78265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        level=2)
78275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Setup start, stop and step, allocating temps if needed
78295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.names = 'start', 'stop', 'step'
78305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        start_stop_step = self.start, self.stop, self.step
78315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for node, name in zip(start_stop_step, self.names):
78335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if node is not None:
78345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.analyse_types(env)
78355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not node.type.is_numeric:
78365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(node.pos, "%s argument must be numeric" % name)
78375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    continue
78385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not node.is_literal:
78405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node = node.coerce_to_temp(env)
78415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    setattr(self, name, node)
78425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # As we range from 0 to nsteps, computing the index along the
78445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # way, we need a fitting type for 'i' and 'nsteps'
78455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.index_type = PyrexTypes.widest_numeric_type(
78465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        self.index_type, node.type)
78475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause is not None:
78495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause = self.else_clause.analyse_expressions(env)
78505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Although not actually an assignment in this scope, it should be
78525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # treated as such to ensure it is unpacked if a closure temp, and to
78535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ensure lastprivate behaviour and propagation. If the target index is
78545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # not a NameNode, it won't have an entry, and an error was issued by
78555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ParallelRangeTransform
78565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if hasattr(self.target, 'entry'):
78575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.assignments[self.target.entry] = self.target.pos, None
78585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node = super(ParallelRangeNode, self).analyse_expressions(env)
78605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.chunksize:
78625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not node.schedule:
78635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.chunksize.pos,
78645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      "Must provide schedule with chunksize")
78655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif node.schedule == 'runtime':
78665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.chunksize.pos,
78675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      "Chunksize not valid for the schedule runtime")
78685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif (node.chunksize.type.is_int and
78695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  node.chunksize.is_literal and
78705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  node.chunksize.compile_time_value(env) <= 0):
78715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.chunksize.pos, "Chunksize must not be negative")
78725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.chunksize = node.chunksize.coerce_to(
78745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                PyrexTypes.c_int_type, env).coerce_to_temp(env)
78755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.nogil:
78775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            env.nogil = was_nogil
78785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.is_nested_prange = node.parent and node.parent.is_prange
78805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.is_nested_prange:
78815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            parent = node
78825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            while parent.parent and parent.parent.is_prange:
78835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                parent = parent.parent
78845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            parent.assignments.update(node.assignments)
78865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            parent.privates.update(node.privates)
78875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            parent.assigned_nodes.extend(node.assigned_nodes)
78885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
78895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def nogil_check(self, env):
78915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        names = 'start', 'stop', 'step', 'target'
78925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        nodes = self.start, self.stop, self.step, self.target
78935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for name, node in zip(names, nodes):
78945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if node is not None and node.type.is_pyobject:
78955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.pos, "%s may not be a Python object "
78965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                "as we don't have the GIL" % name)
78975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
78985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
78995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
79005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Generate code in the following steps
79015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            1)  copy any closure variables determined thread-private
79035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                into temporaries
79045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            2)  allocate temps for start, stop and step
79065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            3)  generate a loop that calculates the total number of steps,
79085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                which then computes the target iteration variable for every step:
79095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    for i in prange(start, stop, step):
79115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        ...
79125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                becomes
79145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    nsteps = (stop - start) / step;
79165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    i = start;
79175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    #pragma omp parallel for lastprivate(i)
79195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    for (temp = 0; temp < nsteps; temp++) {
79205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        i = start + step * temp;
79215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        ...
79225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    }
79235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Note that accumulation of 'i' would have a data dependency
79255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                between iterations.
79265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                Also, you can't do this
79285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    for (i = start; i < stop; i += step)
79305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        ...
79315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                as the '<' operator should become '>' for descending loops.
79335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                'for i from x < i < y:' does not suffer from this problem
79345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                as the relational operator is known at compile time!
79355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            4) release our temps and write back any private closure variables
79375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
79385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.declare_closure_privates(code)
79395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # This can only be a NameNode
79415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        target_index_cname = self.target.entry.cname
79425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # This will be used as the dict to format our code strings, holding
79445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # the start, stop , step, temps and target cnames
79455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        fmt_dict = {
79465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            'target': target_index_cname,
79475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        }
79485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Setup start, stop and step, allocating temps if needed
79505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        start_stop_step = self.start, self.stop, self.step
79515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        defaults = '0', '0', '1'
79525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for node, name, default in zip(start_stop_step, self.names, defaults):
79535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if node is None:
79545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                result = default
79555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif node.is_literal:
79565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                result = node.get_constant_c_result_code()
79575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
79585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.generate_evaluation_code(code)
79595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                result = node.result()
79605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            fmt_dict[name] = result
79625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        fmt_dict['i'] = code.funcstate.allocate_temp(self.index_type, False)
79645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        fmt_dict['nsteps'] = code.funcstate.allocate_temp(self.index_type, False)
79655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # TODO: check if the step is 0 and if so, raise an exception in a
79675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # 'with gil' block. For now, just abort
79685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("if (%(step)s == 0) abort();" % fmt_dict)
79695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.setup_parallel_control_flow_block(code) # parallel control flow block
79715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.control_flow_var_code_point = code.insertion_point()
79735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Note: nsteps is private in an outer scope if present
79755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("%(nsteps)s = (%(stop)s - %(start)s) / %(step)s;" % fmt_dict)
79765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # The target iteration variable might not be initialized, do it only if
79785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # we are executing at least 1 iteration, otherwise we should leave the
79795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # target unaffected. The target iteration variable is firstprivate to
79805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # shut up compiler warnings caused by lastprivate, as the compiler
79815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # erroneously believes that nsteps may be <= 0, leaving the private
79825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # target index uninitialized
79835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("if (%(nsteps)s > 0)" % fmt_dict)
79845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.begin_block() # if block
79855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.generate_loop(code, fmt_dict)
79865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.end_block() # end if block
79875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.restore_labels(code)
79895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.else_clause:
79915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.breaking_label_used:
79925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.put("if (%s < 2)" % Naming.parallel_why)
79935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.begin_block() # else block
79955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("/* else */")
79965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.else_clause.generate_execution_code(code)
79975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.end_block() # end else block
79985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ------ cleanup ------
80005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.end_parallel_control_flow_block(code) # end parallel control flow block
80015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # And finally, release our privates and write back any closure
80035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # variables
80045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for temp in start_stop_step:
80055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if temp is not None:
80065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                temp.generate_disposal_code(code)
80075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                temp.free_temps(code)
80085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.funcstate.release_temp(fmt_dict['i'])
80105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.funcstate.release_temp(fmt_dict['nsteps'])
80115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.release_closure_privates(code)
80135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_loop(self, code, fmt_dict):
80155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_nested_prange:
80165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("#if 0")
80175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
80185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("#ifdef _OPENMP")
80195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.is_parallel:
80215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put("#pragma omp for")
80225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.privatization_insertion_point = code.insertion_point()
80235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            reduction_codepoint = self.parent.privatization_insertion_point
80245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
80255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put("#pragma omp parallel")
80265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.privatization_insertion_point = code.insertion_point()
80275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            reduction_codepoint = self.privatization_insertion_point
80285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("")
80295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.putln("#endif /* _OPENMP */")
80305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.begin_block() # pragma omp parallel begin block
80325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Initialize the GIL if needed for this thread
80345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.begin_parallel_block(code)
80355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.is_nested_prange:
80375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("#if 0")
80385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
80395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code.putln("#ifdef _OPENMP")
80405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put("#pragma omp for")
80415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry, (op, lastprivate) in self.privates.iteritems():
80435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Don't declare the index variable as a reduction
80445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if op and op in "+*-&^|" and entry != self.target.entry:
80455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if entry.type.is_pyobject:
80465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(self.pos, "Python objects cannot be reductions")
80475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
80485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    #code.put(" reduction(%s:%s)" % (op, entry.cname))
80495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    # This is the only way reductions + nesting works in gcc4.5
80505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    reduction_codepoint.put(
80515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                " reduction(%s:%s)" % (op, entry.cname))
80525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
80535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if entry == self.target.entry:
80545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put(" firstprivate(%s)" % entry.cname)
80555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put(" lastprivate(%s)" % entry.cname)
80565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    continue
80575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not entry.type.is_pyobject:
80595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if lastprivate:
80605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        private = 'lastprivate'
80615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    else:
80625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        private = 'private'
80635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    code.put(" %s(%s)" % (private, entry.cname))
80655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.schedule:
80675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.chunksize:
80685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                chunksize = ", %s" % self.evaluate_before_block(code,
80695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                                self.chunksize)
80705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
80715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                chunksize = ""
80725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.put(" schedule(%s%s)" % (self.schedule, chunksize))
80745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.put_num_threads(reduction_codepoint)
80765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("")
80785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("#endif /* _OPENMP */")
80795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.put("for (%(i)s = 0; %(i)s < %(nsteps)s; %(i)s++)" % fmt_dict)
80815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.begin_block() # for loop block
80825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        guard_around_body_codepoint = code.insertion_point()
80845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Start if guard block around the body. This may be unnecessary, but
80865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # at least it doesn't spoil indentation
80875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.begin_block()
80885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.putln("%(target)s = %(start)s + %(step)s * %(i)s;" % fmt_dict)
80905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.initialize_privates_to_nan(code, exclude=self.target.entry)
80915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_parallel:
80935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.funcstate.start_collecting_temps()
80945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.body.generate_execution_code(code)
80965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.trap_parallel_exit(code, should_flush=True)
80975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.privatize_temps(code)
80985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
80995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.breaking_label_used:
81005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Put a guard around the loop body in case return, break or
81015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # exceptions might be used
81025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            guard_around_body_codepoint.putln("if (%s < 2)" % Naming.parallel_why)
81035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.end_block() # end guard around loop body
81055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        code.end_block() # end for loop block
81065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_parallel:
81085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Release the GIL and deallocate the thread state
81095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.end_parallel_block(code)
81105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            code.end_block() # pragma omp parallel end block
81115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CnameDecoratorNode(StatNode):
81145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
81155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    This node is for the cname decorator in CythonUtilityCode:
81165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        @cname('the_cname')
81185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cdef func(...):
81195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            ...
81205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    In case of a cdef class the cname specifies the objstruct_cname.
81225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    node        the node to which the cname decorator is applied
81245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    cname       the cname the node should get
81255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
81265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    child_attrs = ['node']
81285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_declarations(self, env):
81305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.node.analyse_declarations(env)
81315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node = self.node
81335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(node, CompilerDirectivesNode):
81345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = node.body.stats[0]
81355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.is_function = isinstance(node, FuncDefNode)
81375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        is_struct_or_enum = isinstance(node, (CStructOrUnionDefNode,
81385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                   CEnumDefNode))
81395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        e = node.entry
81405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_function:
81425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            e.cname = self.cname
81435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            e.func_cname = self.cname
81445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            e.used = True
81455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if e.pyfunc_cname and '.' in e.pyfunc_cname:
81465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                e.pyfunc_cname = self.mangle(e.pyfunc_cname)
81475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif is_struct_or_enum:
81485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            e.cname = e.type.cname = self.cname
81495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
81505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            scope = node.scope
81515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            e.cname = self.cname
81535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            e.type.objstruct_cname = self.cname + '_obj'
81545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            e.type.typeobj_cname = Naming.typeobj_prefix + self.cname
81555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            e.type.typeptr_cname = self.cname + '_type'
81565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            e.type.scope.namespace_cname = e.type.typeptr_cname
81575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            e.as_variable.cname = py_object_type.cast_code(e.type.typeptr_cname)
81595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            scope.scope_prefix = self.cname + "_"
81615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for name, entry in scope.entries.iteritems():
81635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if entry.func_cname:
81645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    entry.func_cname = self.mangle(entry.cname)
81655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if entry.pyfunc_cname:
81665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    entry.pyfunc_cname = self.mangle(entry.pyfunc_cname)
81675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def mangle(self, cname):
81695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if '.' in cname:
81705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # remove __pyx_base from func_cname
81715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cname = cname.split('.')[-1]
81725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return '%s_%s' % (self.cname, cname)
81735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def analyse_expressions(self, env):
81755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.node = self.node.analyse_expressions(env)
81765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self
81775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_function_definitions(self, env, code):
81795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        "Ensure a prototype for every @cname method in the right place"
81805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.is_function and env.is_c_class_scope:
81815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # method in cdef class, generate a prototype in the header
81825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            h_code = code.globalstate['utility_code_proto']
81835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if isinstance(self.node, DefNode):
81855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.node.generate_function_header(
81865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            h_code, with_pymethdef=False, proto_only=True)
81875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
81885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                import ModuleNode
81895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                entry = self.node.entry
81905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                cname = entry.cname
81915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                entry.cname = entry.func_cname
81925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ModuleNode.generate_cfunction_declaration(
81945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        entry,
81955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        env.global_scope(),
81965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        h_code,
81975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        definition=True)
81985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
81995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                entry.cname = cname
82005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
82015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.node.generate_function_definitions(env, code)
82025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
82035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def generate_execution_code(self, code):
82045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.node.generate_execution_code(code)
82055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
82065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
82075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#------------------------------------------------------------------------------------
82085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#
82095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#  Runtime support code
82105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#
82115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#------------------------------------------------------------------------------------
82125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
82135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)if Options.gcc_branch_hints:
82145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    branch_prediction_macros = """
82155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/* Test for GCC > 2.95 */
82165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(__GNUC__) \
82175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)))
82185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  #define likely(x)   __builtin_expect(!!(x), 1)
82195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  #define unlikely(x) __builtin_expect(!!(x), 0)
82205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else /* !__GNUC__ or GCC < 2.95 */
82215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  #define likely(x)   (x)
82225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  #define unlikely(x) (x)
82235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif /* __GNUC__ */
82245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)"""
82255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)else:
82265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    branch_prediction_macros = """
82275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define likely(x)   (x)
82285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define unlikely(x) (x)
82295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)"""
82305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
82315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#------------------------------------------------------------------------------------
82325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
82335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)printing_utility_code = UtilityCode.load_cached("Print", "Printing.c")
82345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)printing_one_utility_code = UtilityCode.load_cached("PrintOne", "Printing.c")
82355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
82365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#------------------------------------------------------------------------------------
82375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
82385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# Exception raising code
82395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#
82405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# Exceptions are raised by __Pyx_Raise() and stored as plain
82415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# type/value/tb in PyThreadState->curexc_*.  When being caught by an
82425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# 'except' statement, curexc_* is moved over to exc_* by
82435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# __Pyx_GetException()
82445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
82455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)restore_exception_utility_code = UtilityCode.load_cached("PyErrFetchRestore", "Exceptions.c")
82465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)raise_utility_code = UtilityCode.load_cached("RaiseException", "Exceptions.c")
82475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)get_exception_utility_code = UtilityCode.load_cached("GetException", "Exceptions.c")
82485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)swap_exception_utility_code = UtilityCode.load_cached("SwapException", "Exceptions.c")
82495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)reset_exception_utility_code = UtilityCode.load_cached("SaveResetException", "Exceptions.c")
82505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)traceback_utility_code = UtilityCode.load_cached("AddTraceback", "Exceptions.c")
82515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
82525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#------------------------------------------------------------------------------------
82535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
82545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)get_exception_tuple_utility_code = UtilityCode(proto="""
82555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
82565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)""",
82575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# I doubt that calling __Pyx_GetException() here is correct as it moves
82585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# the exception from tstate->curexc_* to tstate->exc_*, which prevents
82595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# exception handlers later on from receiving it.
82605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)impl = """
82615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static PyObject *__Pyx_GetExceptionTuple(void) {
82625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    PyObject *type = NULL, *value = NULL, *tb = NULL;
82635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (__Pyx_GetException(&type, &value, &tb) == 0) {
82645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        PyObject* exc_info = PyTuple_New(3);
82655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (exc_info) {
82665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            Py_INCREF(type);
82675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            Py_INCREF(value);
82685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            Py_INCREF(tb);
82695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            PyTuple_SET_ITEM(exc_info, 0, type);
82705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            PyTuple_SET_ITEM(exc_info, 1, value);
82715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            PyTuple_SET_ITEM(exc_info, 2, tb);
82725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return exc_info;
82735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        }
82745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
82755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return NULL;
82765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
82775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)""",
82785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)requires=[get_exception_utility_code])
8279