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) 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 == "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()) 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 "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.setBody(function_statements_body) annotations = buildParameterAnnotations(provider, node, source_ref) function_creation = ExpressionFunctionCreation( function_ref=ExpressionFunctionRef(function_body=function_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() in ("staticmethod", "classmethod"): 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(provider=provider, 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
def buildLambdaNode(provider, node, source_ref): # Many details to deal with, pylint: disable=too-many-locals assert getKind(node) == "Lambda" function_kind, flags = detectFunctionBodyKind(nodes=(node.body,)) outer_body, function_body, code_object = buildFunctionWithParsing( provider=provider, function_kind=function_kind, name="<lambda>", function_doc=None, flags=flags, node=node, source_ref=source_ref, ) if function_kind == "Function": code_body = function_body else: code_body = ExpressionGeneratorObjectBody( provider=function_body, name="<lambda>", code_object=code_object, flags=set(), source_ref=source_ref, ) code_body.qualname_provider = provider if function_kind == "Generator": function_body.setBody( makeStatementsSequenceFromStatement( statement=StatementReturn( expression=ExpressionMakeGeneratorObject( generator_ref=ExpressionFunctionRef( function_body=code_body, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ) ) ) defaults = buildNodeList(provider, node.args.defaults, source_ref) kw_defaults = buildParameterKwDefaults( provider=provider, node=node, function_body=function_body, source_ref=source_ref ) body = buildNode(provider=code_body, node=node.body, source_ref=source_ref) if function_kind == "Generator": if python_version < 270: tmp_return_value = code_body.allocateTempVariable( temp_scope=None, name="yield_return" ) statements = ( StatementAssignmentVariable( variable=tmp_return_value, source=body, source_ref=source_ref ), makeStatementConditional( condition=ExpressionComparisonIsNOT( left=ExpressionTempVariableRef( variable=tmp_return_value, source_ref=source_ref ), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), yes_branch=StatementExpressionOnly( expression=ExpressionYield( expression=ExpressionTempVariableRef( variable=tmp_return_value, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ), no_branch=None, source_ref=source_ref, ), ) body = makeTryFinallyStatement( provider=provider, tried=statements, final=StatementReleaseVariable( variable=tmp_return_value, source_ref=source_ref ), source_ref=source_ref, ) else: body = StatementExpressionOnly(expression=body, source_ref=source_ref) else: body = StatementReturn(expression=body, source_ref=source_ref) if function_kind == "Generator": frame_class = StatementsFrameGenerator else: frame_class = StatementsFrameFunction body = frame_class( statements=mergeStatements((body,)), code_object=code_object, source_ref=body.getSourceReference(), ) body = makeStatementsSequenceFromStatement(statement=body) code_body.setBody(body) annotations = buildParameterAnnotations(provider, node, source_ref) return ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=outer_body, source_ref=source_ref ), defaults=defaults, kw_defaults=kw_defaults, annotations=annotations, source_ref=source_ref, )
def buildLambdaNode(provider, node, source_ref): # Many details to deal with, pylint: disable=too-many-locals assert getKind(node) == "Lambda" function_kind, flags = detectFunctionBodyKind(nodes=(node.body, )) outer_body, function_body, code_object = buildFunctionWithParsing( provider=provider, function_kind=function_kind, name="<lambda>", function_doc=None, flags=flags, node=node, source_ref=source_ref, ) if function_kind == "Function": code_body = function_body else: code_body = ExpressionGeneratorObjectBody( provider=function_body, name="<lambda>", code_object=code_object, flags=set(), source_ref=source_ref, ) code_body.qualname_provider = provider if function_kind == "Generator": function_body.setBody( makeStatementsSequenceFromStatement(statement=StatementReturn( expression=ExpressionMakeGeneratorObject( generator_ref=ExpressionFunctionRef( function_body=code_body, source_ref=source_ref), source_ref=source_ref, ), source_ref=source_ref, ))) defaults = buildNodeList(provider, node.args.defaults, source_ref) kw_defaults = buildParameterKwDefaults(provider=provider, node=node, function_body=function_body, source_ref=source_ref) body = buildNode(provider=code_body, node=node.body, source_ref=source_ref) if function_kind == "Generator": if python_version < 270: tmp_return_value = code_body.allocateTempVariable( temp_scope=None, name="yield_return") statements = ( StatementAssignmentVariable(variable=tmp_return_value, source=body, source_ref=source_ref), makeStatementConditional( condition=ExpressionComparisonIsNOT( left=ExpressionTempVariableRef( variable=tmp_return_value, source_ref=source_ref), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), yes_branch=StatementExpressionOnly( expression=ExpressionYield( expression=ExpressionTempVariableRef( variable=tmp_return_value, source_ref=source_ref), source_ref=source_ref, ), source_ref=source_ref, ), no_branch=None, source_ref=source_ref, ), ) body = makeTryFinallyStatement( provider=provider, tried=statements, final=StatementReleaseVariable(variable=tmp_return_value, source_ref=source_ref), source_ref=source_ref, ) else: body = StatementExpressionOnly(expression=body, source_ref=source_ref) else: body = StatementReturn(expression=body, source_ref=source_ref) if function_kind == "Generator": frame_class = StatementsFrameGenerator else: frame_class = StatementsFrameFunction body = frame_class( statements=mergeStatements((body, )), code_object=code_object, source_ref=body.getSourceReference(), ) body = makeStatementsSequenceFromStatement(statement=body) code_body.setBody(body) annotations = buildParameterAnnotations(provider, node, source_ref) return ExpressionFunctionCreation( function_ref=ExpressionFunctionRef(function_body=outer_body, source_ref=source_ref), defaults=defaults, kw_defaults=kw_defaults, annotations=annotations, source_ref=source_ref, )