def buildReturnNode(provider, node, source_ref): if provider.isExpressionClassBody() or provider.isCompiledPythonModule(): SyntaxErrors.raiseSyntaxError( "'return' outside function", source_ref.atColumnNumber(node.col_offset) ) expression = buildNode(provider, node.value, source_ref, allow_none = True) if provider.isExpressionGeneratorObjectBody(): if expression is not None and python_version < 300: SyntaxErrors.raiseSyntaxError( "'return' with argument inside generator", source_ref.atColumnNumber(node.col_offset) ) if provider.isExpressionAsyncgenObjectBody(): if expression is not None: SyntaxErrors.raiseSyntaxError( "'return' with value in async generator", source_ref.atColumnNumber(node.col_offset) ) if provider.isExpressionGeneratorObjectBody() or \ provider.isExpressionAsyncgenObjectBody(): if expression is None: expression = ExpressionConstantNoneRef( source_ref = source_ref, user_provided = True ) return StatementGeneratorReturn( expression = expression, source_ref = source_ref ) else: if expression is None: return StatementReturnNone( source_ref = source_ref ) elif expression.isExpressionConstantRef(): return makeStatementReturnConstant( constant = expression.getCompileTimeConstant(), source_ref = source_ref ) else: return StatementReturn( expression = expression, source_ref = source_ref )
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
def buildFunctionNode(provider, node, source_ref): # Functions have way too many details, pylint: disable=too-many-branches,too-many-locals assert getKind(node) == "FunctionDef" function_statement_nodes, function_doc = extractDocFromBody(node) function_kind, flags = detectFunctionBodyKind( nodes=function_statement_nodes) outer_body, function_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 == "Function": code_body = function_body elif function_kind == "Generator": code_body = ExpressionGeneratorObjectBody(provider=function_body, name=node.name, flags=flags, source_ref=source_ref) code_body.qualname_provider = provider for variable in function_body.getVariables(): code_body.getVariableForReference(variable.getName()) else: assert False, function_kind if function_kind == "Generator": function_body.setBody( makeStatementsSequenceFromStatement(statement=StatementReturn( expression=ExpressionMakeGeneratorObject( generator_ref=ExpressionFunctionRef( function_body=code_body, source_ref=source_ref), code_object=code_object, 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 function_statements_body.isStatementsFrame(): function_statements_body = makeStatementsSequenceFromStatement( statement=function_statements_body) code_body.setBody(function_statements_body) annotations = buildParameterAnnotations(provider, node, source_ref) function_creation = ExpressionFunctionCreation( function_ref=ExpressionFunctionRef(function_body=outer_body, source_ref=source_ref), code_object=code_object, 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 node.name == "__new__" and \ provider.isExpressionClassBody(): for decorator in decorators: if decorator.isExpressionVariableNameRef() and \ decorator.getVariableName() == "staticmethod": break else: decorators.append( makeExpressionBuiltinRef(builtin_name="staticmethod", source_ref=source_ref)) if python_version >= 360 and \ node.name == "__init_subclass__" and \ provider.isExpressionClassBody(): for decorator in decorators: if decorator.isExpressionVariableNameRef() and \ decorator.getVariableName() == "classmethod": break else: decorators.append( makeExpressionBuiltinRef(builtin_name="classmethod", source_ref=source_ref)) decorated_function = function_creation for decorator in decorators: decorated_function = makeCallNode(decorator, decorated_function, decorator.getSourceReference()) result = StatementAssignmentVariableName(variable_name=mangleName( node.name, provider), source=decorated_function, source_ref=source_ref) if python_version >= 340: function_body.qualname_setup = result.getVariableName() return result