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.

    # Note: The assign_provider is only to cover Python2 list contractions,
    # assigning one of the loop variables to the outside scope.
    if assign_provider:
        function_body = ExpressionOutlineBody(
            provider   = provider,
            name       = name,
            body       = None, # later
            source_ref = source_ref
        )

        iter_tmp = function_body.allocateTempVariable(
            temp_scope = None,
            name       = ".0"
        )
    else:
        function_body = ExpressionFunctionBody(
            provider   = provider,
            name       = name,
            doc        = None,
            parameters = ParameterSpec(
                name          = "contraction",
                normal_args   = (".0",),
                list_star_arg = None,
                dict_star_arg = None,
                default_count = 0,
                kw_only_args  = ()
            ),
            is_class   = False,
            source_ref = source_ref
        )

        iter_tmp = function_body.getVariableForAssignment(
            variable_name = ".0"
        )
        assert iter_tmp.isParameterVariable()

    if start_value is not None:
        container_tmp = function_body.allocateTempVariable(
            temp_scope = None,
            name       = "contraction_result"
        )
    else:
        container_tmp = None

    statements, release_statements = _buildContractionBodyNode(
        function_body   = function_body,
        assign_provider = assign_provider,
        provider        = provider,
        node            = node,
        emit_class      = emit_class,
        iter_tmp        = iter_tmp,
        temp_scope      = None,
        start_value     = start_value,
        container_tmp   = container_tmp,
        source_ref      = source_ref,
    )

    if start_value is not None:
        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 = StatementsFrame(
                statements    = mergeStatements(statements, False),
                guard_mode    = "pass_through"
                                  if emit_class is not ExpressionYield else
                                "generator",
                var_names     = (),
                arg_count     = 0,
                kw_only_count = 0,
                has_starlist  = False,
                has_stardict  = False,
                code_name     = "contraction",
                source_ref    = source_ref
            )
        )
    )

    if not assign_provider:
        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
        )
    else:
        return function_body
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.

    # Note: The assign_provider is only to cover Python2 list contractions,
    # assigning one of the loop variables to the outside scope.
    if assign_provider:
        function_body = ExpressionOutlineBody(
            provider=provider,
            name=name,
            body=None,  # later
            source_ref=source_ref)

        iter_tmp = function_body.allocateTempVariable(temp_scope=None,
                                                      name=".0")
    else:
        function_body = ExpressionFunctionBody(provider=provider,
                                               name=name,
                                               doc=None,
                                               parameters=ParameterSpec(
                                                   name="contraction",
                                                   normal_args=(".0", ),
                                                   list_star_arg=None,
                                                   dict_star_arg=None,
                                                   default_count=0,
                                                   kw_only_args=()),
                                               is_class=False,
                                               source_ref=source_ref)

        iter_tmp = function_body.getVariableForAssignment(variable_name=".0")
        assert iter_tmp.isParameterVariable()

    if start_value is not None:
        container_tmp = function_body.allocateTempVariable(
            temp_scope=None, name="contraction_result")
    else:
        container_tmp = None

    statements, release_statements = _buildContractionBodyNode(
        function_body=function_body,
        assign_provider=assign_provider,
        provider=provider,
        node=node,
        emit_class=emit_class,
        iter_tmp=iter_tmp,
        temp_scope=None,
        start_value=start_value,
        container_tmp=container_tmp,
        source_ref=source_ref,
    )

    if start_value is not None:
        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=StatementsFrame(
            statements=mergeStatements(statements, False),
            guard_mode="pass_through"
            if emit_class is not ExpressionYield else "generator",
            var_names=(),
            arg_count=0,
            kw_only_count=0,
            has_starlist=False,
            has_stardict=False,
            code_name="contraction",
            source_ref=source_ref)))

    if not assign_provider:
        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)
    else:
        return function_body