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
예제 #6
0
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
예제 #8
0
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)
예제 #10
0
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)
예제 #11
0
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,
    )
예제 #12
0
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
예제 #13
0
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
예제 #14
0
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
예제 #15
0
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
예제 #16
0
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
    )