def _wrapFunctionWithSpecialNestedArgs(name, outer_body, parameters, special_args, source_ref): inner_name = name.strip("<>") + "$inner" iter_vars = [] values = [] statements = [] def unpackFrom(source, arg_names): accesses = [] sub_special_index = 0 iter_var = outer_body.allocateTempVariable( None, "arg_iter_%d" % len(iter_vars)) iter_vars.append(iter_var) statements.append( StatementAssignmentVariable( variable=iter_var, source=ExpressionBuiltinIter1(value=source, source_ref=source_ref), source_ref=source_ref, )) for element_index, arg_name in enumerate(arg_names): if getKind(arg_name) == "Name": arg_var = outer_body.createProvidedVariable(arg_name.id) outer_body.getLocalsScope().registerProvidedVariable(arg_var) statements.append( StatementAssignmentVariable( variable=arg_var, source=ExpressionSpecialUnpack( value=ExpressionTempVariableRef( variable=iter_var, source_ref=source_ref), count=element_index + 1, expected=len(arg_names), starred=False, source_ref=source_ref, ), source_ref=source_ref, )) accesses.append( ExpressionVariableRef(variable=arg_var, source_ref=source_ref)) elif getKind(arg_name) == "Tuple": accesses.extend( unpackFrom( source=ExpressionSpecialUnpack( value=ExpressionTempVariableRef( variable=iter_var, source_ref=source_ref), count=element_index + 1, expected=len(arg_names), starred=False, source_ref=source_ref, ), arg_names=arg_name.elts, )) sub_special_index += 1 else: assert False, arg_name statements.append( StatementSpecialUnpackCheck( iterator=ExpressionTempVariableRef(variable=iter_var, source_ref=source_ref), count=len(arg_names), source_ref=source_ref, )) return accesses for arg_name in parameters.getParameterNames(): if arg_name.startswith("."): source = ExpressionVariableNameRef(provider=outer_body, variable_name=arg_name, source_ref=source_ref) values.extend(unpackFrom(source, special_args[arg_name])) else: values.append( ExpressionVariableNameRef(provider=outer_body, variable_name=arg_name, source_ref=source_ref)) code_body = ExpressionOutlineFunction(provider=outer_body, name=inner_name, source_ref=source_ref) statements.append( StatementReturn(expression=code_body, source_ref=source_ref)) outer_body.setBody( makeStatementsSequenceFromStatement(statement=makeTryFinallyStatement( provider=outer_body, tried=statements, final=[ StatementReleaseVariable(variable=variable, source_ref=source_ref) for variable in sorted( outer_body.getTempVariables(), key=lambda variable: variable.getName(), ) ], source_ref=source_ref, public_exc=False, ))) return code_body
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.setBody( 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.setBody(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 < 300 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 >= 360 and node.name == "__init_subclass__" and provider.isExpressionClassBody()): _injectDecorator(decorators, "classmethod", ("classmethod", ), source_ref) if (python_version >= 370 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 >= 340: function_body.qualname_setup = result.getVariableName() return result
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.setBody(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.setBody( 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 _buildContractionNode(provider, node, name, emit_class, start_value, source_ref): # The contraction nodes are reformulated to function bodies, with loops as # described in the developer manual. They use a lot of temporary names, # nested blocks, etc. and so a lot of variable names. # TODO: No function ought to be necessary, only a variable scope is. function_body = ExpressionFunctionBody(provider=provider, name=name, doc=None, parameters=ParameterSpec( ps_name=name, ps_normal_args=(".0", ), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=()), flags=set(), source_ref=source_ref) iter_tmp = function_body.getVariableForAssignment(variable_name=".0") assert iter_tmp.isParameterVariable() parent_module = provider.getParentModule() code_object = CodeObjectSpec( co_name=name, co_kind="Function", co_varnames=function_body.getParameters().getParameterNames(), co_argcount=len(function_body.getParameters().getParameterNames()), co_kwonlyargcount=0, co_has_starlist=False, co_has_stardict=False, co_filename=parent_module.getRunTimeFilename(), co_lineno=source_ref.getLineNumber(), future_spec=parent_module.getFutureSpec()) container_tmp = function_body.allocateTempVariable( temp_scope=None, name="contraction_result") statements, release_statements = _buildContractionBodyNode( function_body=function_body, provider=provider, node=node, emit_class=emit_class, iter_tmp=iter_tmp, temp_scope=None, start_value=start_value, container_tmp=container_tmp, assign_provider=False, source_ref=source_ref, ) assert start_value statements.append( StatementReturn(expression=ExpressionTempVariableRef( variable=container_tmp, source_ref=source_ref), source_ref=source_ref)) statements = (makeTryFinallyStatement( provider=function_body, tried=statements, final=release_statements, source_ref=source_ref.atInternal()), ) function_body.setBody( makeStatementsSequenceFromStatement(statement=StatementsFrameFunction( statements=mergeStatements(statements, False), code_object=code_object, source_ref=source_ref))) return ExpressionFunctionCall(function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef(function_body=function_body, source_ref=source_ref), code_object=code_object, defaults=(), kw_defaults=None, annotations=None, source_ref=source_ref), values=(ExpressionBuiltinIter1( value=buildNode( provider=provider, node=node.generators[0].iter, source_ref=source_ref), source_ref=source_ref), ), source_ref=source_ref)
def getSetUnpackingHelper(): helper_name = "_unpack_set" result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=(), ps_list_star_arg="args", ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) temp_scope = None tmp_result_variable = result.allocateTempVariable(temp_scope, "set") tmp_iter_variable = result.allocateTempVariable(temp_scope, "iter") tmp_item_variable = result.allocateTempVariable(temp_scope, "keys") loop_body = makeStatementsSequenceFromStatements( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=tmp_item_variable, source=ExpressionBuiltinNext1( value=ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=internal_source_ref), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), exception_name="StopIteration", handler_body=StatementLoopBreak(source_ref=internal_source_ref), source_ref=internal_source_ref, ), StatementExpressionOnly( expression=ExpressionSetOperationUpdate( set_arg=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref), value=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) args_variable = result.getVariableForAssignment(variable_name="args") final = ( StatementReleaseVariable(variable=tmp_result_variable, source_ref=internal_source_ref), StatementReleaseVariable(variable=tmp_iter_variable, source_ref=internal_source_ref), StatementReleaseVariable(variable=tmp_item_variable, source_ref=internal_source_ref), ) tried = makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_iter_variable, source=ExpressionBuiltinIter1( value=ExpressionVariableRef(variable=args_variable, source_ref=internal_source_ref), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), StatementAssignmentVariable( variable=tmp_result_variable, source=makeConstantRefNode(constant=set(), source_ref=internal_source_ref), source_ref=internal_source_ref, ), StatementLoop(body=loop_body, source_ref=internal_source_ref), StatementReturn( expression=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref), source_ref=internal_source_ref, ), ) result.setBody( makeStatementsSequenceFromStatement( makeTryFinallyStatement( provider=result, tried=tried, final=final, source_ref=internal_source_ref, ))) return result
def buildCallNode(provider, node, source_ref): called = buildNode(provider, node.func, source_ref) if python_version >= 350: list_star_arg = None dict_star_arg = None positional_args = [] # For Python3.5 compatibility, the error handling with star argument last # is the old one, only with a starred argument before that, things use the # new unpacking code. for node_arg in node.args[:-1]: if getKind(node_arg) == "Starred": assert python_version >= 350 list_star_arg = buildListUnpacking(provider, node.args, source_ref) positional_args = [] break else: if node.args and getKind(node.args[-1]) == "Starred": assert python_version >= 350 list_star_arg = buildNode(provider, node.args[-1].value, source_ref) positional_args = buildNodeList(provider, node.args[:-1], source_ref) else: positional_args = buildNodeList(provider, node.args, source_ref) # Only the values of keyword pairs have a real source ref, and those only # really matter, so that makes sense. keys = [] values = [] for keyword in node.keywords[:-1]: if keyword.arg is None: assert python_version >= 350 outline_body = ExpressionOutlineBody(provider=provider, name="dict_unpacking_call", source_ref=source_ref) tmp_called = outline_body.allocateTempVariable(temp_scope=None, name="called") helper_args = [ ExpressionTempVariableRef(variable=tmp_called, source_ref=source_ref), ExpressionMakeTuple(elements=buildDictionaryUnpackingArgs( provider=provider, keys=(keyword.arg for keyword in node.keywords), values=(keyword.value for keyword in node.keywords), source_ref=source_ref), source_ref=source_ref) ] dict_star_arg = ExpressionFunctionCall( function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=getFunctionCallHelperDictionaryUnpacking( ), source_ref=source_ref), code_object=None, defaults=(), kw_defaults=None, annotations=None, source_ref=source_ref), values=helper_args, source_ref=source_ref, ) outline_body.setBody( makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_called, source_ref=source_ref), source=called, source_ref=source_ref), StatementReturn(expression=_makeCallNode( called=ExpressionTempVariableRef( variable=tmp_called, source_ref=source_ref), positional_args=positional_args, keys=keys, values=values, list_star_arg=list_star_arg, dict_star_arg=dict_star_arg, source_ref=source_ref, ), source_ref=source_ref))) return outline_body # For Python3.5 compatibility, the error handling with star argument last # is the old one, only with a starred argument before that, things use the # new unpacking code. if node.keywords and node.keywords[-1].arg is None: assert python_version >= 350 dict_star_arg = buildNode(provider, node.keywords[-1].value, source_ref) keywords = node.keywords[:-1] else: keywords = node.keywords for keyword in keywords: keys.append( makeConstantRefNode(constant=keyword.arg, source_ref=source_ref, user_provided=True)) values.append(buildNode(provider, keyword.value, source_ref)) if python_version < 350: list_star_arg = buildNode(provider, node.starargs, source_ref, True) dict_star_arg = buildNode(provider, node.kwargs, source_ref, True) return _makeCallNode( called=called, positional_args=positional_args, keys=keys, values=values, list_star_arg=list_star_arg, dict_star_arg=dict_star_arg, source_ref=source_ref, )
def buildGeneratorExpressionNode(provider, node, source_ref): # Generator expressions are dealt with by general code. assert getKind(node) == "GeneratorExp" function_body = ExpressionOutlineBody(provider=provider, name="genexpr", source_ref=source_ref) iter_tmp = function_body.allocateTempVariable(temp_scope=None, name=".0") parent_module = provider.getParentModule() code_object = CodeObjectSpec( co_name="<genexpr>", co_kind="Generator", co_varnames=(".0", ), co_argcount=1, co_kwonlyargcount=0, co_has_starlist=False, co_has_stardict=False, co_filename=parent_module.getRunTimeFilename(), co_lineno=source_ref.getLineNumber(), future_spec=parent_module.getFutureSpec()) code_body = ExpressionGeneratorObjectBody(provider=provider, name="<genexpr>", flags=set(), source_ref=source_ref) function_body.setBody( makeStatementsSequenceFromStatements( StatementAssignmentVariable(variable=iter_tmp, source=ExpressionBuiltinIter1( value=buildNode( provider=provider, node=node.generators[0].iter, source_ref=source_ref), source_ref=source_ref), source_ref=source_ref), makeTryFinallyStatement( provider=function_body, tried=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), final=StatementReleaseVariable(variable=iter_tmp, source_ref=source_ref), source_ref=source_ref))) statements, release_statements = _buildContractionBodyNode( function_body=code_body, provider=provider, node=node, emit_class=ExpressionYield, iter_tmp=iter_tmp, temp_scope=None, start_value=None, container_tmp=None, assign_provider=False, source_ref=source_ref, ) statements = (makeTryFinallyStatement( provider=function_body, tried=statements, final=release_statements, source_ref=source_ref.atInternal()), ) code_body.setBody( makeStatementsSequenceFromStatement(statement=StatementsFrameGenerator( statements=mergeStatements(statements, False), code_object=code_object, source_ref=source_ref))) return function_body
def getClassBasesMroConversionHelper(): helper_name = "_mro_entries_conversion" result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=("bases", ), ps_pos_only_args=(), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ), inline_const_args=False, # TODO: Allow this. ) temp_scope = None tmp_result_variable = result.allocateTempVariable(temp_scope, "list") tmp_iter_variable = result.allocateTempVariable(temp_scope, "iter") tmp_item_variable = result.allocateTempVariable(temp_scope, "base") args_variable = result.getVariableForAssignment(variable_name="bases") non_type_case = makeStatementConditional( condition=ExpressionAttributeCheck( expression=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref), attribute_name="__mro_entries__", source_ref=internal_source_ref, ), yes_branch=StatementExpressionOnly( expression=ExpressionListOperationExtend( list_arg=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref), value=makeExpressionCall( called=ExpressionAttributeLookup( expression=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref), attribute_name="__mro_entries__", source_ref=internal_source_ref, ), args=makeExpressionMakeTuple( elements=(ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref), ), source_ref=internal_source_ref, ), kw=None, source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), no_branch=StatementListOperationAppend( list_arg=ExpressionTempVariableRef(variable=tmp_result_variable, source_ref=internal_source_ref), value=ExpressionTempVariableRef(variable=tmp_item_variable, source_ref=internal_source_ref), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) type_case = StatementListOperationAppend( list_arg=ExpressionTempVariableRef(variable=tmp_result_variable, source_ref=internal_source_ref), value=ExpressionTempVariableRef(variable=tmp_item_variable, source_ref=internal_source_ref), source_ref=internal_source_ref, ) loop_body = makeStatementsSequenceFromStatements( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=tmp_item_variable, source=ExpressionBuiltinNext1( value=ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=internal_source_ref), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), exception_name="StopIteration", handler_body=StatementLoopBreak(source_ref=internal_source_ref), source_ref=internal_source_ref, ), makeStatementConditional( condition=ExpressionBuiltinIsinstance( instance=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref), classes=makeConstantRefNode(constant=type, source_ref=internal_source_ref), source_ref=internal_source_ref, ), yes_branch=type_case, no_branch=non_type_case, source_ref=internal_source_ref, ), ) final = ( StatementReleaseVariable(variable=args_variable, source_ref=internal_source_ref), StatementReleaseVariable(variable=tmp_result_variable, source_ref=internal_source_ref), StatementReleaseVariable(variable=tmp_iter_variable, source_ref=internal_source_ref), StatementReleaseVariable(variable=tmp_item_variable, source_ref=internal_source_ref), ) tried = makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_iter_variable, source=ExpressionBuiltinIter1( value=ExpressionVariableRef(variable=args_variable, source_ref=internal_source_ref), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), StatementAssignmentVariable( variable=tmp_result_variable, source=makeConstantRefNode(constant=[], source_ref=internal_source_ref), source_ref=internal_source_ref, ), StatementLoop(loop_body=loop_body, source_ref=internal_source_ref), StatementReturn( expression=ExpressionBuiltinTuple( value=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) result.setChild( "body", makeStatementsSequenceFromStatement( makeTryFinallyStatement( provider=result, tried=tried, final=final, source_ref=internal_source_ref, )), ) return result
def buildFunctionNode(provider, node, source_ref): assert getKind(node) == "FunctionDef" function_statements, function_doc = extractDocFromBody(node) function_body = ExpressionFunctionBody(provider=provider, name=node.name, doc=function_doc, parameters=buildParameterSpec( node.name, node, source_ref), source_ref=source_ref) # Hack: function_body.parent = provider decorators = buildNodeList(provider, reversed(node.decorator_list), source_ref) defaults = buildNodeList(provider, node.args.defaults, source_ref) kw_defaults = buildParameterKwDefaults(provider, node, function_body, source_ref) function_statements_body = buildStatementsNode(provider=function_body, nodes=function_statements, frame=True, source_ref=source_ref) if function_body.isExpressionFunctionBody() and function_body.isGenerator( ): # TODO: raise generator exit? pass elif function_statements_body is None: function_statements_body = makeStatementsSequenceFromStatement( statement=StatementReturn(expression=ExpressionConstantRef( constant=None, source_ref=source_ref.atInternal()), source_ref=source_ref.atInternal())) elif not function_statements_body.isStatementAborting(): function_statements_body.setStatements( function_statements_body.getStatements() + (StatementReturn(expression=ExpressionConstantRef( constant=None, source_ref=source_ref), source_ref=source_ref.atInternal()), )) function_body.setBody(function_statements_body) annotations = buildParameterAnnotations(provider, node, source_ref) decorated_body = ExpressionFunctionCreation( function_ref=ExpressionFunctionRef(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 applies them to every class __new__. We add them # early, so our optimization will see it. if node.name == "__new__" and not decorators and \ provider.isExpressionFunctionBody() and provider.isClassDictCreation(): decorators = (ExpressionBuiltinRef(builtin_name="staticmethod", source_ref=source_ref), ) for decorator in decorators: decorated_body = ExpressionCallNoKeywords( called=decorator, args=ExpressionMakeTuple(elements=(decorated_body, ), source_ref=source_ref), source_ref=decorator.getSourceReference()) return StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef(variable_name=node.name, source_ref=source_ref), source=decorated_body, source_ref=source_ref)
def _buildContractionNode(provider, node, name, emit_class, start_value, assign_provider, source_ref): # The contraction nodes are reformulated to function bodies, with loops as described # in the developer manual. They use a lot of temporary names, nested blocks, etc. and # so a lot of variable names. There is no good way around that, and we deal with many # cases, due to having generator expressions sharing this code, # pylint: disable=R0912,R0914 # Note: The assign_provider is only to cover Python2 list contractions, assigning one # of the loop variables to the outside scope. assert provider.isParentVariableProvider(), provider function_body = ExpressionFunctionBody( provider=provider, name=name, doc=None, parameters=make_contraction_parameters, source_ref=source_ref) temp_block = StatementTempBlock(source_ref=source_ref) if start_value is not None: container_tmp = temp_block.getTempVariable("result") statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=container_tmp.makeReference(temp_block), source_ref=source_ref), source=start_value, source_ref=source_ref.atInternal()) ] else: statements = [] if hasattr(node, "elt"): if start_value is not None: current_body = emit_class(ExpressionTempVariableRef( variable=container_tmp.makeReference(temp_block), source_ref=source_ref), buildNode(provider=function_body, node=node.elt, source_ref=source_ref), source_ref=source_ref) else: assert emit_class is ExpressionYield function_body.markAsGenerator() current_body = emit_class(buildNode(provider=function_body, node=node.elt, source_ref=source_ref), source_ref=source_ref) else: assert emit_class is ExpressionDictOperationSet current_body = emit_class(ExpressionTempVariableRef( variable=container_tmp.makeReference(temp_block), source_ref=source_ref), key=buildNode( provider=function_body, node=node.key, source_ref=source_ref, ), value=buildNode( provider=function_body, node=node.value, source_ref=source_ref, ), source_ref=source_ref) current_body = StatementExpressionOnly(expression=current_body, source_ref=source_ref) for qual in reversed(node.generators): nested_temp_block = StatementTempBlock(source_ref=source_ref) tmp_iter_variable = nested_temp_block.getTempVariable( "contraction_iter") tmp_value_variable = nested_temp_block.getTempVariable("iter_value") # The first iterated value is to be calculated outside of the function and # will be given as a parameter "_iterated". if qual is node.generators[0]: value_iterator = ExpressionVariableRef(variable_name="__iterator", source_ref=source_ref) else: value_iterator = ExpressionBuiltinIter1(value=buildNode( provider=function_body, node=qual.iter, source_ref=source_ref), source_ref=source_ref) # First create the iterator and store it, next should be loop body nested_statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_iter_variable.makeReference( nested_temp_block), source_ref=source_ref), source=value_iterator, source_ref=source_ref) ] loop_statements = [ makeTryExceptSingleHandlerNode( tried=makeStatementsSequenceFromStatement( statement=StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_value_variable.makeReference( nested_temp_block), source_ref=source_ref), source=ExpressionBuiltinNext1( value=ExpressionTempVariableRef( variable=tmp_iter_variable.makeReference( nested_temp_block), source_ref=source_ref), source_ref=source_ref), source_ref=source_ref)), exception_name="StopIteration", handler_body=makeStatementsSequenceFromStatement( statement=StatementBreakLoop( source_ref=source_ref.atInternal())), source_ref=source_ref), buildAssignmentStatements( provider=provider if assign_provider else function_body, node=qual.target, source=ExpressionTempVariableRef( variable=tmp_value_variable.makeReference( nested_temp_block), source_ref=source_ref), source_ref=source_ref) ] conditions = buildNodeList(provider=function_body, nodes=qual.ifs, source_ref=source_ref) if len(conditions) == 1: loop_statements.append( StatementConditional( condition=conditions[0], yes_branch=makeStatementsSequenceFromStatement( statement=current_body), no_branch=None, source_ref=source_ref)) elif len(conditions) > 1: loop_statements.append( StatementConditional( condition=buildAndNode(provider=function_body, values=conditions, source_ref=source_ref), yes_branch=makeStatementsSequenceFromStatement( statement=current_body), no_branch=None, source_ref=source_ref)) else: loop_statements.append(current_body) nested_statements.append( StatementLoop(body=StatementsSequence(statements=loop_statements, source_ref=source_ref), source_ref=source_ref)) nested_temp_block.setBody( StatementsSequence(statements=nested_statements, source_ref=source_ref)) current_body = nested_temp_block statements.append(current_body) if start_value is not None: statements.append( StatementReturn(expression=ExpressionTempVariableRef( variable=container_tmp.makeReference(temp_block), source_ref=source_ref), source_ref=source_ref)) temp_block.setBody( StatementsSequence(statements=statements, source_ref=source_ref)) function_body.setBody( StatementsFrame(statements=[temp_block], guard_mode="pass_through" if emit_class is not ExpressionYield else "generator", arg_names=(), kw_only_count=0, code_name="contraction", source_ref=source_ref)) return ExpressionFunctionCall(function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef(function_body=function_body, source_ref=source_ref), defaults=(), kw_defaults=None, annotations=None, source_ref=source_ref), values=(ExpressionBuiltinIter1( value=buildNode( provider=provider, node=node.generators[0].iter, source_ref=source_ref), source_ref=source_ref), ), source_ref=source_ref)
def buildClassNode3(provider, node, source_ref): # Many variables, due to the huge re-formulation that is going on here, # which just has the complexity and optimization checks: # pylint: disable=I0021,too-many-branches,too-many-locals,too-many-statements # This function is the Python3 special case with special re-formulation as # according to developer manual. class_statement_nodes, class_doc = extractDocFromBody(node) # We need a scope for the temporary variables, and they might be closured. temp_scope = provider.allocateTempScope(name="class_creation") tmp_class_decl_dict = provider.allocateTempVariable(temp_scope=temp_scope, name="class_decl_dict") tmp_metaclass = provider.allocateTempVariable(temp_scope=temp_scope, name="metaclass") tmp_prepared = provider.allocateTempVariable(temp_scope=temp_scope, name="prepared") class_creation_function = ExpressionClassBody(provider=provider, name=node.name, doc=class_doc, source_ref=source_ref) class_locals_scope = class_creation_function.getLocalsScope() # Only local variable, for provision to methods. class_variable = class_locals_scope.getLocalVariable( owner=class_creation_function, variable_name="__class__") class_locals_scope.registerProvidedVariable(class_variable) class_variable_ref = ExpressionVariableRef(variable=class_variable, source_ref=source_ref) parent_module = provider.getParentModule() code_object = CodeObjectSpec( co_name=node.name, co_kind="Class", co_varnames=(), co_freevars=(), co_argcount=0, co_posonlyargcount=0, co_kwonlyargcount=0, co_has_starlist=False, co_has_stardict=False, co_filename=parent_module.getRunTimeFilename(), co_lineno=source_ref.getLineNumber(), future_spec=parent_module.getFutureSpec(), ) body = buildFrameNode( provider=class_creation_function, nodes=class_statement_nodes, code_object=code_object, source_ref=source_ref, ) source_ref_orig = source_ref if body is not None: # The frame guard has nothing to tell its line number to. body.source_ref = source_ref locals_scope = class_creation_function.getLocalsScope() statements = [ StatementSetLocals( locals_scope=locals_scope, new_locals=ExpressionTempVariableRef(variable=tmp_prepared, source_ref=source_ref), source_ref=source_ref, ), StatementAssignmentVariableName( provider=class_creation_function, variable_name="__module__", source=ExpressionModuleAttributeNameRef( variable=provider.getParentModule().getVariableForReference( "__name__"), source_ref=source_ref, ), source_ref=source_ref, ), ] if class_doc is not None: statements.append( StatementAssignmentVariableName( provider=class_creation_function, variable_name="__doc__", source=makeConstantRefNode(constant=class_doc, source_ref=source_ref, user_provided=True), source_ref=source_ref, )) # The "__qualname__" attribute is new in Python3. qualname = class_creation_function.getFunctionQualname() if python_version < 0x340: qualname_ref = makeConstantRefNode(constant=qualname, source_ref=source_ref, user_provided=True) else: qualname_ref = ExpressionFunctionQualnameRef( function_body=class_creation_function, source_ref=source_ref) statements.append( StatementLocalsDictOperationSet( locals_scope=locals_scope, variable_name="__qualname__", value=qualname_ref, source_ref=source_ref, )) if python_version >= 0x340: qualname_assign = statements[-1] if python_version >= 0x360 and class_creation_function.needsAnnotationsDictionary( ): statements.append( StatementLocalsDictOperationSet( locals_scope=locals_scope, variable_name="__annotations__", value=makeConstantRefNode(constant={}, source_ref=source_ref, user_provided=True), source_ref=source_ref, )) statements.append(body) if node.bases: tmp_bases = provider.allocateTempVariable(temp_scope=temp_scope, name="bases") if python_version >= 0x370: tmp_bases_orig = provider.allocateTempVariable( temp_scope=temp_scope, name="bases_orig") def makeBasesRef(): return ExpressionTempVariableRef(variable=tmp_bases, source_ref=source_ref) else: def makeBasesRef(): return makeConstantRefNode(constant=(), source_ref=source_ref) if python_version >= 0x370 and node.bases: statements.append( makeStatementConditional( condition=makeComparisonExpression( comparator="NotEq", left=ExpressionTempVariableRef(variable=tmp_bases, source_ref=source_ref), right=ExpressionTempVariableRef(variable=tmp_bases_orig, source_ref=source_ref), source_ref=source_ref, ), yes_branch=StatementLocalsDictOperationSet( locals_scope=locals_scope, variable_name="__orig_bases__", value=ExpressionTempVariableRef(variable=tmp_bases_orig, source_ref=source_ref), source_ref=source_ref, ), no_branch=None, source_ref=source_ref, )) statements += ( StatementAssignmentVariable( variable=class_variable, source=makeExpressionCall( called=ExpressionTempVariableRef(variable=tmp_metaclass, source_ref=source_ref), args=makeExpressionMakeTuple( elements=( makeConstantRefNode( constant=node.name, source_ref=source_ref, user_provided=True, ), makeBasesRef(), ExpressionBuiltinLocalsRef(locals_scope=locals_scope, source_ref=source_ref), ), source_ref=source_ref, ), kw=ExpressionTempVariableRef(variable=tmp_class_decl_dict, source_ref=source_ref), source_ref=source_ref, ), source_ref=source_ref, ), StatementReturn(expression=class_variable_ref, source_ref=source_ref), ) body = makeStatementsSequenceFromStatement( statement=makeTryFinallyStatement( provider=class_creation_function, tried=mergeStatements(statements, True), final=StatementReleaseLocals(locals_scope=locals_scope, source_ref=source_ref), source_ref=source_ref, )) # The class body is basically a function that implicitly, at the end # returns its locals and cannot have other return statements contained. class_creation_function.setChild("body", body) # The class body is basically a function that implicitly, at the end # returns its created class and cannot have other return statements # contained. decorated_body = class_creation_function for decorator in buildNodeList(provider, reversed(node.decorator_list), source_ref): decorated_body = makeExpressionCall( called=decorator, args=makeExpressionMakeTuple(elements=(decorated_body, ), source_ref=source_ref), kw=None, source_ref=decorator.getSourceReference(), ) if node.keywords and node.keywords[-1].arg is None: keywords = node.keywords[:-1] else: keywords = node.keywords statements = [] if node.bases: statements.append( StatementAssignmentVariable( variable=tmp_bases if python_version < 0x370 else tmp_bases_orig, source=_buildBasesTupleCreationNode(provider=provider, elements=node.bases, source_ref=source_ref), source_ref=source_ref, )) if python_version >= 0x370: bases_conversion = ExpressionFunctionCall( function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=getClassBasesMroConversionHelper(), source_ref=source_ref, ), defaults=(), kw_defaults=None, annotations=None, source_ref=source_ref, ), values=(ExpressionTempVariableRef(variable=tmp_bases_orig, source_ref=source_ref), ), source_ref=source_ref, ) statements.append( StatementAssignmentVariable(variable=tmp_bases, source=bases_conversion, source_ref=source_ref)) statements.append( StatementAssignmentVariable( variable=tmp_class_decl_dict, source=makeDictCreationOrConstant2( keys=[keyword.arg for keyword in keywords], values=[ buildNode(provider, keyword.value, source_ref) for keyword in keywords ], source_ref=source_ref, ), source_ref=source_ref, )) if node.keywords and node.keywords[-1].arg is None: statements.append( StatementDictOperationUpdate( dict_arg=ExpressionVariableRef(variable=tmp_class_decl_dict, source_ref=source_ref), value=buildNode(provider, node.keywords[-1].value, source_ref), source_ref=source_ref, )) # Check if there are bases, and if there are, go with the type of the # first base class as a metaclass unless it was specified in the class # decl dict of course. if node.bases: unspecified_metaclass_expression = ExpressionBuiltinType1( value=ExpressionSubscriptLookup( expression=ExpressionTempVariableRef(variable=tmp_bases, source_ref=source_ref), subscript=makeConstantRefNode(constant=0, source_ref=source_ref, user_provided=True), source_ref=source_ref, ), source_ref=source_ref, ) # Might become empty behind our back during conversion, therefore make the # check at run time for 3.7 or higher. if python_version >= 0x370: unspecified_metaclass_expression = ExpressionConditional( condition=ExpressionTempVariableRef(variable=tmp_bases, source_ref=source_ref), expression_yes=unspecified_metaclass_expression, expression_no=makeExpressionBuiltinTypeRef( builtin_name="type", source_ref=source_ref), source_ref=source_ref, ) else: unspecified_metaclass_expression = makeExpressionBuiltinTypeRef( builtin_name="type", source_ref=source_ref) call_prepare = StatementAssignmentVariable( variable=tmp_prepared, source=makeExpressionCall( called=ExpressionAttributeLookup( expression=ExpressionTempVariableRef(variable=tmp_metaclass, source_ref=source_ref), attribute_name="__prepare__", source_ref=source_ref, ), args=makeExpressionMakeTuple( elements=( makeConstantRefNode(constant=node.name, source_ref=source_ref, user_provided=True), makeBasesRef(), ), source_ref=source_ref, ), kw=ExpressionTempVariableRef(variable=tmp_class_decl_dict, source_ref=source_ref), source_ref=source_ref, ), source_ref=source_ref, ) if python_version >= 0x364: call_prepare = makeStatementsSequenceFromStatements( call_prepare, makeStatementConditional( condition=ExpressionAttributeCheck( expression=ExpressionTempVariableRef( variable=tmp_prepared, source_ref=source_ref), attribute_name="__getitem__", source_ref=source_ref, ), yes_branch=None, no_branch=makeRaiseExceptionExpressionFromTemplate( exception_type="TypeError", template="%s.__prepare__() must return a mapping, not %s", template_args=( ExpressionBuiltinGetattr( expression=ExpressionTempVariableRef( variable=tmp_metaclass, source_ref=source_ref), name=makeConstantRefNode(constant="__name__", source_ref=source_ref), default=makeConstantRefNode(constant="<metaclass>", source_ref=source_ref), source_ref=source_ref, ), ExpressionAttributeLookup( expression=ExpressionBuiltinType1( value=ExpressionTempVariableRef( variable=tmp_prepared, source_ref=source_ref), source_ref=source_ref, ), attribute_name="__name__", source_ref=source_ref, ), ), source_ref=source_ref, ).asStatement(), source_ref=source_ref, ), ) statements += ( StatementAssignmentVariable( variable=tmp_metaclass, source=ExpressionSelectMetaclass( metaclass=ExpressionConditional( condition=ExpressionDictOperationIn( key=makeConstantRefNode( constant="metaclass", source_ref=source_ref, user_provided=True, ), dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref), source_ref=source_ref, ), expression_yes=ExpressionDictOperationGet( dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref), key=makeConstantRefNode( constant="metaclass", source_ref=source_ref, user_provided=True, ), source_ref=source_ref, ), expression_no=unspecified_metaclass_expression, source_ref=source_ref, ), bases=makeBasesRef(), source_ref=source_ref, ), source_ref=source_ref_orig, ), makeStatementConditional( condition=ExpressionDictOperationIn( key=makeConstantRefNode(constant="metaclass", source_ref=source_ref, user_provided=True), dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref), source_ref=source_ref, ), no_branch=None, yes_branch=StatementDictOperationRemove( dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref), key=makeConstantRefNode(constant="metaclass", source_ref=source_ref, user_provided=True), source_ref=source_ref, ), source_ref=source_ref, ), makeStatementConditional( condition=ExpressionAttributeCheck( expression=ExpressionTempVariableRef(variable=tmp_metaclass, source_ref=source_ref), attribute_name="__prepare__", source_ref=source_ref, ), yes_branch=call_prepare, no_branch=StatementAssignmentVariable( variable=tmp_prepared, source=makeConstantRefNode(constant={}, source_ref=source_ref, user_provided=True), source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariableName( provider=provider, variable_name=mangleName(node.name, provider), source=decorated_body, source_ref=source_ref, ), ) if python_version >= 0x340: class_creation_function.qualname_setup = node.name, qualname_assign final = [tmp_class_decl_dict, tmp_metaclass, tmp_prepared] if node.bases: final.insert(0, tmp_bases) if python_version >= 0x370: final.insert(0, tmp_bases_orig) return makeTryFinallyStatement( provider=provider, tried=statements, final=tuple( StatementReleaseVariable(variable=variable, source_ref=source_ref) for variable in final), source_ref=source_ref, )
def _buildContractionNode(provider, node, name, emit_class, start_value, source_ref): # The contraction nodes are reformulated to function bodies, with loops as # described in the developer manual. They use a lot of temporary names, # nested blocks, etc. and so a lot of variable names. function_body = ExpressionOutlineFunction( provider=provider, name=intern(name[1:-1]), source_ref=source_ref ) iter_tmp = function_body.allocateTempVariable(temp_scope=None, name=".0") container_tmp = function_body.allocateTempVariable( temp_scope=None, name="contraction" ) statements, release_statements = _buildContractionBodyNode( provider=provider, node=node, emit_class=emit_class, iter_tmp=iter_tmp, temp_scope=None, start_value=start_value, container_tmp=container_tmp, function_body=function_body, assign_provider=False, for_asyncgen=False, source_ref=source_ref, ) assign_iter_statement = StatementAssignmentVariable( source=_makeIteratorCreation( provider=provider, qual=node.generators[0], for_asyncgen=False, source_ref=source_ref, ), variable=iter_tmp, source_ref=source_ref, ) statements.append( StatementReturn( expression=ExpressionTempVariableRef( variable=container_tmp, source_ref=source_ref ), source_ref=source_ref, ) ) statements = ( makeTryFinallyStatement( provider=function_body, tried=statements, final=release_statements, source_ref=source_ref.atInternal(), ), ) if python_version < 300: body = makeStatementsSequenceFromStatements(assign_iter_statement, statements) else: parent_module = provider.getParentModule() code_object = CodeObjectSpec( co_name=name, co_kind="Function", co_varnames=(), co_argcount=1, co_posonlyargcount=0, co_kwonlyargcount=0, co_has_starlist=False, co_has_stardict=False, co_filename=parent_module.getRunTimeFilename(), co_lineno=source_ref.getLineNumber(), future_spec=parent_module.getFutureSpec(), ) body = makeStatementsSequenceFromStatements( assign_iter_statement, StatementsFrameFunction( statements=mergeStatements(statements, False), code_object=code_object, source_ref=source_ref, ), ) function_body.setBody(body) return function_body
def buildGeneratorExpressionNode(provider, node, source_ref): # Generator expressions are dealt with by general code. assert getKind(node) == "GeneratorExp" function_body = ExpressionOutlineBody( provider=provider, name="genexpr", source_ref=source_ref ) iter_tmp = function_body.allocateTempVariable(temp_scope=None, name=".0") parent_module = provider.getParentModule() code_object = CodeObjectSpec( co_name="<genexpr>", co_kind="Generator", co_varnames=(".0",), co_argcount=1, co_posonlyargcount=0, co_kwonlyargcount=0, co_has_starlist=False, co_has_stardict=False, co_filename=parent_module.getRunTimeFilename(), co_lineno=source_ref.getLineNumber(), future_spec=parent_module.getFutureSpec(), ) is_async = any(getattr(qual, "is_async", 0) for qual in node.generators) # Some of the newly allowed stuff in 3.7 fails to set the async flag. if not is_async and python_version >= 370: is_async = detectFunctionBodyKind(nodes=node.generators)[0] in ( "Asyncgen", "Coroutine", ) if is_async: code_body = ExpressionAsyncgenObjectBody( provider=provider, name="<genexpr>", code_object=code_object, flags=None, auto_release=None, source_ref=source_ref, ) maker_class = ExpressionMakeAsyncgenObject else: code_body = ExpressionGeneratorObjectBody( provider=provider, name="<genexpr>", code_object=code_object, flags=None, auto_release=None, source_ref=source_ref.atColumnNumber(node.col_offset + 1), ) maker_class = ExpressionMakeGeneratorObject function_body.setBody( makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=iter_tmp, source=_makeIteratorCreation( provider=provider, qual=node.generators[0], for_asyncgen=is_async, source_ref=source_ref, ), source_ref=source_ref, ), makeTryFinallyStatement( provider=function_body, tried=StatementReturn( expression=maker_class( ExpressionFunctionRef( function_body=code_body, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ), final=StatementReleaseVariable( variable=iter_tmp, source_ref=source_ref ), source_ref=source_ref, ), ) ) statements, release_statements = _buildContractionBodyNode( provider=provider, node=node, emit_class=ExpressionYield, iter_tmp=iter_tmp, temp_scope=None, start_value=None, container_tmp=None, function_body=code_body, assign_provider=False, for_asyncgen=is_async, source_ref=source_ref, ) if is_async: statements.append(StatementGeneratorReturnNone(source_ref=source_ref)) statements = ( makeTryFinallyStatement( provider=function_body, tried=statements, final=release_statements, source_ref=source_ref.atInternal(), ), ) code_body.setBody( makeStatementsSequenceFromStatement( statement=StatementsFrameGenerator( statements=mergeStatements(statements, False), code_object=code_object, source_ref=source_ref, ) ) ) return function_body
def getDictUnpackingHelper(): helper_name = "_unpack_dict" result = ExpressionFunctionBody(provider=getInternalModule(), name=helper_name, doc=None, parameters=ParameterSpec( name=helper_name, normal_args=(), list_star_arg="args", dict_star_arg=None, default_count=0, kw_only_args=()), source_ref=internal_source_ref, is_class=False) temp_scope = None tmp_result_variable = result.allocateTempVariable(temp_scope, "dict") tmp_iter_variable = result.allocateTempVariable(temp_scope, "iter") tmp_item_variable = result.allocateTempVariable(temp_scope, "keys") loop_body = makeStatementsSequenceFromStatements( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref), source=ExpressionBuiltinNext1(value=ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=internal_source_ref), source_ref=internal_source_ref), source_ref=internal_source_ref), exception_name="StopIteration", handler_body=StatementBreakLoop(source_ref=internal_source_ref), source_ref=internal_source_ref), makeTryExceptSingleHandlerNode( tried=StatementExpressionOnly( expression=ExpressionDictOperationUpdate( dict_arg=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref), value=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref), source_ref=internal_source_ref), source_ref=internal_source_ref), exception_name="AttributeError", handler_body=StatementRaiseException( exception_type=ExpressionBuiltinMakeException( exception_name="TypeError", args=(ExpressionOperationBinary( operator="Mod", left=ExpressionConstantRef( constant="""\ '%s' object is not a mapping""", source_ref=internal_source_ref, user_provided=True), right=ExpressionMakeTuple( elements=(ExpressionAttributeLookup( source=ExpressionBuiltinType1( value=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref), source_ref=internal_source_ref), attribute_name="__name__", source_ref=internal_source_ref), ), source_ref=internal_source_ref), source_ref=internal_source_ref), ), source_ref=internal_source_ref), exception_value=None, exception_trace=None, exception_cause=None, source_ref=internal_source_ref), source_ref=internal_source_ref)) args_variable = result.getVariableForAssignment(variable_name="args") final = ( StatementReleaseVariable(variable=tmp_result_variable, source_ref=internal_source_ref), StatementReleaseVariable(variable=tmp_iter_variable, source_ref=internal_source_ref), StatementReleaseVariable(variable=tmp_item_variable, source_ref=internal_source_ref), ) tried = makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_iter_variable, source_ref=internal_source_ref), source=ExpressionBuiltinIter1(value=ExpressionVariableRef( variable_name="args", variable=args_variable, source_ref=internal_source_ref), source_ref=internal_source_ref), source_ref=internal_source_ref), StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref), source=ExpressionConstantRef(constant={}, source_ref=internal_source_ref), source_ref=internal_source_ref), StatementLoop(body=loop_body, source_ref=internal_source_ref), StatementReturn(expression=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref), source_ref=internal_source_ref)) result.setBody( makeStatementsSequenceFromStatement( makeTryFinallyStatement(provider=result, tried=tried, final=final, source_ref=internal_source_ref))) return result
def buildComplexComparisonNode(provider, left, rights, comparators, source_ref): # This is a bit complex, due to the many details, pylint: disable=too-many-locals outline_body = ExpressionOutlineBody(provider=provider, name="comparison_chain", source_ref=source_ref) variables = [ outline_body.allocateTempVariable(temp_scope=None, name="operand_%d" % count) for count in range(2, len(rights) + 2) ] tmp_variable = outline_body.allocateTempVariable(temp_scope=None, name="comparison_result") def makeTempAssignment(count, value): return StatementAssignmentVariable(variable=variables[count], source=value, source_ref=source_ref) def makeReleaseStatement(count): return StatementReleaseVariable(variable=variables[count], source_ref=source_ref) def makeValueComparisonReturn(left, right, comparator): yield StatementAssignmentVariable( variable=tmp_variable, source=_makeComparisonNode(left=left, right=right, comparator=comparator, source_ref=source_ref), source_ref=source_ref, ) yield makeStatementConditional( condition=ExpressionOperationNot( operand=ExpressionTempVariableRef(variable=tmp_variable, source_ref=source_ref), source_ref=source_ref, ), yes_branch=StatementReturn( expression=ExpressionTempVariableRef(variable=tmp_variable, source_ref=source_ref), source_ref=source_ref, ), no_branch=None, source_ref=source_ref, ) statements = [] final = [] for count, value in enumerate(rights): if value is not rights[-1]: statements.append(makeTempAssignment(count, value)) final.append(makeReleaseStatement(count)) right = ExpressionTempVariableRef(variable=variables[count], source_ref=source_ref) else: right = value if count != 0: left = ExpressionTempVariableRef(variable=variables[count - 1], source_ref=source_ref) comparator = comparators[count] if value is not rights[-1]: statements.extend( makeValueComparisonReturn(left, right, comparator)) else: statements.append( StatementReturn( expression=_makeComparisonNode( left=left, right=right, comparator=comparator, source_ref=source_ref, ), source_ref=source_ref, )) final.append( StatementReleaseVariable(variable=tmp_variable, source_ref=source_ref)) outline_body.setChild( "body", makeStatementsSequenceFromStatement(statement=makeTryFinallyStatement( provider=outline_body, tried=statements, final=final, source_ref=source_ref, )), ) return outline_body
def buildClassNode2(provider, node, source_ref): # This function is the Python2 special case with special re-formulation as # according to developer manual, and it's very detailed, pylint: disable=too-many-locals class_statement_nodes, class_doc = extractDocFromBody(node) function_body = ExpressionClassBody( provider=provider, name=node.name, doc=class_doc, source_ref=source_ref ) parent_module = provider.getParentModule() code_object = CodeObjectSpec( co_name=node.name, co_kind="Class", co_varnames=(), co_argcount=0, co_posonlyargcount=0, co_kwonlyargcount=0, co_has_starlist=False, co_has_stardict=False, co_filename=parent_module.getRunTimeFilename(), co_lineno=source_ref.getLineNumber(), future_spec=parent_module.getFutureSpec(), ) body = buildFrameNode( provider=function_body, nodes=class_statement_nodes, code_object=code_object, source_ref=source_ref, ) if body is not None: # The frame guard has nothing to tell its line number to. body.source_ref = source_ref.atInternal() locals_scope = function_body.getFunctionLocalsScope() # The class body is basically a function that implicitly, at the end # returns its locals and cannot have other return statements contained, and # starts out with a variables "__module__" and potentially "__doc__" set. statements = [ StatementSetLocalsDictionary(locals_scope=locals_scope, source_ref=source_ref), StatementAssignmentVariableName( provider=function_body, variable_name="__module__", source=ExpressionModuleAttributeNameRef( variable=provider.getParentModule().getVariableForReference("__name__"), source_ref=source_ref, ), source_ref=source_ref.atInternal(), ), ] if class_doc is not None: statements.append( StatementAssignmentVariableName( provider=function_body, variable_name="__doc__", source=makeConstantRefNode( constant=class_doc, source_ref=source_ref, user_provided=True ), source_ref=source_ref.atInternal(), ) ) statements += [ body, StatementReturn( expression=ExpressionBuiltinLocalsRef( locals_scope=locals_scope, source_ref=source_ref ), source_ref=source_ref, ), ] body = makeStatementsSequenceFromStatement( statement=makeTryFinallyStatement( provider=function_body, tried=mergeStatements(statements, True), final=StatementReleaseLocals( locals_scope=locals_scope, source_ref=source_ref ), source_ref=source_ref, ) ) # The class body is basically a function that implicitly, at the end # returns its locals and cannot have other return statements contained. function_body.setBody(body) temp_scope = provider.allocateTempScope("class_creation") tmp_bases = provider.allocateTempVariable(temp_scope, "bases") tmp_class_dict = provider.allocateTempVariable(temp_scope, "class_dict") tmp_metaclass = provider.allocateTempVariable(temp_scope, "metaclass") tmp_class = provider.allocateTempVariable(temp_scope, "class") select_metaclass = ExpressionOutlineBody( provider=provider, name="select_metaclass", body=None, source_ref=source_ref ) if node.bases: tmp_base = select_metaclass.allocateTempVariable(temp_scope=None, name="base") statements = ( StatementAssignmentVariable( variable=tmp_base, source=ExpressionSubscriptLookup( subscribed=ExpressionTempVariableRef( variable=tmp_bases, source_ref=source_ref ), subscript=makeConstantRefNode( constant=0, source_ref=source_ref, user_provided=True ), source_ref=source_ref, ), source_ref=source_ref, ), makeTryFinallyStatement( provider, tried=StatementTry( tried=makeStatementsSequenceFromStatement( statement=StatementReturn( expression=ExpressionAttributeLookup( source=ExpressionTempVariableRef( variable=tmp_base, source_ref=source_ref ), attribute_name="__class__", source_ref=source_ref, ), source_ref=source_ref, ) ), except_handler=makeStatementsSequenceFromStatement( statement=StatementReturn( expression=ExpressionBuiltinType1( value=ExpressionTempVariableRef( variable=tmp_base, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ) ), break_handler=None, continue_handler=None, return_handler=None, source_ref=source_ref, ), final=StatementReleaseVariable( variable=tmp_base, source_ref=source_ref ), source_ref=source_ref, public_exc=False, ), ) else: statements = ( StatementTry( tried=makeStatementsSequenceFromStatement( statement=StatementReturn( # TODO: Should avoid checking __builtins__ for this. expression=ExpressionVariableNameRef( variable_name="__metaclass__", provider=parent_module, source_ref=source_ref, ), source_ref=source_ref, ) ), except_handler=makeStatementsSequenceFromStatement( statement=StatementReturn( expression=ExpressionBuiltinAnonymousRef( builtin_name="classobj", source_ref=source_ref ), source_ref=source_ref, ) ), break_handler=None, continue_handler=None, return_handler=None, source_ref=source_ref, ), ) select_metaclass.setBody( makeStatementsSequence( statements=statements, allow_none=False, source_ref=source_ref ) ) statements = [ StatementAssignmentVariable( variable=tmp_bases, source=makeSequenceCreationOrConstant( sequence_kind="tuple", elements=buildNodeList( provider=provider, nodes=node.bases, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariable( variable=tmp_class_dict, source=function_body, source_ref=source_ref ), StatementAssignmentVariable( variable=tmp_metaclass, source=ExpressionConditional( condition=ExpressionDictOperationIn( key=makeConstantRefNode( constant="__metaclass__", source_ref=source_ref, user_provided=True, ), dict_arg=ExpressionTempVariableRef( variable=tmp_class_dict, source_ref=source_ref ), source_ref=source_ref, ), expression_yes=ExpressionDictOperationGet( dict_arg=ExpressionTempVariableRef( variable=tmp_class_dict, source_ref=source_ref ), key=makeConstantRefNode( constant="__metaclass__", source_ref=source_ref, user_provided=True, ), source_ref=source_ref, ), expression_no=select_metaclass, source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariable( variable=tmp_class, source=makeExpressionCall( called=ExpressionTempVariableRef( variable=tmp_metaclass, source_ref=source_ref ), args=ExpressionMakeTuple( elements=( makeConstantRefNode( constant=node.name, source_ref=source_ref, user_provided=True, ), ExpressionTempVariableRef( variable=tmp_bases, source_ref=source_ref ), ExpressionTempVariableRef( variable=tmp_class_dict, source_ref=source_ref ), ), source_ref=source_ref, ), kw=None, source_ref=source_ref, ), source_ref=source_ref, ), ] for decorator in buildNodeList(provider, reversed(node.decorator_list), source_ref): statements.append( StatementAssignmentVariable( variable=tmp_class, source=makeExpressionCall( called=decorator, args=ExpressionMakeTuple( elements=( ExpressionTempVariableRef( variable=tmp_class, source_ref=source_ref ), ), source_ref=source_ref, ), kw=None, source_ref=decorator.getSourceReference(), ), source_ref=decorator.getSourceReference(), ) ) statements.append( StatementAssignmentVariableName( provider=provider, variable_name=mangleName(node.name, provider), source=ExpressionTempVariableRef(variable=tmp_class, source_ref=source_ref), source_ref=source_ref, ) ) final = ( StatementReleaseVariable(variable=tmp_class, source_ref=source_ref), StatementReleaseVariable(variable=tmp_bases, source_ref=source_ref), StatementReleaseVariable(variable=tmp_class_dict, source_ref=source_ref), StatementReleaseVariable(variable=tmp_metaclass, source_ref=source_ref), ) return makeTryFinallyStatement( provider=function_body, tried=statements, final=final, source_ref=source_ref )