def buildAsyncFunctionNode(provider, node, source_ref): # We are creating a function here that creates coroutine objects, with # many details each, pylint: disable=too-many-locals assert getKind(node) == "AsyncFunctionDef" function_statement_nodes, function_doc = extractDocFromBody(node) function_kind, flags = detectFunctionBodyKind( nodes=function_statement_nodes, start_value="Coroutine" ) creator_function_body, _, code_object = buildFunctionWithParsing( provider=provider, function_kind=function_kind, name=node.name, function_doc=function_doc, flags=(), node=node, source_ref=source_ref, ) if function_kind == "Coroutine": function_body = ExpressionCoroutineObjectBody( provider=creator_function_body, name=node.name, code_object=code_object, flags=flags, auto_release=None, source_ref=source_ref, ) else: function_body = ExpressionAsyncgenObjectBody( provider=creator_function_body, name=node.name, code_object=code_object, flags=flags, auto_release=None, source_ref=source_ref, ) function_body.qualname_provider = provider for variable in creator_function_body.getProvidedVariables(): function_body.getVariableForReference(variable.getName()) decorators = buildNodeList( provider=provider, nodes=reversed(node.decorator_list), source_ref=source_ref ) defaults = buildNodeList( provider=provider, nodes=node.args.defaults, source_ref=source_ref ) function_statements_body = buildFrameNode( provider=function_body, nodes=function_statement_nodes, code_object=code_object, source_ref=source_ref, ) function_statements_body = _insertFinalReturnStatement( function_statements_body=function_statements_body, return_statement=StatementGeneratorReturnNone(source_ref=source_ref), ) if function_statements_body.isStatementsFrame(): function_statements_body = makeStatementsSequenceFromStatement( statement=function_statements_body ) function_body.setChild("body", function_statements_body) annotations = buildParameterAnnotations(provider, node, source_ref) kw_defaults = buildParameterKwDefaults( provider=provider, node=node, function_body=creator_function_body, source_ref=source_ref, ) if function_kind == "Coroutine": creation_node = ExpressionMakeCoroutineObject( coroutine_ref=ExpressionFunctionRef( function_body=function_body, source_ref=source_ref ), source_ref=source_ref, ) else: creation_node = ExpressionMakeAsyncgenObject( asyncgen_ref=ExpressionFunctionRef( function_body=function_body, source_ref=source_ref ), source_ref=source_ref, ) creator_function_body.setChild( "body", makeStatementsSequenceFromStatement( statement=StatementReturn(expression=creation_node, source_ref=source_ref) ), ) function_creation = ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=creator_function_body, source_ref=source_ref ), defaults=defaults, kw_defaults=kw_defaults, annotations=annotations, source_ref=source_ref, ) decorated_function = function_creation for decorator in decorators: decorated_function = makeCallNode( decorator, decorated_function, decorator.getSourceReference() ) result = StatementAssignmentVariableName( provider=provider, variable_name=mangleName(node.name, provider), source=decorated_function, source_ref=source_ref, ) function_body.qualname_setup = result.getVariableName() # Share the non-local declarations. TODO: This may also apply to generators # and async generators. creator_function_body.non_local_declarations = function_body.non_local_declarations return result
def buildFunctionNode(provider, node, source_ref): # Functions have way too many details, pylint: disable=too-many-locals assert getKind(node) == "FunctionDef" function_statement_nodes, function_doc = extractDocFromBody(node) function_kind, flags = detectFunctionBodyKind(nodes=function_statement_nodes) function_body, code_body, code_object = buildFunctionWithParsing( provider=provider, function_kind=function_kind, name=node.name, function_doc=function_doc, flags=flags, node=node, source_ref=source_ref, ) if function_kind in ("Generator", "Coroutine"): if function_kind == "Coroutine": code_body = ExpressionCoroutineObjectBody( provider=function_body, name=node.name, code_object=code_object, flags=flags, auto_release=None, source_ref=source_ref, ) maker_class = ExpressionMakeCoroutineObject else: code_body = ExpressionGeneratorObjectBody( provider=function_body, name=node.name, code_object=code_object, flags=flags, auto_release=None, source_ref=source_ref, ) maker_class = ExpressionMakeGeneratorObject code_body.qualname_provider = provider for variable in function_body.getProvidedVariables(): code_body.getVariableForReference(variable.getName()) function_body.setChild( "body", makeStatementsSequenceFromStatement( statement=StatementReturn( expression=maker_class( ExpressionFunctionRef( function_body=code_body, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ) ), ) decorators = buildNodeList( provider=provider, nodes=reversed(node.decorator_list), source_ref=source_ref ) defaults = buildNodeList( provider=provider, nodes=node.args.defaults, source_ref=source_ref ) kw_defaults = buildParameterKwDefaults( provider=provider, node=node, function_body=function_body, source_ref=source_ref ) function_statements_body = buildFrameNode( provider=code_body, nodes=function_statement_nodes, code_object=code_object, source_ref=source_ref, ) if function_kind == "Function": # TODO: Generators might have to raise GeneratorExit instead. function_statements_body = _insertFinalReturnStatement( function_statements_body=function_statements_body, return_statement=StatementReturnNone(source_ref=source_ref), ) if "has_exec" in flags: function_statements_body = _insertInitialSetLocalsDictStatement( function_body=code_body, function_statements_body=function_statements_body ) if function_statements_body.isStatementsFrame(): function_statements_body = makeStatementsSequenceFromStatement( statement=function_statements_body ) code_body.setChild("body", function_statements_body) annotations = buildParameterAnnotations(provider, node, source_ref) function_creation = ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=function_body, source_ref=source_ref ), defaults=defaults, kw_defaults=kw_defaults, annotations=annotations, source_ref=source_ref, ) # Add the "staticmethod" decorator to __new__ methods if not provided. # CPython made these optional, but secretly applies them when it does # "class __new__". We add them earlier, so our optimization will see it. if ( python_version < 0x300 and node.name == "__new__" and provider.isExpressionClassBody() ): _injectDecorator( decorators, "staticmethod", ("staticmethod", "classmethod"), source_ref ) # Add the "classmethod" decorator to __init_subclass__ methods if not provided. if ( python_version >= 0x360 and node.name == "__init_subclass__" and provider.isExpressionClassBody() ): _injectDecorator(decorators, "classmethod", ("classmethod",), source_ref) if ( python_version >= 0x370 and node.name == "__class_getitem__" and provider.isExpressionClassBody() ): _injectDecorator(decorators, "classmethod", ("classmethod",), source_ref) decorated_function = function_creation for decorator in decorators: decorated_function = makeCallNode( decorator, decorated_function, decorator.getSourceReference() ) result = StatementAssignmentVariableName( provider=provider, variable_name=mangleName(node.name, provider), source=decorated_function, source_ref=source_ref, ) if python_version >= 0x340: function_body.qualname_setup = result.getVariableName() return result