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