15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import cython
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)cython.declare(PyrexTypes=object, Naming=object, ExprNodes=object, Nodes=object,
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               Options=object, UtilNodes=object, LetNode=object,
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               LetRefNode=object, TreeFragment=object, EncodedString=object,
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               error=object, warning=object, copy=object)
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import PyrexTypes
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import Naming
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import ExprNodes
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import Nodes
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import Options
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import Builtin
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Cython.Compiler.Visitor import VisitorTransform, TreeVisitor
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Cython.Compiler.Visitor import CythonTransform, EnvTransform, ScopeTrackingTransform
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Cython.Compiler.UtilNodes import LetNode, LetRefNode, ResultRefNode
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Cython.Compiler.TreeFragment import TreeFragment
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Cython.Compiler.StringEncoding import EncodedString
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Cython.Compiler.Errors import error, warning, CompileError, InternalError
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Cython.Compiler.Code import UtilityCode
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import copy
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class NameNodeCollector(TreeVisitor):
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """Collect all NameNodes of a (sub-)tree in the ``name_nodes``
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    attribute.
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self):
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(NameNodeCollector, self).__init__()
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.name_nodes = []
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_NameNode(self, node):
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.name_nodes.append(node)
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_Node(self, node):
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self._visitchildren(node, None)
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class SkipDeclarations(object):
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Variable and function declarations can often have a deep tree structure,
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    and yet most transformations don't need to descend to this depth.
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Declaration nodes are removed after AnalyseDeclarationsTransform, so there
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is no need to use this for transformations after that point.
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CTypeDefNode(self, node):
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CVarDefNode(self, node):
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CDeclaratorNode(self, node):
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CBaseTypeNode(self, node):
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CEnumDefNode(self, node):
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CStructOrUnionDefNode(self, node):
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class NormalizeTree(CythonTransform):
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    This transform fixes up a few things after parsing
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    in order to make the parse tree more suitable for
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    transforms.
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    a) After parsing, blocks with only one statement will
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    be represented by that statement, not by a StatListNode.
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    When doing transforms this is annoying and inconsistent,
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    as one cannot in general remove a statement in a consistent
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    way and so on. This transform wraps any single statements
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    in a StatListNode containing a single statement.
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    b) The PassStatNode is a noop and serves no purpose beyond
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    plugging such one-statement blocks; i.e., once parsed a
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)`    "pass" can just as well be represented using an empty
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    StatListNode. This means less special cases to worry about
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    in subsequent transforms (one always checks to see if a
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    StatListNode has no children to see if the block is empty).
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, context):
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(NormalizeTree, self).__init__(context)
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.is_in_statlist = False
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.is_in_expr = False
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ExprNode(self, node):
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        stacktmp = self.is_in_expr
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.is_in_expr = True
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.is_in_expr = stacktmp
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_StatNode(self, node, is_listcontainer=False):
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        stacktmp = self.is_in_statlist
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.is_in_statlist = is_listcontainer
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.is_in_statlist = stacktmp
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.is_in_statlist and not self.is_in_expr:
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return Nodes.StatListNode(pos=node.pos, stats=[node])
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_StatListNode(self, node):
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.is_in_statlist = True
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.is_in_statlist = False
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ParallelAssignmentNode(self, node):
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.visit_StatNode(node, True)
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CEnumDefNode(self, node):
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.visit_StatNode(node, True)
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CStructOrUnionDefNode(self, node):
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.visit_StatNode(node, True)
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_PassStatNode(self, node):
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """Eliminate PassStatNode"""
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.is_in_statlist:
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return Nodes.StatListNode(pos=node.pos, stats=[])
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return []
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ExprStatNode(self, node):
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """Eliminate useless string literals"""
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.expr.is_string_literal:
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.visit_PassStatNode(node)
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.visit_StatNode(node)
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CDeclaratorNode(self, node):
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class PostParseError(CompileError): pass
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# error strings checked by unit tests, so define them
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ERR_CDEF_INCLASS = 'Cannot assign default value to fields in cdef classes, structs or unions'
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ERR_BUF_DEFAULTS = 'Invalid buffer defaults specification (see docs)'
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ERR_INVALID_SPECIALATTR_TYPE = 'Special attributes must not have a type declared'
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class PostParse(ScopeTrackingTransform):
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Basic interpretation of the parse tree, as well as validity
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    checking that can be done on a very basic level on the parse
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    tree (while still not being a problem with the basic syntax,
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    as such).
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Specifically:
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    - Default values to cdef assignments are turned into single
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    assignments following the declaration (everywhere but in class
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bodies, where they raise a compile error)
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    - Interpret some node structures into Python runtime values.
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Some nodes take compile-time arguments (currently:
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    TemplatedTypeNode[args] and __cythonbufferdefaults__ = {args}),
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    which should be interpreted. This happens in a general way
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    and other steps should be taken to ensure validity.
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Type arguments cannot be interpreted in this way.
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    - For __cythonbufferdefaults__ the arguments are checked for
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    validity.
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    TemplatedTypeNode has its directives interpreted:
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Any first positional argument goes into the "dtype" attribute,
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    any "ndim" keyword argument goes into the "ndim" attribute and
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    so on. Also it is checked that the directive combination is valid.
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    - __cythonbufferdefaults__ attributes are parsed and put into the
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    type information.
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Note: Currently Parsing.py does a lot of interpretation and
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    reorganization that can be refactored into this transform
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if a more pure Abstract Syntax Tree is wanted.
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, context):
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(PostParse, self).__init__(context)
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.specialattribute_handlers = {
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            '__cythonbufferdefaults__' : self.handle_bufferdefaults
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        }
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ModuleNode(self, node):
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lambda_counter = 1
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.genexpr_counter = 1
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return super(PostParse, self).visit_ModuleNode(node)
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_LambdaNode(self, node):
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # unpack a lambda expression into the corresponding DefNode
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lambda_id = self.lambda_counter
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.lambda_counter += 1
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.lambda_name = EncodedString(u'lambda%d' % lambda_id)
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        collector = YieldNodeCollector()
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        collector.visitchildren(node.result_expr)
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if collector.yields or isinstance(node.result_expr, ExprNodes.YieldExprNode):
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            body = Nodes.ExprStatNode(
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.result_expr.pos, expr=node.result_expr)
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            body = Nodes.ReturnStatNode(
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.result_expr.pos, value=node.result_expr)
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.def_node = Nodes.DefNode(
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.pos, name=node.name, lambda_name=node.lambda_name,
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            args=node.args, star_arg=node.star_arg,
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            starstar_arg=node.starstar_arg,
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            body=body, doc=None)
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_GeneratorExpressionNode(self, node):
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # unpack a generator expression into the corresponding DefNode
2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        genexpr_id = self.genexpr_counter
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.genexpr_counter += 1
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.genexpr_name = EncodedString(u'genexpr%d' % genexpr_id)
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.def_node = Nodes.DefNode(node.pos, name=node.name,
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      doc=None,
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      args=[], star_arg=None,
2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      starstar_arg=None,
2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      body=node.loop)
2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # cdef variables
2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def handle_bufferdefaults(self, decl):
2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not isinstance(decl.default, ExprNodes.DictNode):
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            raise PostParseError(decl.pos, ERR_BUF_DEFAULTS)
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.scope_node.buffer_defaults_node = decl.default
2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.scope_node.buffer_defaults_pos = decl.pos
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CVarDefNode(self, node):
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # This assumes only plain names and pointers are assignable on
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # declaration. Also, it makes use of the fact that a cdef decl
2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # must appear before the first use, so we don't have to deal with
2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # "i = 3; cdef int i = i" and can simply move the nodes around.
2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        try:
2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.visitchildren(node)
2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            stats = [node]
2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            newdecls = []
2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for decl in node.declarators:
2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                declbase = decl
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                while isinstance(declbase, Nodes.CPtrDeclaratorNode):
2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    declbase = declbase.base
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if isinstance(declbase, Nodes.CNameDeclaratorNode):
2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if declbase.default is not None:
2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        if self.scope_type in ('cclass', 'pyclass', 'struct'):
2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            if isinstance(self.scope_node, Nodes.CClassDefNode):
2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                handler = self.specialattribute_handlers.get(decl.name)
2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                if handler:
2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    if decl is not declbase:
2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        raise PostParseError(decl.pos, ERR_INVALID_SPECIALATTR_TYPE)
2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    handler(decl)
2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    continue # Remove declaration
2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            raise PostParseError(decl.pos, ERR_CDEF_INCLASS)
2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        first_assignment = self.scope_type != 'module'
2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        stats.append(Nodes.SingleAssignmentNode(node.pos,
2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            lhs=ExprNodes.NameNode(node.pos, name=declbase.name),
2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            rhs=declbase.default, first=first_assignment))
2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        declbase.default = None
2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                newdecls.append(decl)
2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.declarators = newdecls
2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return stats
2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        except PostParseError, e:
2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # An error in a cdef clause is ok, simply remove the declaration
2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # and try to move on to report more errors
2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.context.nonfatal_error(e)
2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Split parallel assignments (a,b = b,a) into separate partial
2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # assignments that are executed rhs-first using temps.  This
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # restructuring must be applied before type analysis so that known
2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # types on rhs and lhs can be matched directly.  It is required in
2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # the case that the types cannot be coerced to a Python type in
2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # order to assign from a tuple.
2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_SingleAssignmentNode(self, node):
2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self._visit_assignment_node(node, [node.lhs, node.rhs])
2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CascadedAssignmentNode(self, node):
2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self._visit_assignment_node(node, node.lhs_list + [node.rhs])
2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _visit_assignment_node(self, node, expr_list):
2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """Flatten parallel assignments into separate single
2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        assignments or cascaded assignments.
2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if sum([ 1 for expr in expr_list
2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 if expr.is_sequence_constructor or expr.is_string_literal ]) < 2:
2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # no parallel assignments => nothing to do
2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        expr_list_list = []
2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        flatten_parallel_assignments(expr_list, expr_list_list)
3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        temp_refs = []
3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        eliminate_rhs_duplicates(expr_list_list, temp_refs)
3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        nodes = []
3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for expr_list in expr_list_list:
3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lhs_list = expr_list[:-1]
3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs = expr_list[-1]
3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if len(lhs_list) == 1:
3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node = Nodes.SingleAssignmentNode(rhs.pos,
3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    lhs = lhs_list[0], rhs = rhs)
3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node = Nodes.CascadedAssignmentNode(rhs.pos,
3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    lhs_list = lhs_list, rhs = rhs)
3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            nodes.append(node)
3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if len(nodes) == 1:
3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            assign_node = nodes[0]
3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            assign_node = Nodes.ParallelAssignmentNode(nodes[0].pos, stats = nodes)
3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if temp_refs:
3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            duplicates_and_temps = [ (temp.expression, temp)
3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     for temp in temp_refs ]
3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            sort_common_subsequences(duplicates_and_temps)
3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for _, temp_ref in duplicates_and_temps[::-1]:
3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                assign_node = LetNode(temp_ref, assign_node)
3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return assign_node
3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _flatten_sequence(self, seq, result):
3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in seq.args:
3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if arg.is_sequence_constructor:
3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self._flatten_sequence(arg, result)
3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                result.append(arg)
3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return result
3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_DelStatNode(self, node):
3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.args = self._flatten_sequence(node, [])
3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ExceptClauseNode(self, node):
3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.is_except_as:
3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # except-as must delete NameNode target at the end
3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            del_target = Nodes.DelStatNode(
3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.pos,
3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                args=[ExprNodes.NameNode(
3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node.target.pos, name=node.target.name)],
3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ignore_nonexisting=True)
3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.body = Nodes.StatListNode(
3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.pos,
3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                stats=[Nodes.TryFinallyStatNode(
3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node.pos,
3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    body=node.body,
3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    finally_clause=Nodes.StatListNode(
3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        node.pos,
3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        stats=[del_target]))])
3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def eliminate_rhs_duplicates(expr_list_list, ref_node_sequence):
3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """Replace rhs items by LetRefNodes if they appear more than once.
3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Creates a sequence of LetRefNodes that set up the required temps
3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    and appends them to ref_node_sequence.  The input list is modified
3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    in-place.
3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    seen_nodes = set()
3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ref_nodes = {}
3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def find_duplicates(node):
3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.is_literal or node.is_name:
3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # no need to replace those; can't include attributes here
3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # as their access is not necessarily side-effect free
3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node in seen_nodes:
3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if node not in ref_nodes:
3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ref_node = LetRefNode(node)
3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ref_nodes[node] = ref_node
3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ref_node_sequence.append(ref_node)
3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            seen_nodes.add(node)
3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if node.is_sequence_constructor:
3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for item in node.args:
3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    find_duplicates(item)
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for expr_list in expr_list_list:
3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        rhs = expr_list[-1]
3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        find_duplicates(rhs)
3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if not ref_nodes:
3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return
3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def substitute_nodes(node):
3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node in ref_nodes:
3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return ref_nodes[node]
3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif node.is_sequence_constructor:
3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.args = list(map(substitute_nodes, node.args))
3975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
3985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # replace nodes inside of the common subexpressions
4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for node in ref_nodes:
4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.is_sequence_constructor:
4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.args = list(map(substitute_nodes, node.args))
4035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # replace common subexpressions on all rhs items
4055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for expr_list in expr_list_list:
4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        expr_list[-1] = substitute_nodes(expr_list[-1])
4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def sort_common_subsequences(items):
4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """Sort items/subsequences so that all items and subsequences that
4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    an item contains appear before the item itself.  This is needed
4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    because each rhs item must only be evaluated once, so its value
4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    must be evaluated first and then reused when packing sequences
4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    that contain it.
4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    This implies a partial order, and the sort must be stable to
4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    preserve the original order as much as possible, so we use a
4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    simple insertion sort (which is very fast for short sequences, the
4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    normal case in practice).
4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def contains(seq, x):
4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for item in seq:
4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if item is x:
4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return True
4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif item.is_sequence_constructor and contains(item.args, x):
4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return True
4265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return False
4275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def lower_than(a,b):
4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return b.is_sequence_constructor and contains(b.args, a)
4295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for pos, item in enumerate(items):
4315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        key = item[1] # the ResultRefNode which has already been injected into the sequences
4325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        new_pos = pos
4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i in xrange(pos-1, -1, -1):
4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if lower_than(key, items[i][0]):
4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                new_pos = i
4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if new_pos != pos:
4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for i in xrange(pos, new_pos, -1):
4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                items[i] = items[i-1]
4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            items[new_pos] = item
4405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def unpack_string_to_character_literals(literal):
4425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    chars = []
4435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    pos = literal.pos
4445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    stype = literal.__class__
4455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    sval = literal.value
4465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    sval_type = sval.__class__
4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for char in sval:
4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cval = sval_type(char)
4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        chars.append(stype(pos, value=cval, constant_result=cval))
4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return chars
4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def flatten_parallel_assignments(input, output):
4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  The input is a list of expression nodes, representing the LHSs
4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  and RHS of one (possibly cascaded) assignment statement.  For
4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  sequence constructors, rearranges the matching parts of both
4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  sides into a list of equivalent assignments between the
4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  individual elements.  This transformation is applied
4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #  recursively, so that nested structures get matched as well.
4595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    rhs = input[-1]
4605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (not (rhs.is_sequence_constructor or isinstance(rhs, ExprNodes.UnicodeNode))
4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        or not sum([lhs.is_sequence_constructor for lhs in input[:-1]])):
4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        output.append(input)
4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return
4645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    complete_assignments = []
4665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if rhs.is_sequence_constructor:
4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        rhs_args = rhs.args
4695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    elif rhs.is_string_literal:
4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        rhs_args = unpack_string_to_character_literals(rhs)
4715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    rhs_size = len(rhs_args)
4735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    lhs_targets = [ [] for _ in xrange(rhs_size) ]
4745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    starred_assignments = []
4755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for lhs in input[:-1]:
4765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not lhs.is_sequence_constructor:
4775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if lhs.is_starred:
4785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(lhs.pos, "starred assignment target must be in a list or tuple")
4795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            complete_assignments.append(lhs)
4805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            continue
4815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lhs_size = len(lhs.args)
4825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        starred_targets = sum([1 for expr in lhs.args if expr.is_starred])
4835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if starred_targets > 1:
4845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(lhs.pos, "more than 1 starred expression in assignment")
4855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            output.append([lhs,rhs])
4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            continue
4875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif lhs_size - starred_targets > rhs_size:
4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(lhs.pos, "need more than %d value%s to unpack"
4895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  % (rhs_size, (rhs_size != 1) and 's' or ''))
4905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            output.append([lhs,rhs])
4915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            continue
4925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif starred_targets:
4935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            map_starred_assignment(lhs_targets, starred_assignments,
4945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   lhs.args, rhs_args)
4955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif lhs_size < rhs_size:
4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(lhs.pos, "too many values to unpack (expected %d, got %d)"
4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  % (lhs_size, rhs_size))
4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            output.append([lhs,rhs])
4995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            continue
5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for targets, expr in zip(lhs_targets, lhs.args):
5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                targets.append(expr)
5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if complete_assignments:
5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        complete_assignments.append(rhs)
5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        output.append(complete_assignments)
5075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # recursively flatten partial assignments
5095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for cascade, rhs in zip(lhs_targets, rhs_args):
5105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if cascade:
5115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cascade.append(rhs)
5125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            flatten_parallel_assignments(cascade, output)
5135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # recursively flatten starred assignments
5155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for cascade in starred_assignments:
5165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if cascade[0].is_sequence_constructor:
5175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            flatten_parallel_assignments(cascade, output)
5185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
5195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            output.append(cascade)
5205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def map_starred_assignment(lhs_targets, starred_assignments, lhs_args, rhs_args):
5225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Appends the fixed-position LHS targets to the target list that
5235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # appear left and right of the starred argument.
5245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    #
5255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # The starred_assignments list receives a new tuple
5265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # (lhs_target, rhs_values_list) that maps the remaining arguments
5275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # (those that match the starred target) to a list.
5285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # left side of the starred target
5305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for i, (targets, expr) in enumerate(zip(lhs_targets, lhs_args)):
5315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if expr.is_starred:
5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            starred = i
5335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lhs_remaining = len(lhs_args) - i - 1
5345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            break
5355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        targets.append(expr)
5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    else:
5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        raise InternalError("no starred arg found when splitting starred assignment")
5385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # right side of the starred target
5405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for i, (targets, expr) in enumerate(zip(lhs_targets[-lhs_remaining:],
5415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            lhs_args[starred + 1:])):
5425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        targets.append(expr)
5435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # the starred target itself, must be assigned a (potentially empty) list
5455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    target = lhs_args[starred].target # unpack starred node
5465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    starred_rhs = rhs_args[starred:]
5475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if lhs_remaining:
5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        starred_rhs = starred_rhs[:-lhs_remaining]
5495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if starred_rhs:
5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pos = starred_rhs[0].pos
5515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    else:
5525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pos = target.pos
5535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    starred_assignments.append([
5545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        target, ExprNodes.ListNode(pos=pos, args=starred_rhs)])
5555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class PxdPostParse(CythonTransform, SkipDeclarations):
5585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
5595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Basic interpretation/validity checking that should only be
5605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    done on pxd trees.
5615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    A lot of this checking currently happens in the parser; but
5635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    what is listed below happens here.
5645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    - "def" functions are let through only if they fill the
5665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    getbuffer/releasebuffer slots
5675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    - cdef functions are let through only if they are on the
5695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    top level and are declared "inline"
5705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
5715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ERR_INLINE_ONLY = "function definition in pxd file must be declared 'cdef inline'"
5725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ERR_NOGO_WITH_INLINE = "inline function definition in pxd file cannot be '%s'"
5735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __call__(self, node):
5755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.scope_type = 'pxd'
5765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return super(PxdPostParse, self).__call__(node)
5775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CClassDefNode(self, node):
5795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old = self.scope_type
5805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.scope_type = 'cclass'
5815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
5825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.scope_type = old
5835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
5845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_FuncDefNode(self, node):
5865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # FuncDefNode always come with an implementation (without
5875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # an imp they are CVarDefNodes..)
5885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        err = self.ERR_INLINE_ONLY
5895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (isinstance(node, Nodes.DefNode) and self.scope_type == 'cclass'
5915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            and node.name in ('__getbuffer__', '__releasebuffer__')):
5925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            err = None # allow these slots
5935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(node, Nodes.CFuncDefNode):
5955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (u'inline' in node.modifiers and
5965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.scope_type in ('pxd', 'cclass')):
5975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.inline_in_pxd = True
5985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if node.visibility != 'private':
5995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    err = self.ERR_NOGO_WITH_INLINE % node.visibility
6005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif node.api:
6015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    err = self.ERR_NOGO_WITH_INLINE % 'api'
6025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
6035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    err = None # allow inline function
6045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
6055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                err = self.ERR_INLINE_ONLY
6065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if err:
6085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.context.nonfatal_error(PostParseError(node.pos, err))
6095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
6105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
6115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
6125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
6145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
6155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    After parsing, directives can be stored in a number of places:
6165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    - #cython-comments at the top of the file (stored in ModuleNode)
6175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    - Command-line arguments overriding these
6185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    - @cython.directivename decorators
6195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    - with cython.directivename: statements
6205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    This transform is responsible for interpreting these various sources
6225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    and store the directive in two ways:
6235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    - Set the directives attribute of the ModuleNode for global directives.
6245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    - Use a CompilerDirectivesNode to override directives for a subtree.
6255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    (The first one is primarily to not have to modify with the tree
6275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    structure, so that ModuleNode stay on top.)
6285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    The directives are stored in dictionaries from name to value in effect.
6305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Each such dictionary is always filled in for all possible directives,
6315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    using default values where no value is given by the user.
6325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    The available directives are controlled in Options.py.
6345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Note that we have to run this prior to analysis, and so some minor
6365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    duplication of functionality has to occur: We manually track cimports
6375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    and which names the "cython" module may have been imported to.
6385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
6395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    unop_method_nodes = {
6405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        'typeof': ExprNodes.TypeofNode,
6415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        'operator.address': ExprNodes.AmpersandNode,
6435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        'operator.dereference': ExprNodes.DereferenceNode,
6445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        'operator.preincrement' : ExprNodes.inc_dec_constructor(True, '++'),
6455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        'operator.predecrement' : ExprNodes.inc_dec_constructor(True, '--'),
6465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        'operator.postincrement': ExprNodes.inc_dec_constructor(False, '++'),
6475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        'operator.postdecrement': ExprNodes.inc_dec_constructor(False, '--'),
6485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # For backwards compatability.
6505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        'address': ExprNodes.AmpersandNode,
6515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
6525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    binop_method_nodes = {
6545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        'operator.comma'        : ExprNodes.c_binop_constructor(','),
6555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
6565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    special_methods = set(['declare', 'union', 'struct', 'typedef',
6585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           'sizeof', 'cast', 'pointer', 'compiled',
6595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           'NULL', 'fused_type', 'parallel'])
6605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    special_methods.update(unop_method_nodes.keys())
6615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    valid_parallel_directives = set([
6635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        "parallel",
6645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        "prange",
6655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        "threadid",
6665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#        "threadsavailable",
6675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ])
6685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, context, compilation_directive_defaults):
6705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(InterpretCompilerDirectives, self).__init__(context)
6715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.compilation_directive_defaults = {}
6725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for key, value in compilation_directive_defaults.items():
6735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.compilation_directive_defaults[unicode(key)] = copy.deepcopy(value)
6745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.cython_module_names = set()
6755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.directive_names = {}
6765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.parallel_directives = {}
6775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def check_directive_scope(self, pos, directive, scope):
6795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        legal_scopes = Options.directive_scopes.get(directive, None)
6805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if legal_scopes and scope not in legal_scopes:
6815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.context.nonfatal_error(PostParseError(pos, 'The %s compiler directive '
6825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        'is not allowed in %s scope' % (directive, scope)))
6835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return False
6845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
6855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (directive not in Options.directive_defaults
6865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    and directive not in Options.directive_types):
6875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(pos, "Invalid directive: '%s'." % (directive,))
6885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return True
6895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Set up processing and handle the cython: comments.
6915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ModuleNode(self, node):
6925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for key, value in node.directive_comments.items():
6935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not self.check_directive_scope(node.pos, key, 'module'):
6945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.wrong_scope_error(node.pos, key, 'module')
6955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                del node.directive_comments[key]
6965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.module_scope = node.scope
6985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        directives = copy.deepcopy(Options.directive_defaults)
7005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        directives.update(copy.deepcopy(self.compilation_directive_defaults))
7015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        directives.update(node.directive_comments)
7025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.directives = directives
7035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.directives = directives
7045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.parallel_directives = self.parallel_directives
7055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
7065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.cython_module_names = self.cython_module_names
7075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
7085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # The following four functions track imports and cimports that
7105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # begin with "cython"
7115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def is_cython_directive(self, name):
7125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return (name in Options.directive_types or
7135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                name in self.special_methods or
7145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                PyrexTypes.parse_basic_type(name))
7155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def is_parallel_directive(self, full_name, pos):
7175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
7185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Checks to see if fullname (e.g. cython.parallel.prange) is a valid
7195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        parallel directive. If it is a star import it also updates the
7205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        parallel_directives.
7215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
7225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        result = (full_name + ".").startswith("cython.parallel.")
7235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if result:
7255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            directive = full_name.split('.')
7265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if full_name == u"cython.parallel":
7275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.parallel_directives[u"parallel"] = u"cython.parallel"
7285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif full_name == u"cython.parallel.*":
7295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for name in self.valid_parallel_directives:
7305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.parallel_directives[name] = u"cython.parallel.%s" % name
7315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif (len(directive) != 3 or
7325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  directive[-1] not in self.valid_parallel_directives):
7335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(pos, "No such directive: %s" % full_name)
7345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.module_scope.use_utility_code(
7365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                UtilityCode.load_cached("InitThreads", "ModuleSetupCode.c"))
7375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return result
7395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CImportStatNode(self, node):
7415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.module_name == u"cython":
7425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.cython_module_names.add(node.as_name or u"cython")
7435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif node.module_name.startswith(u"cython."):
7445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if node.module_name.startswith(u"cython.parallel."):
7455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.pos, node.module_name + " is not a module")
7465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if node.module_name == u"cython.parallel":
7475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if node.as_name and node.as_name != u"cython":
7485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.parallel_directives[node.as_name] = node.module_name
7495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
7505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.cython_module_names.add(u"cython")
7515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.parallel_directives[
7525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    u"cython.parallel"] = node.module_name
7535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.module_scope.use_utility_code(
7545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    UtilityCode.load_cached("InitThreads", "ModuleSetupCode.c"))
7555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif node.as_name:
7565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.directive_names[node.as_name] = node.module_name[7:]
7575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
7585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.cython_module_names.add(u"cython")
7595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # if this cimport was a compiler directive, we don't
7605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # want to leave the cimport node sitting in the tree
7615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
7625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
7635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_FromCImportStatNode(self, node):
7655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (node.module_name == u"cython") or \
7665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               node.module_name.startswith(u"cython."):
7675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            submodule = (node.module_name + u".")[7:]
7685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            newimp = []
7695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for pos, name, as_name, kind in node.imported_names:
7715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                full_name = submodule + name
7725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                qualified_name = u"cython." + full_name
7735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.is_parallel_directive(qualified_name, node.pos):
7755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    # from cython cimport parallel, or
7765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    # from cython.parallel cimport parallel, prange, ...
7775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.parallel_directives[as_name or name] = qualified_name
7785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif self.is_cython_directive(full_name):
7795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if as_name is None:
7805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        as_name = full_name
7815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.directive_names[as_name] = full_name
7835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if kind is not None:
7845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        self.context.nonfatal_error(PostParseError(pos,
7855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            "Compiler directive imports must be plain imports"))
7865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
7875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    newimp.append((pos, name, as_name, kind))
7885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not newimp:
7905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return None
7915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.imported_names = newimp
7935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
7945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_FromImportStatNode(self, node):
7965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (node.module.module_name.value == u"cython") or \
7975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               node.module.module_name.value.startswith(u"cython."):
7985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            submodule = (node.module.module_name.value + u".")[7:]
7995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            newimp = []
8005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for name, name_node in node.items:
8015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                full_name = submodule + name
8025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                qualified_name = u"cython." + full_name
8035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.is_parallel_directive(qualified_name, node.pos):
8045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.parallel_directives[name_node.name] = qualified_name
8055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif self.is_cython_directive(full_name):
8065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.directive_names[name_node.name] = full_name
8075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
8085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    newimp.append((name, name_node))
8095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not newimp:
8105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return None
8115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.items = newimp
8125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
8135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_SingleAssignmentNode(self, node):
8155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(node.rhs, ExprNodes.ImportNode):
8165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            module_name = node.rhs.module_name.value
8175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            is_parallel = (module_name + u".").startswith(u"cython.parallel.")
8185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if module_name != u"cython" and not is_parallel:
8205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return node
8215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            module_name = node.rhs.module_name.value
8235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            as_name = node.lhs.name
8245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = Nodes.CImportStatNode(node.pos,
8265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         module_name = module_name,
8275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         as_name = as_name)
8285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = self.visit_CImportStatNode(node)
8295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
8305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.visitchildren(node)
8315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
8335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_NameNode(self, node):
8355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.name in self.cython_module_names:
8365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.is_cython_module = True
8375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
8385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.cython_attribute = self.directive_names.get(node.name)
8395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
8405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def try_to_parse_directives(self, node):
8425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # If node is the contents of an directive (in a with statement or
8435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # decorator), returns a list of (directivename, value) pairs.
8445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Otherwise, returns None
8455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(node, ExprNodes.CallNode):
8465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.visit(node.function)
8475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            optname = node.function.as_cython_attribute()
8485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if optname:
8495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                directivetype = Options.directive_types.get(optname)
8505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if directivetype:
8515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    args, kwds = node.explicit_args_kwds()
8525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    directives = []
8535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    key_value_pairs = []
8545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if kwds is not None and directivetype is not dict:
8555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        for keyvalue in kwds.key_value_pairs:
8565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            key, value = keyvalue
8575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            sub_optname = "%s.%s" % (optname, key.value)
8585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            if Options.directive_types.get(sub_optname):
8595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                directives.append(self.try_to_parse_directive(sub_optname, [value], None, keyvalue.pos))
8605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            else:
8615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                key_value_pairs.append(keyvalue)
8625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        if not key_value_pairs:
8635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            kwds = None
8645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        else:
8655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            kwds.key_value_pairs = key_value_pairs
8665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        if directives and not kwds and not args:
8675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            return directives
8685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    directives.append(self.try_to_parse_directive(optname, args, kwds, node.function.pos))
8695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    return directives
8705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif isinstance(node, (ExprNodes.AttributeNode, ExprNodes.NameNode)):
8715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.visit(node)
8725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            optname = node.as_cython_attribute()
8735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if optname:
8745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                directivetype = Options.directive_types.get(optname)
8755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if directivetype is bool:
8765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    return [(optname, True)]
8775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif directivetype is None:
8785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    return [(optname, None)]
8795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
8805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    raise PostParseError(
8815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        node.pos, "The '%s' directive should be used as a function call." % optname)
8825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return None
8835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def try_to_parse_directive(self, optname, args, kwds, pos):
8855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        directivetype = Options.directive_types.get(optname)
8865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if len(args) == 1 and isinstance(args[0], ExprNodes.NoneNode):
8875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return optname, Options.directive_defaults[optname]
8885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif directivetype is bool:
8895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if kwds is not None or len(args) != 1 or not isinstance(args[0], ExprNodes.BoolNode):
8905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                raise PostParseError(pos,
8915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    'The %s directive takes one compile-time boolean argument' % optname)
8925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return (optname, args[0].value)
8935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif directivetype is int:
8945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if kwds is not None or len(args) != 1 or not isinstance(args[0], ExprNodes.IntNode):
8955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                raise PostParseError(pos,
8965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    'The %s directive takes one compile-time integer argument' % optname)
8975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return (optname, int(args[0].value))
8985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif directivetype is str:
8995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if kwds is not None or len(args) != 1 or not isinstance(
9005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    args[0], (ExprNodes.StringNode, ExprNodes.UnicodeNode)):
9015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                raise PostParseError(pos,
9025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    'The %s directive takes one compile-time string argument' % optname)
9035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return (optname, str(args[0].value))
9045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif directivetype is type:
9055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if kwds is not None or len(args) != 1:
9065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                raise PostParseError(pos,
9075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    'The %s directive takes one type argument' % optname)
9085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return (optname, args[0])
9095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif directivetype is dict:
9105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if len(args) != 0:
9115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                raise PostParseError(pos,
9125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    'The %s directive takes no prepositional arguments' % optname)
9135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return optname, dict([(key.value, value) for key, value in kwds.key_value_pairs])
9145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif directivetype is list:
9155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if kwds and len(kwds) != 0:
9165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                raise PostParseError(pos,
9175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    'The %s directive takes no keyword arguments' % optname)
9185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return optname, [ str(arg.value) for arg in args ]
9195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif callable(directivetype):
9205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if kwds is not None or len(args) != 1 or not isinstance(
9215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    args[0], (ExprNodes.StringNode, ExprNodes.UnicodeNode)):
9225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                raise PostParseError(pos,
9235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    'The %s directive takes one compile-time string argument' % optname)
9245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return (optname, directivetype(optname, str(args[0].value)))
9255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
9265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            assert False
9275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_with_directives(self, body, directives):
9295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        olddirectives = self.directives
9305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        newdirectives = copy.copy(olddirectives)
9315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        newdirectives.update(directives)
9325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.directives = newdirectives
9335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        assert isinstance(body, Nodes.StatListNode), body
9345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        retbody = self.visit_Node(body)
9355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        directive = Nodes.CompilerDirectivesNode(pos=retbody.pos, body=retbody,
9365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                 directives=newdirectives)
9375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.directives = olddirectives
9385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return directive
9395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Handle decorators
9415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_FuncDefNode(self, node):
9425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        directives = self._extract_directives(node, 'function')
9435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not directives:
9445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.visit_Node(node)
9455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        body = Nodes.StatListNode(node.pos, stats=[node])
9465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.visit_with_directives(body, directives)
9475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CVarDefNode(self, node):
9495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        directives = self._extract_directives(node, 'function')
9505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not directives:
9515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
9525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for name, value in directives.iteritems():
9535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if name == 'locals':
9545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.directive_locals = value
9555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif name != 'final':
9565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.context.nonfatal_error(PostParseError(
9575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node.pos,
9585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    "Cdef functions can only take cython.locals() "
9595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    "or final decorators, got %s." % name))
9605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        body = Nodes.StatListNode(node.pos, stats=[node])
9615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.visit_with_directives(body, directives)
9625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CClassDefNode(self, node):
9645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        directives = self._extract_directives(node, 'cclass')
9655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not directives:
9665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.visit_Node(node)
9675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        body = Nodes.StatListNode(node.pos, stats=[node])
9685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.visit_with_directives(body, directives)
9695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_PyClassDefNode(self, node):
9715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        directives = self._extract_directives(node, 'class')
9725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not directives:
9735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.visit_Node(node)
9745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        body = Nodes.StatListNode(node.pos, stats=[node])
9755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.visit_with_directives(body, directives)
9765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _extract_directives(self, node, scope_name):
9785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not node.decorators:
9795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return {}
9805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Split the decorators into two lists -- real decorators and directives
9815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        directives = []
9825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        realdecs = []
9835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for dec in node.decorators:
9845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            new_directives = self.try_to_parse_directives(dec.decorator)
9855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if new_directives is not None:
9865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for directive in new_directives:
9875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if self.check_directive_scope(node.pos, directive[0], scope_name):
9885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        directives.append(directive)
9895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
9905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                realdecs.append(dec)
9915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if realdecs and isinstance(node, (Nodes.CFuncDefNode, Nodes.CClassDefNode, Nodes.CVarDefNode)):
9925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            raise PostParseError(realdecs[0].pos, "Cdef functions/classes cannot take arbitrary decorators.")
9935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
9945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.decorators = realdecs
9955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # merge or override repeated directives
9965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        optdict = {}
9975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        directives.reverse() # Decorators coming first take precedence
9985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for directive in directives:
9995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            name, value = directive
10005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if name in optdict:
10015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                old_value = optdict[name]
10025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # keywords and arg lists can be merged, everything
10035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # else overrides completely
10045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if isinstance(old_value, dict):
10055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    old_value.update(value)
10065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif isinstance(old_value, list):
10075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    old_value.extend(value)
10085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
10095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    optdict[name] = value
10105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
10115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                optdict[name] = value
10125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return optdict
10135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Handle with statements
10155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_WithStatNode(self, node):
10165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        directive_dict = {}
10175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for directive in self.try_to_parse_directives(node.manager) or []:
10185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if directive is not None:
10195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if node.target is not None:
10205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.context.nonfatal_error(
10215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        PostParseError(node.pos, "Compiler directive with statements cannot contain 'as'"))
10225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
10235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    name, value = directive
10245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if name in ('nogil', 'gil'):
10255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        # special case: in pure mode, "with nogil" spells "with cython.nogil"
10265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        node = Nodes.GILStatNode(node.pos, state = name, body = node.body)
10275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        return self.visit_Node(node)
10285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if self.check_directive_scope(node.pos, name, 'with statement'):
10295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        directive_dict[name] = value
10305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if directive_dict:
10315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.visit_with_directives(node.body, directive_dict)
10325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.visit_Node(node)
10335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ParallelRangeTransform(CythonTransform, SkipDeclarations):
10365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
10375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Transform cython.parallel stuff. The parallel_directives come from the
10385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    module node, set there by InterpretCompilerDirectives.
10395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        x = cython.parallel.threadavailable()   -> ParallelThreadAvailableNode
10415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        with nogil, cython.parallel.parallel(): -> ParallelWithBlockNode
10425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            print cython.parallel.threadid()    -> ParallelThreadIdNode
10435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for i in cython.parallel.prange(...):  -> ParallelRangeNode
10445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ...
10455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
10465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # a list of names, maps 'cython.parallel.prange' in the code to
10485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # ['cython', 'parallel', 'prange']
10495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    parallel_directive = None
10505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Indicates whether a namenode in an expression is the cython module
10525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    namenode_is_cython_module = False
10535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Keep track of whether we are the context manager of a 'with' statement
10555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    in_context_manager_section = False
10565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # One of 'prange' or 'with parallel'. This is used to disallow closely
10585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # nested 'with parallel:' blocks
10595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    state = None
10605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    directive_to_node = {
10625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        u"cython.parallel.parallel": Nodes.ParallelWithBlockNode,
10635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # u"cython.parallel.threadsavailable": ExprNodes.ParallelThreadsAvailableNode,
10645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        u"cython.parallel.threadid": ExprNodes.ParallelThreadIdNode,
10655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        u"cython.parallel.prange": Nodes.ParallelRangeNode,
10665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
10675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def node_is_parallel_directive(self, node):
10695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node.name in self.parallel_directives or node.is_cython_module
10705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def get_directive_class_node(self, node):
10725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
10735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Figure out which parallel directive was used and return the associated
10745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Node class.
10755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        E.g. for a cython.parallel.prange() call we return ParallelRangeNode
10775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
10785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.namenode_is_cython_module:
10795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            directive = '.'.join(self.parallel_directive)
10805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
10815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            directive = self.parallel_directives[self.parallel_directive[0]]
10825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            directive = '%s.%s' % (directive,
10835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   '.'.join(self.parallel_directive[1:]))
10845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            directive = directive.rstrip('.')
10855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cls = self.directive_to_node.get(directive)
10875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if cls is None and not (self.namenode_is_cython_module and
10885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                self.parallel_directive[0] != 'parallel'):
10895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(node.pos, "Invalid directive: %s" % directive)
10905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.namenode_is_cython_module = False
10925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.parallel_directive = None
10935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return cls
10955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ModuleNode(self, node):
10975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
10985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        If any parallel directives were imported, copy them over and visit
10995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        the AST
11005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
11015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.parallel_directives:
11025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.parallel_directives = node.parallel_directives
11035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.visit_Node(node)
11045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # No parallel directives were imported, so they can't be used :)
11065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
11075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_NameNode(self, node):
11095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.node_is_parallel_directive(node):
11105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.parallel_directive = [node.name]
11115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.namenode_is_cython_module = node.is_cython_module
11125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
11135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_AttributeNode(self, node):
11155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
11165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.parallel_directive:
11175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.parallel_directive.append(node.attribute)
11185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
11195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CallNode(self, node):
11215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visit(node.function)
11225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.parallel_directive:
11235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
11245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # We are a parallel directive, replace this node with the
11265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # corresponding ParallelSomethingSomething node
11275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(node, ExprNodes.GeneralCallNode):
11295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            args = node.positional_args.args
11305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            kwargs = node.keyword_args
11315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
11325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            args = node.args
11335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            kwargs = {}
11345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        parallel_directive_class = self.get_directive_class_node(node)
11365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if parallel_directive_class:
11375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Note: in case of a parallel() the body is set by
11385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # visit_WithStatNode
11395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = parallel_directive_class(node.pos, args=args, kwargs=kwargs)
11405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
11425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_WithStatNode(self, node):
11445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        "Rewrite with cython.parallel.parallel() blocks"
11455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        newnode = self.visit(node.manager)
11465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(newnode, Nodes.ParallelWithBlockNode):
11485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.state == 'parallel with':
11495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.manager.pos,
11505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      "Nested parallel with blocks are disallowed")
11515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.state = 'parallel with'
11535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            body = self.visit(node.body)
11545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.state = None
11555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            newnode.body = body
11575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return newnode
11585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif self.parallel_directive:
11595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            parallel_directive_class = self.get_directive_class_node(node)
11605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not parallel_directive_class:
11625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # There was an error, stop here and now
11635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return None
11645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if parallel_directive_class is Nodes.ParallelWithBlockNode:
11665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.pos, "The parallel directive must be called")
11675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return None
11685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.body = self.visit(node.body)
11705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
11715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ForInStatNode(self, node):
11735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        "Rewrite 'for i in cython.parallel.prange(...):'"
11745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visit(node.iterator)
11755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visit(node.target)
11765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        in_prange = isinstance(node.iterator.sequence,
11785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               Nodes.ParallelRangeNode)
11795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        previous_state = self.state
11805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if in_prange:
11825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # This will replace the entire ForInStatNode, so copy the
11835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # attributes
11845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            parallel_range_node = node.iterator.sequence
11855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            parallel_range_node.target = node.target
11875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            parallel_range_node.body = node.body
11885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            parallel_range_node.else_clause = node.else_clause
11895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = parallel_range_node
11915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not isinstance(node.target, ExprNodes.NameNode):
11935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.target.pos,
11945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      "Can only iterate over an iteration variable")
11955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.state = 'prange'
11975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visit(node.body)
11995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.state = previous_state
12005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visit(node.else_clause)
12015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
12025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit(self, node):
12045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        "Visit a node that may be None"
12055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node is not None:
12065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return super(ParallelRangeTransform, self).visit(node)
12075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class WithTransform(CythonTransform, SkipDeclarations):
12105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_WithStatNode(self, node):
12115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node, 'body')
12125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pos = node.pos
12135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        body, target, manager = node.body, node.target, node.manager
12145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.enter_call = ExprNodes.SimpleCallNode(
12155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pos, function=ExprNodes.AttributeNode(
12165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pos, obj=ExprNodes.CloneNode(manager),
12175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                attribute=EncodedString('__enter__'),
12185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                is_special_lookup=True),
12195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            args=[],
12205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            is_temp=True)
12215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if target is not None:
12225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            body = Nodes.StatListNode(
12235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pos, stats = [
12245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    Nodes.WithTargetAssignmentStatNode(
12255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        pos, lhs = target,
12265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        rhs = ResultRefNode(node.enter_call),
12275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        orig_rhs = node.enter_call),
12285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    body])
12295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        excinfo_target = ExprNodes.TupleNode(pos, slow=True, args=[
12315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            ExprNodes.ExcValueNode(pos) for _ in range(3)])
12325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        except_clause = Nodes.ExceptClauseNode(
12335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pos, body=Nodes.IfStatNode(
12345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pos, if_clauses=[
12355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    Nodes.IfClauseNode(
12365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        pos, condition=ExprNodes.NotNode(
12375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            pos, operand=ExprNodes.WithExitCallNode(
12385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                pos, with_stat=node,
12395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                test_if_run=False,
12405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                args=excinfo_target)),
12415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        body=Nodes.ReraiseStatNode(pos),
12425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        ),
12435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    ],
12445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else_clause=None),
12455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pattern=None,
12465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            target=None,
12475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            excinfo_target=excinfo_target,
12485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            )
12495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.body = Nodes.TryFinallyStatNode(
12515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pos, body=Nodes.TryExceptStatNode(
12525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pos, body=body,
12535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                except_clauses=[except_clause],
12545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else_clause=None,
12555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ),
12565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            finally_clause=Nodes.ExprStatNode(
12575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pos, expr=ExprNodes.WithExitCallNode(
12585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    pos, with_stat=node,
12595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    test_if_run=True,
12605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    args=ExprNodes.TupleNode(
12615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        pos, args=[ExprNodes.NoneNode(pos) for _ in range(3)]
12625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        ))),
12635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            handle_error_case=False,
12645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            )
12655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
12665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ExprNode(self, node):
12685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # With statements are never inside expressions.
12695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
12705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class DecoratorTransform(ScopeTrackingTransform, SkipDeclarations):
12735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """Originally, this was the only place where decorators were
12745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    transformed into the corresponding calling code.  Now, this is
12755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    done directly in DefNode and PyClassDefNode to avoid reassignments
12765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    to the function/class name - except for cdef class methods.  For
12775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    those, the reassignment is required as methods are originally
12785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    defined in the PyMethodDef struct.
12795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    The IndirectionNode allows DefNode to override the decorator
12815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
12825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_DefNode(self, func_node):
12845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        scope_type = self.scope_type
12855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        func_node = self.visit_FuncDefNode(func_node)
12865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if scope_type != 'cclass' or not func_node.decorators:
12875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return func_node
12885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.handle_decorators(func_node, func_node.decorators,
12895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      func_node.name)
12905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def handle_decorators(self, node, decorators, name):
12925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        decorator_result = ExprNodes.NameNode(node.pos, name = name)
12935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for decorator in decorators[::-1]:
12945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            decorator_result = ExprNodes.SimpleCallNode(
12955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                decorator.pos,
12965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                function = decorator.decorator,
12975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                args = [decorator_result])
12985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
12995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        name_node = ExprNodes.NameNode(node.pos, name = name)
13005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        reassignment = Nodes.SingleAssignmentNode(
13015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.pos,
13025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lhs = name_node,
13035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs = decorator_result)
13045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        reassignment = Nodes.IndirectionNode([reassignment])
13065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.decorator_indirection = reassignment
13075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return [node, reassignment]
13085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CnameDirectivesTransform(CythonTransform, SkipDeclarations):
13105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
13115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Only part of the CythonUtilityCode pipeline. Must be run before
13125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DecoratorTransform in case this is a decorator for a cdef class.
13135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    It filters out @cname('my_cname') decorators and rewrites them to
13145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CnameDecoratorNodes.
13155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
13165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def handle_function(self, node):
13185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not getattr(node, 'decorators', None):
13195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.visit_Node(node)
13205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for i, decorator in enumerate(node.decorators):
13225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            decorator = decorator.decorator
13235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (isinstance(decorator, ExprNodes.CallNode) and
13255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    decorator.function.is_name and
13265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    decorator.function.name == 'cname'):
13275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                args, kwargs = decorator.explicit_args_kwds()
13285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if kwargs:
13305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    raise AssertionError(
13315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            "cname decorator does not take keyword arguments")
13325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if len(args) != 1:
13345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    raise AssertionError(
13355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            "cname decorator takes exactly one argument")
13365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not (args[0].is_literal and
13385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        args[0].type == Builtin.str_type):
13395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    raise AssertionError(
13405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            "argument to cname decorator must be a string literal")
13415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                cname = args[0].compile_time_value(None).decode('UTF-8')
13435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                del node.decorators[i]
13445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node = Nodes.CnameDecoratorNode(pos=node.pos, node=node,
13455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                cname=cname)
13465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                break
13475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.visit_Node(node)
13495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    visit_FuncDefNode = handle_function
13515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    visit_CClassDefNode = handle_function
13525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    visit_CEnumDefNode = handle_function
13535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    visit_CStructOrUnionDefNode = handle_function
13545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ForwardDeclareTypes(CythonTransform):
13575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CompilerDirectivesNode(self, node):
13595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env = self.module_scope
13605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old = env.directives
13615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.directives = node.directives
13625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
13635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env.directives = old
13645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
13655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ModuleNode(self, node):
13675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.module_scope = node.scope
13685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.module_scope.directives = node.directives
13695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
13705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
13715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CDefExternNode(self, node):
13735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_cinclude_flag = self.module_scope.in_cinclude
13745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.module_scope.in_cinclude = 1
13755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
13765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.module_scope.in_cinclude = old_cinclude_flag
13775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
13785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CEnumDefNode(self, node):
13805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.declare(self.module_scope)
13815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
13825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CStructOrUnionDefNode(self, node):
13845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.name not in self.module_scope.entries:
13855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.declare(self.module_scope)
13865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
13875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CClassDefNode(self, node):
13895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.class_name not in self.module_scope.entries:
13905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.declare(self.module_scope)
13915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
13925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class AnalyseDeclarationsTransform(EnvTransform):
13955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    basic_property = TreeFragment(u"""
13975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)property NAME:
13985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __get__(self):
13995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return ATTR
14005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __set__(self, value):
14015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ATTR = value
14025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """, level='c_class', pipeline=[NormalizeTree(None)])
14035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    basic_pyobject_property = TreeFragment(u"""
14045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)property NAME:
14055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __get__(self):
14065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return ATTR
14075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __set__(self, value):
14085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ATTR = value
14095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __del__(self):
14105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ATTR = None
14115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """, level='c_class', pipeline=[NormalizeTree(None)])
14125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    basic_property_ro = TreeFragment(u"""
14135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)property NAME:
14145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __get__(self):
14155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return ATTR
14165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """, level='c_class', pipeline=[NormalizeTree(None)])
14175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    struct_or_union_wrapper = TreeFragment(u"""
14195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)cdef class NAME:
14205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    cdef TYPE value
14215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, MEMBER=None):
14225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cdef int count
14235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        count = 0
14245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        INIT_ASSIGNMENTS
14255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if IS_UNION and count > 1:
14265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            raise ValueError, "At most one union member should be specified."
14275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __str__(self):
14285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return STR_FORMAT % MEMBER_TUPLE
14295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __repr__(self):
14305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return REPR_FORMAT % MEMBER_TUPLE
14315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """, pipeline=[NormalizeTree(None)])
14325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    init_assignment = TreeFragment(u"""
14345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)if VALUE is not None:
14355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ATTR = VALUE
14365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    count += 1
14375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """, pipeline=[NormalizeTree(None)])
14385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    fused_function = None
14405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    in_lambda = 0
14415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __call__(self, root):
14435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # needed to determine if a cdef var is declared after it's used.
14445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.seen_vars_stack = []
14455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.fused_error_funcs = set()
14465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super_class = super(AnalyseDeclarationsTransform, self)
14475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self._super_visit_FuncDefNode = super_class.visit_FuncDefNode
14485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return super_class.__call__(root)
14495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_NameNode(self, node):
14515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.seen_vars_stack[-1].add(node.name)
14525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
14535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ModuleNode(self, node):
14555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.seen_vars_stack.append(set())
14565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.analyse_declarations(self.current_env())
14575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
14585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.seen_vars_stack.pop()
14595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
14605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_LambdaNode(self, node):
14625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.in_lambda += 1
14635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.analyse_declarations(self.current_env())
14645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
14655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.in_lambda -= 1
14665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
14675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CClassDefNode(self, node):
14695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node = self.visit_ClassDefNode(node)
14705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.scope and node.scope.implemented:
14715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            stats = []
14725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for entry in node.scope.var_entries:
14735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if entry.needs_property:
14745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    property = self.create_Property(entry)
14755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    property.analyse_declarations(node.scope)
14765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    self.visit(property)
14775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    stats.append(property)
14785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if stats:
14795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.body.stats += stats
14805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
14815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _handle_fused_def_decorators(self, old_decorators, env, node):
14835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
14845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Create function calls to the decorators and reassignments to
14855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        the function.
14865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
14875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Delete staticmethod and classmethod decorators, this is
14885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # handled directly by the fused function object.
14895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        decorators = []
14905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for decorator in old_decorators:
14915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            func = decorator.decorator
14925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (not func.is_name or
14935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                func.name not in ('staticmethod', 'classmethod') or
14945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                env.lookup_here(func.name)):
14955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # not a static or classmethod
14965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                decorators.append(decorator)
14975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if decorators:
14995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            transform = DecoratorTransform(self.context)
15005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            def_node = node.node
15015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            _, reassignments = transform.handle_decorators(
15025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                def_node, decorators, def_node.name)
15035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            reassignments.analyse_declarations(env)
15045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = [node, reassignments]
15055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
15075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _handle_def(self, decorators, env, node):
15095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        "Handle def or cpdef fused functions"
15105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Create PyCFunction nodes for each specialization
15115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.stats.insert(0, node.py_func)
15125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.py_func = self.visit(node.py_func)
15135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.update_fused_defnode_entry(env)
15145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pycfunc = ExprNodes.PyCFunctionNode.from_defnode(node.py_func,
15155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                         True)
15165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pycfunc = ExprNodes.ProxyNode(pycfunc.coerce_to_temp(env))
15175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.resulting_fused_function = pycfunc
15185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Create assignment node for our def function
15195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.fused_func_assignment = self._create_assignment(
15205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.py_func, ExprNodes.CloneNode(pycfunc), env)
15215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if decorators:
15235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = self._handle_fused_def_decorators(decorators, env, node)
15245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
15265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _create_fused_function(self, env, node):
15285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        "Create a fused function for a DefNode with fused arguments"
15295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        from Cython.Compiler import FusedNode
15305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.fused_function or self.in_lambda:
15325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.fused_function not in self.fused_error_funcs:
15335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if self.in_lambda:
15345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(node.pos, "Fused lambdas not allowed")
15355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
15365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(node.pos, "Cannot nest fused functions")
15375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.fused_error_funcs.add(self.fused_function)
15395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.body = Nodes.PassStatNode(node.pos)
15415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for arg in node.args:
15425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if arg.type.is_fused:
15435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg.type = arg.type.get_fused_types()[0]
15445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
15465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        decorators = getattr(node, 'decorators', None)
15485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node = FusedNode.FusedCFuncDefNode(node, env)
15495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.fused_function = node
15505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
15515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.fused_function = None
15525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.py_func:
15535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = self._handle_def(decorators, env, node)
15545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
15565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _handle_nogil_cleanup(self, lenv, node):
15585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        "Handle cleanup for 'with gil' blocks in nogil functions."
15595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if lenv.nogil and lenv.has_with_gil_block:
15605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Acquire the GIL for cleanup in 'nogil' functions, by wrapping
15615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # the entire function body in try/finally.
15625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # The corresponding release will be taken care of by
15635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Nodes.FuncDefNode.generate_function_definitions()
15645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.body = Nodes.NogilTryFinallyStatNode(
15655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.body.pos,
15665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                body=node.body,
15675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                finally_clause=Nodes.EnsureGILNode(node.body.pos))
15685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _handle_fused(self, node):
15705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.is_generator and node.has_fused_arguments:
15715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.has_fused_arguments = False
15725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(node.pos, "Fused generators not supported")
15735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.gbody = Nodes.StatListNode(node.pos,
15745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            stats=[],
15755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            body=Nodes.PassStatNode(node.pos))
15765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node.has_fused_arguments
15785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_FuncDefNode(self, node):
15805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
15815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Analyse a function and its body, as that hasn't happend yet. Also
15825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        analyse the directive_locals set by @cython.locals(). Then, if we are
15835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        a function with fused arguments, replace the function (after it has
15845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        declared itself in the symbol table!) with a FusedCFuncDefNode, and
15855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        analyse its children (which are in turn normal functions). If we're a
15865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        normal function, just analyse the body of the function.
15875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
15885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env = self.current_env()
15895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.seen_vars_stack.append(set())
15915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lenv = node.local_scope
15925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.declare_arguments(lenv)
15935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for var, type_node in node.directive_locals.items():
15955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not lenv.lookup_here(var):   # don't redeclare args
15965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                type = type_node.analyse_as_type(lenv)
15975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if type:
15985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    lenv.declare_var(var, type, type_node.pos)
15995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
16005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(type_node.pos, "Not a type")
16015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self._handle_fused(node):
16035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = self._create_fused_function(env, node)
16045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
16055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.body.analyse_declarations(lenv)
16065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self._handle_nogil_cleanup(lenv, node)
16075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self._super_visit_FuncDefNode(node)
16085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.seen_vars_stack.pop()
16105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
16115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_DefNode(self, node):
16135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node = self.visit_FuncDefNode(node)
16145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env = self.current_env()
16155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (not isinstance(node, Nodes.DefNode) or
16165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.fused_py_func or node.is_generator_body or
16175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            not node.needs_assignment_synthesis(env)):
16185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
16195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return [node, self._synthesize_assignment(node, env)]
16205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_GeneratorBodyDefNode(self, node):
16225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.visit_FuncDefNode(node)
16235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _synthesize_assignment(self, node, env):
16255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Synthesize assignment node and put it right after defnode
16265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        genv = env
16275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        while genv.is_py_class_scope or genv.is_c_class_scope:
16285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            genv = genv.outer_scope
16295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if genv.is_closure_scope:
16315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs = node.py_cfunc_node = ExprNodes.InnerFunctionNode(
16325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.pos, def_node=node,
16335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pymethdef_cname=node.entry.pymethdef_cname,
16345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                code_object=ExprNodes.CodeObjectNode(node))
16355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
16365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            binding = self.current_directives.get('binding')
16375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs = ExprNodes.PyCFunctionNode.from_defnode(node, binding)
16385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if env.is_py_class_scope:
16405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs.binding = True
16415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.is_cyfunction = rhs.binding
16435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self._create_assignment(node, rhs, env)
16445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _create_assignment(self, def_node, rhs, env):
16465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if def_node.decorators:
16475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for decorator in def_node.decorators[::-1]:
16485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                rhs = ExprNodes.SimpleCallNode(
16495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    decorator.pos,
16505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    function = decorator.decorator,
16515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    args = [rhs])
16525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            def_node.decorators = None
16535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        assmt = Nodes.SingleAssignmentNode(
16555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            def_node.pos,
16565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lhs=ExprNodes.NameNode(def_node.pos, name=def_node.name),
16575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs=rhs)
16585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        assmt.analyse_declarations(env)
16595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return assmt
16605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ScopedExprNode(self, node):
16625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env = self.current_env()
16635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.analyse_declarations(env)
16645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # the node may or may not have a local scope
16655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.has_local_scope:
16665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.seen_vars_stack.append(set(self.seen_vars_stack[-1]))
16675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.enter_scope(node, node.expr_scope)
16685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.analyse_scoped_declarations(node.expr_scope)
16695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.visitchildren(node)
16705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.exit_scope()
16715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.seen_vars_stack.pop()
16725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
16735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.analyse_scoped_declarations(env)
16745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.visitchildren(node)
16755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
16765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_TempResultFromStatNode(self, node):
16785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
16795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.analyse_declarations(self.current_env())
16805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
16815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CppClassNode(self, node):
16835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.visibility == 'extern':
16845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
16855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
16865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.visit_ClassDefNode(node)
16875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CStructOrUnionDefNode(self, node):
16895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Create a wrapper node if needed.
16905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # We want to use the struct type information (so it can't happen
16915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # before this phase) but also create new objects to be declared
16925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # (so it can't happen later).
16935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Note that we don't return the original node, as it is
16945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # never used after this phase.
16955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if True: # private (default)
16965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
16975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self_value = ExprNodes.AttributeNode(
16995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pos = node.pos,
17005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            obj = ExprNodes.NameNode(pos=node.pos, name=u"self"),
17015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            attribute = EncodedString(u"value"))
17025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        var_entries = node.entry.type.scope.var_entries
17035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        attributes = []
17045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry in var_entries:
17055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            attributes.append(ExprNodes.AttributeNode(pos = entry.pos,
17065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                      obj = self_value,
17075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                      attribute = entry.name))
17085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # __init__ assignments
17095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        init_assignments = []
17105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry, attr in zip(var_entries, attributes):
17115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # TODO: branch on visibility
17125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            init_assignments.append(self.init_assignment.substitute({
17135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    u"VALUE": ExprNodes.NameNode(entry.pos, name = entry.name),
17145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    u"ATTR": attr,
17155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                }, pos = entry.pos))
17165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # create the class
17185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        str_format = u"%s(%s)" % (node.entry.type.name, ("%s, " * len(attributes))[:-2])
17195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        wrapper_class = self.struct_or_union_wrapper.substitute({
17205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            u"INIT_ASSIGNMENTS": Nodes.StatListNode(node.pos, stats = init_assignments),
17215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            u"IS_UNION": ExprNodes.BoolNode(node.pos, value = not node.entry.type.is_struct),
17225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            u"MEMBER_TUPLE": ExprNodes.TupleNode(node.pos, args=attributes),
17235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            u"STR_FORMAT": ExprNodes.StringNode(node.pos, value = EncodedString(str_format)),
17245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            u"REPR_FORMAT": ExprNodes.StringNode(node.pos, value = EncodedString(str_format.replace("%s", "%r"))),
17255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        }, pos = node.pos).stats[0]
17265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        wrapper_class.class_name = node.name
17275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        wrapper_class.shadow = True
17285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        class_body = wrapper_class.body.stats
17295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # fix value type
17315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        assert isinstance(class_body[0].base_type, Nodes.CSimpleBaseTypeNode)
17325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        class_body[0].base_type.name = node.name
17335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # fix __init__ arguments
17355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        init_method = class_body[1]
17365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        assert isinstance(init_method, Nodes.DefNode) and init_method.name == '__init__'
17375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        arg_template = init_method.args[1]
17385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not node.entry.type.is_struct:
17395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg_template.kw_only = True
17405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        del init_method.args[1]
17415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry, attr in zip(var_entries, attributes):
17425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg = copy.deepcopy(arg_template)
17435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            arg.declarator.name = entry.name
17445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            init_method.args.append(arg)
17455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # setters/getters
17475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry, attr in zip(var_entries, attributes):
17485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # TODO: branch on visibility
17495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.type.is_pyobject:
17505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                template = self.basic_pyobject_property
17515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
17525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                template = self.basic_property
17535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            property = template.substitute({
17545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    u"ATTR": attr,
17555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                }, pos = entry.pos).stats[0]
17565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            property.name = entry.name
17575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            wrapper_class.body.stats.append(property)
17585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        wrapper_class.analyse_declarations(self.current_env())
17605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.visit_CClassDefNode(wrapper_class)
17615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Some nodes are no longer needed after declaration
17635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # analysis and can be dropped. The analysis was performed
17645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # on these nodes in a seperate recursive process from the
17655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # enclosing function or module, so we can simply drop them.
17665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CDeclaratorNode(self, node):
17675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # necessary to ensure that all CNameDeclaratorNodes are visited.
17685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
17695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
17705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CTypeDefNode(self, node):
17725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
17735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CBaseTypeNode(self, node):
17755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return None
17765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CEnumDefNode(self, node):
17785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.visibility == 'public':
17795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
17805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
17815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
17825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CNameDeclaratorNode(self, node):
17845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.name in self.seen_vars_stack[-1]:
17855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            entry = self.current_env().lookup(node.name)
17865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (entry is None or entry.visibility != 'extern'
17875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                and not entry.scope.is_c_class_scope):
17885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                warning(node.pos, "cdef variable '%s' declared after it is used" % node.name, 2)
17895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
17905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
17915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CVarDefNode(self, node):
17935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # to ensure all CNameDeclaratorNodes are visited.
17945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
17955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return None
17965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
17975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CnameDecoratorNode(self, node):
17985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        child_node = self.visit(node.node)
17995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not child_node:
18005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
18015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if type(child_node) is list: # Assignment synthesized
18025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.child_node = child_node[0]
18035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return [node] + child_node[1:]
18045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.node = child_node
18055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
18065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def create_Property(self, entry):
18085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if entry.visibility == 'public':
18095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.type.is_pyobject:
18105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                template = self.basic_pyobject_property
18115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
18125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                template = self.basic_property
18135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif entry.visibility == 'readonly':
18145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            template = self.basic_property_ro
18155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        property = template.substitute({
18165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                u"ATTR": ExprNodes.AttributeNode(pos=entry.pos,
18175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                 obj=ExprNodes.NameNode(pos=entry.pos, name="self"),
18185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                 attribute=entry.name),
18195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            }, pos=entry.pos).stats[0]
18205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        property.name = entry.name
18215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        property.doc = entry.doc
18225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return property
18235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CalculateQualifiedNamesTransform(EnvTransform):
18265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
18275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Calculate and store the '__qualname__' and the global
18285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    module name on some nodes.
18295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
18305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ModuleNode(self, node):
18315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.module_name = self.global_scope().qualified_name
18325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.qualified_name = []
18335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        _super = super(CalculateQualifiedNamesTransform, self)
18345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self._super_visit_FuncDefNode = _super.visit_FuncDefNode
18355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self._super_visit_ClassDefNode = _super.visit_ClassDefNode
18365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
18375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
18385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _set_qualname(self, node, name=None):
18405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if name:
18415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            qualname = self.qualified_name[:]
18425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            qualname.append(name)
18435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
18445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            qualname = self.qualified_name
18455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.qualname = EncodedString('.'.join(qualname))
18465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.module_name = self.module_name
18475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
18485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
18495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _append_entry(self, entry):
18515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if entry.is_pyglobal and not entry.is_pyclass_attr:
18525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.qualified_name = [entry.name]
18535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
18545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.qualified_name.append(entry.name)
18555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ClassNode(self, node):
18575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self._set_qualname(node, node.name)
18585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_PyClassNamespaceNode(self, node):
18605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # class name was already added by parent node
18615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self._set_qualname(node)
18625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_PyCFunctionNode(self, node):
18645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self._set_qualname(node, node.def_node.name)
18655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_FuncDefNode(self, node):
18675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        orig_qualified_name = self.qualified_name[:]
18685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if getattr(node, 'name', None) == '<lambda>':
18695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.qualified_name.append('<lambda>')
18705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
18715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self._append_entry(node.entry)
18725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.qualified_name.append('<locals>')
18735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self._super_visit_FuncDefNode(node)
18745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.qualified_name = orig_qualified_name
18755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
18765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ClassDefNode(self, node):
18785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        orig_qualified_name = self.qualified_name[:]
18795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry = (getattr(node, 'entry', None) or             # PyClass
18805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 self.current_env().lookup_here(node.name))  # CClass
18815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self._append_entry(entry)
18825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self._super_visit_ClassDefNode(node)
18835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.qualified_name = orig_qualified_name
18845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
18855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class AnalyseExpressionsTransform(CythonTransform):
18885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ModuleNode(self, node):
18905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.scope.infer_types()
18915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.body = node.body.analyse_expressions(node.scope)
18925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
18935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
18945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_FuncDefNode(self, node):
18965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.local_scope.infer_types()
18975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.body = node.body.analyse_expressions(node.local_scope)
18985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
18995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
19005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ScopedExprNode(self, node):
19025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.has_local_scope:
19035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.expr_scope.infer_types()
19045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = node.analyse_scoped_expressions(node.expr_scope)
19055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
19065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
19075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_IndexNode(self, node):
19095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
19105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Replace index nodes used to specialize cdef functions with fused
19115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        argument types with the Attribute- or NameNode referring to the
19125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        function. We then need to copy over the specialization properties to
19135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        the attribute or name node.
19145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Because the indexing might be a Python indexing operation on a fused
19165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        function, or (usually) a Cython indexing operation, we need to
19175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        re-analyse the types.
19185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
19195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visit_Node(node)
19205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.is_fused_index and not node.type.is_error:
19225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = node.base
19235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif node.memslice_ellipsis_noop:
19245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # memoryviewslice[...] expression, drop the IndexNode
19255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = node.base
19265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
19285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class FindInvalidUseOfFusedTypes(CythonTransform):
19315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_FuncDefNode(self, node):
19335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Errors related to use in functions with fused args will already
19345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # have been detected
19355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not node.has_fused_arguments:
19365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not node.is_generator_body and node.return_type.is_fused:
19375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.pos, "Return type is not specified as argument type")
19385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
19395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.visitchildren(node)
19405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
19425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ExprNode(self, node):
19445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.type and node.type.is_fused:
19455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(node.pos, "Invalid use of fused types, type cannot be specialized")
19465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
19475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.visitchildren(node)
19485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
19505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ExpandInplaceOperators(EnvTransform):
19535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_InPlaceAssignmentNode(self, node):
19555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lhs = node.lhs
19565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        rhs = node.rhs
19575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if lhs.type.is_cpp_class:
19585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # No getting around this exact operator here.
19595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
19605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(lhs, ExprNodes.IndexNode) and lhs.is_buffer_access:
19615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # There is code to handle this case.
19625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
19635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env = self.current_env()
19655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        def side_effect_free_reference(node, setting=False):
19665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if isinstance(node, ExprNodes.NameNode):
19675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return node, []
19685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif node.type.is_pyobject and not setting:
19695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node = LetRefNode(node)
19705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return node, [node]
19715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif isinstance(node, ExprNodes.IndexNode):
19725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if node.is_buffer_access:
19735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    raise ValueError("Buffer access")
19745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                base, temps = side_effect_free_reference(node.base)
19755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                index = LetRefNode(node.index)
19765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return ExprNodes.IndexNode(node.pos, base=base, index=index), temps + [index]
19775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif isinstance(node, ExprNodes.AttributeNode):
19785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                obj, temps = side_effect_free_reference(node.obj)
19795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return ExprNodes.AttributeNode(node.pos, obj=obj, attribute=node.attribute), temps
19805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
19815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node = LetRefNode(node)
19825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return node, [node]
19835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        try:
19845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lhs, let_ref_nodes = side_effect_free_reference(lhs, setting=True)
19855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        except ValueError:
19865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
19875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        dup = lhs.__class__(**lhs.__dict__)
19885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        binop = ExprNodes.binop_node(node.pos,
19895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     operator = node.operator,
19905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     operand1 = dup,
19915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     operand2 = rhs,
19925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     inplace=True)
19935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Manually analyse types for new node.
19945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lhs.analyse_target_types(env)
19955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        dup.analyse_types(env)
19965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        binop.analyse_operation(env)
19975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node = Nodes.SingleAssignmentNode(
19985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.pos,
19995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lhs = lhs,
20005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            rhs=binop.coerce_to(lhs.type, env))
20015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Use LetRefNode to avoid side effects.
20025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        let_ref_nodes.reverse()
20035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for t in let_ref_nodes:
20045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = LetNode(t, node)
20055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
20065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ExprNode(self, node):
20085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # In-place assignments can't happen within an expression.
20095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
20105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class AdjustDefByDirectives(CythonTransform, SkipDeclarations):
20125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
20135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Adjust function and class definitions by the decorator directives:
20145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    @cython.cfunc
20165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    @cython.cclass
20175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    @cython.ccall
20185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
20195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ModuleNode(self, node):
20215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.directives = node.directives
20225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.in_py_class = False
20235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
20245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
20255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CompilerDirectivesNode(self, node):
20275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_directives = self.directives
20285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.directives = node.directives
20295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
20305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.directives = old_directives
20315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
20325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_DefNode(self, node):
20345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if 'ccall' in self.directives:
20355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = node.as_cfunction(overridable=True, returns=self.directives.get('returns'))
20365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.visit(node)
20375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if 'cfunc' in self.directives:
20385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.in_py_class:
20395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.pos, "cfunc directive is not allowed here")
20405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
20415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node = node.as_cfunction(overridable=False, returns=self.directives.get('returns'))
20425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return self.visit(node)
20435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
20445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
20455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_PyClassDefNode(self, node):
20475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if 'cclass' in self.directives:
20485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = node.as_cclass()
20495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.visit(node)
20505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
20515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            old_in_pyclass = self.in_py_class
20525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.in_py_class = True
20535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.visitchildren(node)
20545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.in_py_class = old_in_pyclass
20555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
20565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CClassDefNode(self, node):
20585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        old_in_pyclass = self.in_py_class
20595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.in_py_class = False
20605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
20615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.in_py_class = old_in_pyclass
20625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
20635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class AlignFunctionDefinitions(CythonTransform):
20665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
20675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    This class takes the signatures from a .pxd file and applies them to
20685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    the def methods in a .py file.
20695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
20705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ModuleNode(self, node):
20725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.scope = node.scope
20735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.directives = node.directives
20745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.imported_names = set()  # hack, see visit_FromImportStatNode()
20755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
20765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
20775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_PyClassDefNode(self, node):
20795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pxd_def = self.scope.lookup(node.name)
20805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if pxd_def:
20815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if pxd_def.is_cclass:
20825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return self.visit_CClassDefNode(node.as_cclass(), pxd_def)
20835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif not pxd_def.scope or not pxd_def.scope.is_builtin_scope:
20845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.pos, "'%s' redeclared" % node.name)
20855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if pxd_def.pos:
20865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(pxd_def.pos, "previous declaration here")
20875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return None
20885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
20895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CClassDefNode(self, node, pxd_def=None):
20915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if pxd_def is None:
20925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pxd_def = self.scope.lookup(node.class_name)
20935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if pxd_def:
20945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            outer_scope = self.scope
20955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.scope = pxd_def.type.scope
20965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
20975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if pxd_def:
20985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.scope = outer_scope
20995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
21005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_DefNode(self, node):
21025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pxd_def = self.scope.lookup(node.name)
21035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if pxd_def and (not pxd_def.scope or not pxd_def.scope.is_builtin_scope):
21045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not pxd_def.is_cfunction:
21055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.pos, "'%s' redeclared" % node.name)
21065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if pxd_def.pos:
21075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(pxd_def.pos, "previous declaration here")
21085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return None
21095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = node.as_cfunction(pxd_def)
21105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif (self.scope.is_module_scope and self.directives['auto_cpdef']
21115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              and not node.name in self.imported_names
21125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              and node.is_cdef_func_compatible()):
21135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # FIXME: cpdef-ing should be done in analyse_declarations()
21145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = node.as_cfunction(scope=self.scope)
21155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Enable this when nested cdef functions are allowed.
21165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # self.visitchildren(node)
21175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
21185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_FromImportStatNode(self, node):
21205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # hack to prevent conditional import fallback functions from
21215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # being cdpef-ed (global Python variables currently conflict
21225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # with imports)
21235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.scope.is_module_scope:
21245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for name, _ in node.items:
21255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                self.imported_names.add(name)
21265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
21275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ExprNode(self, node):
21295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ignore lambdas and everything else that appears in expressions
21305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
21315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class RemoveUnreachableCode(CythonTransform):
21345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_StatListNode(self, node):
21355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.current_directives['remove_unreachable']:
21365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
21375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
21385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for idx, stat in enumerate(node.stats):
21395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            idx += 1
21405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if stat.is_terminator:
21415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if idx < len(node.stats):
21425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if self.current_directives['warn.unreachable']:
21435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        warning(node.stats[idx].pos, "Unreachable code", 2)
21445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node.stats = node.stats[:idx]
21455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.is_terminator = True
21465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                break
21475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
21485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_IfClauseNode(self, node):
21505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
21515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.body.is_terminator:
21525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.is_terminator = True
21535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
21545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_IfStatNode(self, node):
21565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
21575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.else_clause and node.else_clause.is_terminator:
21585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for clause in node.if_clauses:
21595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not clause.is_terminator:
21605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    break
21615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
21625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.is_terminator = True
21635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
21645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_TryExceptStatNode(self, node):
21665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
21675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.body.is_terminator and node.else_clause:
21685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if self.current_directives['warn.unreachable']:
21695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                warning(node.else_clause.pos, "Unreachable code", 2)
21705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.else_clause = None
21715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
21725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class YieldNodeCollector(TreeVisitor):
21755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self):
21775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(YieldNodeCollector, self).__init__()
21785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.yields = []
21795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.returns = []
21805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.has_return_value = False
21815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_Node(self, node):
21835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
21845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_YieldExprNode(self, node):
21865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.yields.append(node)
21875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
21885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ReturnStatNode(self, node):
21905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
21915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.value:
21925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.has_return_value = True
21935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.returns.append(node)
21945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ClassDefNode(self, node):
21965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
21975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_FuncDefNode(self, node):
21995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
22005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_LambdaNode(self, node):
22025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
22035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_GeneratorExpressionNode(self, node):
22055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pass
22065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class MarkClosureVisitor(CythonTransform):
22095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ModuleNode(self, node):
22115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.needs_closure = False
22125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
22135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
22145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_FuncDefNode(self, node):
22165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.needs_closure = False
22175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
22185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.needs_closure = self.needs_closure
22195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.needs_closure = True
22205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        collector = YieldNodeCollector()
22225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        collector.visitchildren(node)
22235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if collector.yields:
22255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if isinstance(node, Nodes.CFuncDefNode):
22265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # Will report error later
22275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return node
22285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for i, yield_expr in enumerate(collector.yields):
22295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                yield_expr.label_num = i + 1  # no enumerate start arg in Py2.4
22305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for retnode in collector.returns:
22315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                retnode.in_generator = True
22325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            gbody = Nodes.GeneratorBodyDefNode(
22345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pos=node.pos, name=node.name, body=node.body)
22355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            generator = Nodes.GeneratorDefNode(
22365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pos=node.pos, name=node.name, args=node.args,
22375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                star_arg=node.star_arg, starstar_arg=node.starstar_arg,
22385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                doc=node.doc, decorators=node.decorators,
22395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                gbody=gbody, lambda_name=node.lambda_name)
22405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return generator
22415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
22425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CFuncDefNode(self, node):
22445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visit_FuncDefNode(node)
22455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.needs_closure:
22465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(node.pos, "closures inside cdef functions not yet supported")
22475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
22485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_LambdaNode(self, node):
22505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.needs_closure = False
22515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
22525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.needs_closure = self.needs_closure
22535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.needs_closure = True
22545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
22555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ClassDefNode(self, node):
22575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
22585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.needs_closure = True
22595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
22605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CreateClosureClasses(CythonTransform):
22625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Output closure classes in module scope for all functions
22635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # that really need it.
22645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, context):
22665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(CreateClosureClasses, self).__init__(context)
22675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.path = []
22685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.in_lambda = False
22695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ModuleNode(self, node):
22715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.module_scope = node.scope
22725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
22735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
22745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def find_entries_used_in_closures(self, node):
22765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        from_closure = []
22775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        in_closure = []
22785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for name, entry in node.local_scope.entries.items():
22795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.from_closure:
22805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                from_closure.append((name, entry))
22815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif entry.in_closure:
22825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                in_closure.append((name, entry))
22835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return from_closure, in_closure
22845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def create_class_from_scope(self, node, target_module_scope, inner_node=None):
22865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # move local variables into closure
22875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.is_generator:
22885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            for entry in node.local_scope.entries.values():
22895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not entry.from_closure:
22905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    entry.in_closure = True
22915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        from_closure, in_closure = self.find_entries_used_in_closures(node)
22935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        in_closure.sort()
22945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Now from the begining
22965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.needs_closure = False
22975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.needs_outer_scope = False
22985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        func_scope = node.local_scope
23005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cscope = node.entry.scope
23015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        while cscope.is_py_class_scope or cscope.is_c_class_scope:
23025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cscope = cscope.outer_scope
23035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not from_closure and (self.path or inner_node):
23055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not inner_node:
23065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if not node.py_cfunc_node:
23075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    raise InternalError("DefNode does not have assignment node")
23085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                inner_node = node.py_cfunc_node
23095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            inner_node.needs_self_code = False
23105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.needs_outer_scope = False
23115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.is_generator:
23135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pass
23145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif not in_closure and not from_closure:
23155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
23165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif not in_closure:
23175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            func_scope.is_passthrough = True
23185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            func_scope.scope_class = cscope.scope_class
23195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.needs_outer_scope = True
23205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return
23215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        as_name = '%s_%s' % (
23235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            target_module_scope.next_id(Naming.closure_class_prefix),
23245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.entry.cname)
23255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry = target_module_scope.declare_c_class(
23275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            name=as_name, pos=node.pos, defining=True,
23285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            implementing=True)
23295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry.type.is_final_type = True
23305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        func_scope.scope_class = entry
23325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        class_scope = entry.type.scope
23335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        class_scope.is_internal = True
23345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if Options.closure_freelist_size:
23355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            class_scope.directives['freelist'] = Options.closure_freelist_size
23365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if from_closure:
23385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            assert cscope.is_closure_scope
23395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            class_scope.declare_var(pos=node.pos,
23405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    name=Naming.outer_scope_cname,
23415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    cname=Naming.outer_scope_cname,
23425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    type=cscope.scope_class.type,
23435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    is_cdef=True)
23445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.needs_outer_scope = True
23455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for name, entry in in_closure:
23465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            closure_entry = class_scope.declare_var(pos=entry.pos,
23475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    name=entry.name,
23485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    cname=entry.cname,
23495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    type=entry.type,
23505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    is_cdef=True)
23515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.is_declared_generic:
23525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                closure_entry.is_declared_generic = 1
23535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.needs_closure = True
23545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Do it here because other classes are already checked
23555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        target_module_scope.check_c_class(func_scope.scope_class)
23565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_LambdaNode(self, node):
23585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not isinstance(node.def_node, Nodes.DefNode):
23595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # fused function, an error has been previously issued
23605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
23615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        was_in_lambda = self.in_lambda
23635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.in_lambda = True
23645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.create_class_from_scope(node.def_node, self.module_scope, node)
23655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
23665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.in_lambda = was_in_lambda
23675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
23685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_FuncDefNode(self, node):
23705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.in_lambda:
23715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.visitchildren(node)
23725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
23735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.needs_closure or self.path:
23745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.create_class_from_scope(node, self.module_scope)
23755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.path.append(node)
23765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.visitchildren(node)
23775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.path.pop()
23785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
23795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_GeneratorBodyDefNode(self, node):
23815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
23825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
23835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CFuncDefNode(self, node):
23855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
23865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
23875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class GilCheck(VisitorTransform):
23905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
23915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Call `node.gil_check(env)` on each node to make sure we hold the
23925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    GIL when we need it.  Raise an error when on Python operations
23935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    inside a `nogil` environment.
23945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Additionally, raise exceptions for closely nested with gil or with nogil
23965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    statements. The latter would abort Python.
23975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
23985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __call__(self, root):
24005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.env_stack = [root.scope]
24015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.nogil = False
24025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # True for 'cdef func() nogil:' functions, as the GIL may be held while
24045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # calling this function (thus contained 'nogil' blocks may be valid).
24055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.nogil_declarator_only = False
24065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return super(GilCheck, self).__call__(root)
24075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_FuncDefNode(self, node):
24095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.env_stack.append(node.local_scope)
24105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        was_nogil = self.nogil
24115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.nogil = node.local_scope.nogil
24125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.nogil:
24145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.nogil_declarator_only = True
24155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.nogil and node.nogil_check:
24175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.nogil_check(node.local_scope)
24185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
24205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # This cannot be nested, so it doesn't need backup/restore
24225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.nogil_declarator_only = False
24235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.env_stack.pop()
24255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.nogil = was_nogil
24265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
24275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_GILStatNode(self, node):
24295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.nogil and node.nogil_check:
24305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.nogil_check()
24315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        was_nogil = self.nogil
24335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.nogil = (node.state == 'nogil')
24345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if was_nogil == self.nogil and not self.nogil_declarator_only:
24365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not was_nogil:
24375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.pos, "Trying to acquire the GIL while it is "
24385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                "already held.")
24395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
24405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.pos, "Trying to release the GIL while it was "
24415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                "previously released.")
24425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(node.finally_clause, Nodes.StatListNode):
24445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # The finally clause of the GILStatNode is a GILExitNode,
24455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # which is wrapped in a StatListNode. Just unpack that.
24465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.finally_clause, = node.finally_clause.stats
24475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
24495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.nogil = was_nogil
24505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
24515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ParallelRangeNode(self, node):
24535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.nogil:
24545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.nogil = False
24555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node = Nodes.GILStatNode(node.pos, state='nogil', body=node)
24565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.visit_GILStatNode(node)
24575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.nogil:
24595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(node.pos, "prange() can only be used without the GIL")
24605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Forget about any GIL-related errors that may occur in the body
24615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
24625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.nogil_check(self.env_stack[-1])
24645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
24655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
24665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ParallelWithBlockNode(self, node):
24685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.nogil:
24695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(node.pos, "The parallel section may only be used without "
24705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            "the GIL")
24715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
24725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.nogil_check:
24745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # It does not currently implement this, but test for it anyway to
24755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # avoid potential future surprises
24765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.nogil_check(self.env_stack[-1])
24775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
24795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
24805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_TryFinallyStatNode(self, node):
24825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
24835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Take care of try/finally statements in nogil code sections.
24845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
24855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not self.nogil or isinstance(node, Nodes.GILStatNode):
24865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return self.visit_Node(node)
24875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.nogil_check = None
24895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.is_try_finally_in_nogil = True
24905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
24915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
24925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
24935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_Node(self, node):
24945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.env_stack and self.nogil and node.nogil_check:
24955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.nogil_check(self.env_stack[-1])
24965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
24975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.in_nogil_context = self.nogil
24985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
24995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class TransformBuiltinMethods(EnvTransform):
25025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_SingleAssignmentNode(self, node):
25045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.declaration_only:
25055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return None
25065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
25075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.visitchildren(node)
25085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
25095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_AttributeNode(self, node):
25115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
25125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.visit_cython_attribute(node)
25135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_NameNode(self, node):
25155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.visit_cython_attribute(node)
25165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_cython_attribute(self, node):
25185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        attribute = node.as_cython_attribute()
25195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if attribute:
25205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if attribute == u'compiled':
25215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node = ExprNodes.BoolNode(node.pos, value=True)
25225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif attribute == u'__version__':
25235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                import Cython
25245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node = ExprNodes.StringNode(node.pos, value=EncodedString(Cython.__version__))
25255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif attribute == u'NULL':
25265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node = ExprNodes.NullNode(node.pos)
25275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif attribute in (u'set', u'frozenset'):
25285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node = ExprNodes.NameNode(node.pos, name=EncodedString(attribute),
25295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          entry=self.current_env().builtin_scope().lookup_here(attribute))
25305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif PyrexTypes.parse_basic_type(attribute):
25315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pass
25325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif self.context.cython_scope.lookup_qualified_name(attribute):
25335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pass
25345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
25355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.pos, u"'%s' not a valid cython attribute or is being used incorrectly" % attribute)
25365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
25375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ExecStatNode(self, node):
25395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lenv = self.current_env()
25405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
25415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if len(node.args) == 1:
25425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.args.append(ExprNodes.GlobalsExprNode(node.pos))
25435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not lenv.is_module_scope:
25445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.args.append(
25455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    ExprNodes.LocalsExprNode(
25465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        node.pos, self.current_scope_node(), lenv))
25475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
25485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _inject_locals(self, node, func_name):
25505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # locals()/dir()/vars() builtins
25515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lenv = self.current_env()
25525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry = lenv.lookup_here(func_name)
25535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if entry:
25545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # not the builtin
25555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
25565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pos = node.pos
25575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if func_name in ('locals', 'vars'):
25585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if func_name == 'locals' and len(node.args) > 0:
25595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "Builtin 'locals()' called with wrong number of args, expected 0, got %d"
25605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      % len(node.args))
25615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return node
25625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif func_name == 'vars':
25635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if len(node.args) > 1:
25645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(self.pos, "Builtin 'vars()' called with wrong number of args, expected 0-1, got %d"
25655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          % len(node.args))
25665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if len(node.args) > 0:
25675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    return node # nothing to do
25685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return ExprNodes.LocalsExprNode(pos, self.current_scope_node(), lenv)
25695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else: # dir()
25705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if len(node.args) > 1:
25715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(self.pos, "Builtin 'dir()' called with wrong number of args, expected 0-1, got %d"
25725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      % len(node.args))
25735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if len(node.args) > 0:
25745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # optimised in Builtin.py
25755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return node
25765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if lenv.is_py_class_scope or lenv.is_module_scope:
25775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if lenv.is_py_class_scope:
25785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    pyclass = self.current_scope_node()
25795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    locals_dict = ExprNodes.CloneNode(pyclass.dict)
25805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
25815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    locals_dict = ExprNodes.GlobalsExprNode(pos)
25825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return ExprNodes.SortedDictKeysNode(locals_dict)
25835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            local_names = [ var.name for var in lenv.entries.values() if var.name ]
25845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            items = [ ExprNodes.IdentifierStringNode(pos, value=var)
25855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      for var in local_names ]
25865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return ExprNodes.ListNode(pos, args=items)
25875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_PrimaryCmpNode(self, node):
25895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # special case: for in/not-in test, we do not need to sort locals()
25905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
25915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.operator in 'not_in':  # in/not_in
25925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if isinstance(node.operand2, ExprNodes.SortedDictKeysNode):
25935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                arg = node.operand2.arg
25945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if isinstance(arg, ExprNodes.NoneCheckNode):
25955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    arg = arg.arg
25965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.operand2 = arg
25975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
25985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
25995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_CascadedCmpNode(self, node):
26005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.visit_PrimaryCmpNode(node)
26015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
26025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _inject_eval(self, node, func_name):
26035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lenv = self.current_env()
26045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry = lenv.lookup_here(func_name)
26055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if entry or len(node.args) != 1:
26065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
26075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Inject globals and locals
26085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        node.args.append(ExprNodes.GlobalsExprNode(node.pos))
26095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if not lenv.is_module_scope:
26105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.args.append(
26115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ExprNodes.LocalsExprNode(
26125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node.pos, self.current_scope_node(), lenv))
26135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
26145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
26155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _inject_super(self, node, func_name):
26165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lenv = self.current_env()
26175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entry = lenv.lookup_here(func_name)
26185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if entry or node.args:
26195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
26205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Inject no-args super
26215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        def_node = self.current_scope_node()
26225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (not isinstance(def_node, Nodes.DefNode) or not def_node.args or
26235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            len(self.env_stack) < 2):
26245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
26255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        class_node, class_scope = self.env_stack[-2]
26265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if class_scope.is_py_class_scope:
26275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            def_node.requires_classobj = True
26285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            class_node.class_cell.is_active = True
26295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.args = [
26305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ExprNodes.ClassCellNode(
26315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node.pos, is_generator=def_node.is_generator),
26325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ExprNodes.NameNode(node.pos, name=def_node.args[0].name)
26335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ]
26345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif class_scope.is_c_class_scope:
26355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.args = [
26365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ExprNodes.NameNode(
26375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node.pos, name=class_node.scope.name,
26385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    entry=class_node.entry),
26395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ExprNodes.NameNode(node.pos, name=def_node.args[0].name)
26405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                ]
26415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
26425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
26435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_SimpleCallNode(self, node):
26445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # cython.foo
26455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        function = node.function.as_cython_attribute()
26465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if function:
26475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if function in InterpretCompilerDirectives.unop_method_nodes:
26485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if len(node.args) != 1:
26495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(node.function.pos, u"%s() takes exactly one argument" % function)
26505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
26515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node = InterpretCompilerDirectives.unop_method_nodes[function](node.function.pos, operand=node.args[0])
26525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif function in InterpretCompilerDirectives.binop_method_nodes:
26535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if len(node.args) != 2:
26545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(node.function.pos, u"%s() takes exactly two arguments" % function)
26555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
26565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node = InterpretCompilerDirectives.binop_method_nodes[function](node.function.pos, operand1=node.args[0], operand2=node.args[1])
26575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif function == u'cast':
26585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if len(node.args) != 2:
26595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(node.function.pos, u"cast() takes exactly two arguments")
26605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
26615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    type = node.args[0].analyse_as_type(self.current_env())
26625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if type:
26635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        node = ExprNodes.TypecastNode(node.function.pos, type=type, operand=node.args[1])
26645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    else:
26655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        error(node.args[0].pos, "Not a type")
26665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif function == u'sizeof':
26675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if len(node.args) != 1:
26685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(node.function.pos, u"sizeof() takes exactly one argument")
26695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
26705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    type = node.args[0].analyse_as_type(self.current_env())
26715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if type:
26725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        node = ExprNodes.SizeofTypeNode(node.function.pos, arg_type=type)
26735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    else:
26745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        node = ExprNodes.SizeofVarNode(node.function.pos, operand=node.args[0])
26755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif function == 'cmod':
26765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if len(node.args) != 2:
26775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(node.function.pos, u"cmod() takes exactly two arguments")
26785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
26795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node = ExprNodes.binop_node(node.function.pos, '%', node.args[0], node.args[1])
26805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node.cdivision = True
26815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif function == 'cdiv':
26825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if len(node.args) != 2:
26835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(node.function.pos, u"cdiv() takes exactly two arguments")
26845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
26855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node = ExprNodes.binop_node(node.function.pos, '/', node.args[0], node.args[1])
26865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    node.cdivision = True
26875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif function == u'set':
26885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                node.function = ExprNodes.NameNode(node.pos, name=EncodedString('set'))
26895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif self.context.cython_scope.lookup_qualified_name(function):
26905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                pass
26915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
26925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                error(node.function.pos,
26935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      u"'%s' not a valid cython language construct" % function)
26945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
26955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
26965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
26975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if isinstance(node, ExprNodes.SimpleCallNode) and node.function.is_name:
26985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            func_name = node.function.name
26995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if func_name in ('dir', 'locals', 'vars'):
27005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return self._inject_locals(node, func_name)
27015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if func_name == 'eval':
27025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return self._inject_eval(node, func_name)
27035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if func_name == 'super':
27045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                return self._inject_super(node, func_name)
27055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
27065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ReplaceFusedTypeChecks(VisitorTransform):
27095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
27105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    This is not a transform in the pipeline. It is invoked on the specific
27115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    versions of a cdef function with fused argument types. It filters out any
27125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    type branches that don't match. e.g.
27135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if fused_t is mytype:
27155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            ...
27165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        elif fused_t in other_fused_type:
27175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            ...
27185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
27195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, local_scope):
27205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(ReplaceFusedTypeChecks, self).__init__()
27215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.local_scope = local_scope
27225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # defer the import until now to avoid circular import time dependencies
27235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        from Cython.Compiler import Optimize
27245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.transform = Optimize.ConstantFolding(reevaluate=True)
27255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_IfStatNode(self, node):
27275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
27285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Filters out any if clauses with false compile time type check
27295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        expression.
27305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
27315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
27325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return self.transform(node)
27335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_PrimaryCmpNode(self, node):
27355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        type1 = node.operand1.analyse_as_type(self.local_scope)
27365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        type2 = node.operand2.analyse_as_type(self.local_scope)
27375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if type1 and type2:
27395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            false_node = ExprNodes.BoolNode(node.pos, value=False)
27405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            true_node = ExprNodes.BoolNode(node.pos, value=True)
27415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            type1 = self.specialize_type(type1, node.operand1.pos)
27435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            op = node.operator
27445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if op in ('is', 'is_not', '==', '!='):
27465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                type2 = self.specialize_type(type2, node.operand2.pos)
27475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                is_same = type1.same_as(type2)
27495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                eq = op in ('is', '==')
27505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if (is_same and eq) or (not is_same and not eq):
27525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    return true_node
27535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif op in ('in', 'not_in'):
27555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # We have to do an instance check directly, as operand2
27565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # needs to be a fused type and not a type with a subtype
27575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # that is fused. First unpack the typedef
27585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if isinstance(type2, PyrexTypes.CTypedefType):
27595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    type2 = type2.typedef_base_type
27605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                if type1.is_fused:
27625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(node.operand1.pos, "Type is fused")
27635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                elif not type2.is_fused:
27645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    error(node.operand2.pos,
27655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          "Can only use 'in' or 'not in' on a fused type")
27665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                else:
27675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    types = PyrexTypes.get_specialized_types(type2)
27685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    for specialized_type in types:
27705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        if type1.same_as(specialized_type):
27715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            if op == 'in':
27725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                return true_node
27735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            else:
27745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                return false_node
27755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    if op == 'not_in':
27775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        return true_node
27785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return false_node
27805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
27825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def specialize_type(self, type, pos):
27845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        try:
27855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return type.specialize(self.local_scope.fused_to_specific)
27865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        except KeyError:
27875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            error(pos, "Type is not specific")
27885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return type
27895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_Node(self, node):
27915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
27925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
27935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class DebugTransform(CythonTransform):
27965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
27975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Write debug information for this Cython module.
27985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    """
27995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def __init__(self, context, options, result):
28015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        super(DebugTransform, self).__init__(context)
28025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visited = set()
28035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # our treebuilder and debug output writer
28045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # (see Cython.Debugger.debug_output.CythonDebugWriter)
28055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb = self.context.gdb_debug_outputwriter
28065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        #self.c_output_file = options.output_file
28075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.c_output_file = result.c_file
28085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Closure support, basically treat nested functions as if the AST were
28105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # never nested
28115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.nested_funcdefs = []
28125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # tells visit_NameNode whether it should register step-into functions
28145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.register_stepinto = False
28155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_ModuleNode(self, node):
28175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.module_name = node.full_module_name
28185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        attrs = dict(
28195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            module_name=node.full_module_name,
28205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            filename=node.pos[0].filename,
28215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            c_filename=self.c_output_file)
28225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.start('Module', attrs)
28245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # serialize functions
28265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.start('Functions')
28275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # First, serialize functions normally...
28285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
28295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # ... then, serialize nested functions
28315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for nested_funcdef in self.nested_funcdefs:
28325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.visit_FuncDefNode(nested_funcdef)
28335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.register_stepinto = True
28355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.serialize_modulenode_as_function(node)
28365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.register_stepinto = False
28375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.end('Functions')
28385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # 2.3 compatibility. Serialize global variables
28405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.start('Globals')
28415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        entries = {}
28425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for k, v in node.scope.entries.iteritems():
28445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (v.qualified_name not in self.visited and not
28455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                v.name.startswith('__pyx_') and not
28465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                v.type.is_cfunction and not
28475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                v.type.is_extension_type):
28485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                entries[k]= v
28495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.serialize_local_variables(entries)
28515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.end('Globals')
28525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # self.tb.end('Module') # end Module after the line number mapping in
28535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # Cython.Compiler.ModuleNode.ModuleNode._serialize_lineno_map
28545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
28555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_FuncDefNode(self, node):
28575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visited.add(node.local_scope.qualified_name)
28585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if getattr(node, 'is_wrapper', False):
28605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
28615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if self.register_stepinto:
28635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.nested_funcdefs.append(node)
28645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return node
28655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        # node.entry.visibility = 'extern'
28675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if node.py_func is None:
28685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pf_cname = ''
28695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        else:
28705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pf_cname = node.py_func.entry.func_cname
28715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        attrs = dict(
28735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            name=node.entry.name or getattr(node, 'name', '<unknown>'),
28745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cname=node.entry.func_cname,
28755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pf_cname=pf_cname,
28765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            qualified_name=node.local_scope.qualified_name,
28775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lineno=str(node.pos[1]))
28785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.start('Function', attrs=attrs)
28805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.start('Locals')
28825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.serialize_local_variables(node.local_scope.entries)
28835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.end('Locals')
28845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.start('Arguments')
28865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for arg in node.local_scope.arg_entries:
28875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.tb.start(arg.name)
28885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.tb.end(arg.name)
28895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.end('Arguments')
28905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.start('StepIntoFunctions')
28925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.register_stepinto = True
28935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
28945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.register_stepinto = False
28955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.end('StepIntoFunctions')
28965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.end('Function')
28975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
28995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def visit_NameNode(self, node):
29015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (self.register_stepinto and
29025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.type.is_cfunction and
29035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            getattr(node, 'is_called', False) and
29045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            node.entry.func_cname is not None):
29055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # don't check node.entry.in_cinclude, as 'cdef extern: ...'
29065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # declared functions are not 'in_cinclude'.
29075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # This means we will list called 'cdef' functions as
29085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # "step into functions", but this is not an issue as they will be
29095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # recognized as Cython functions anyway.
29105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            attrs = dict(name=node.entry.func_cname)
29115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.tb.start('StepIntoFunction', attrs=attrs)
29125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.tb.end('StepIntoFunction')
29135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
29155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return node
29165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def serialize_modulenode_as_function(self, node):
29185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
29195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Serialize the module-level code as a function so the debugger will know
29205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        it's a "relevant frame" and it will know where to set the breakpoint
29215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for 'break modulename'.
29225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        """
29235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        name = node.full_module_name.rpartition('.')[-1]
29245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cname_py2 = 'init' + name
29265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cname_py3 = 'PyInit_' + name
29275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        py2_attrs = dict(
29295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            name=name,
29305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cname=cname_py2,
29315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            pf_cname='',
29325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # Ignore the qualified_name, breakpoints should be set using
29335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            # `cy break modulename:lineno` for module-level breakpoints.
29345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            qualified_name='',
29355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            lineno='1',
29365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            is_initmodule_function="True",
29375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        )
29385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        py3_attrs = dict(py2_attrs, cname=cname_py3)
29405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self._serialize_modulenode_as_function(node, py2_attrs)
29425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self._serialize_modulenode_as_function(node, py3_attrs)
29435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def _serialize_modulenode_as_function(self, node, attrs):
29455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.start('Function', attrs=attrs)
29465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.start('Locals')
29485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.serialize_local_variables(node.scope.entries)
29495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.end('Locals')
29505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.start('Arguments')
29525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.end('Arguments')
29535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.start('StepIntoFunctions')
29555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.register_stepinto = True
29565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.visitchildren(node)
29575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.register_stepinto = False
29585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.end('StepIntoFunctions')
29595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        self.tb.end('Function')
29615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def serialize_local_variables(self, entries):
29635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for entry in entries.values():
29645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not entry.cname:
29655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # not a local variable
29665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                continue
29675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.type.is_pyobject:
29685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                vartype = 'PythonObject'
29695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
29705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                vartype = 'CObject'
29715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if entry.from_closure:
29735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # We're dealing with a closure where a variable from an outer
29745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # scope is accessed, get it from the scope object.
29755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                cname = '%s->%s' % (Naming.cur_scope_cname,
29765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    entry.outer_entry.cname)
29775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                qname = '%s.%s.%s' % (entry.scope.outer_scope.qualified_name,
29795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      entry.scope.name,
29805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      entry.name)
29815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            elif entry.in_closure:
29825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                cname = '%s->%s' % (Naming.cur_scope_cname,
29835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    entry.cname)
29845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                qname = entry.qualified_name
29855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
29865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                cname = entry.cname
29875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                qname = entry.qualified_name
29885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if not entry.pos:
29905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # this happens for variables that are not in the user's code,
29915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # e.g. for the global __builtins__, __doc__, etc. We can just
29925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                # set the lineno to 0 for those.
29935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                lineno = '0'
29945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            else:
29955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                lineno = str(entry.pos[1])
29965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
29975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            attrs = dict(
29985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                name=entry.name,
29995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                cname=cname,
30005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                qualified_name=qname,
30015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                type=vartype,
30025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                lineno=lineno)
30035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
30045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.tb.start('LocalVar', attrs)
30055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self.tb.end('LocalVar')
3006