Exemplo n.º 1
0
def convertFunctionCallToOutline(provider, function_body, values,
                                 call_source_ref):
    # This has got to have pretty man details, pylint: disable=too-many-locals
    function_source_ref = function_body.getSourceReference()

    outline_body = ExpressionOutlineBody(provider=provider,
                                         name="inline",
                                         source_ref=function_source_ref)

    # Make a clone first, so we do not harm other references.
    clone = function_body.subnode_body.makeClone()

    locals_scope_clone, variable_translation = function_body.locals_scope.makeClone(
        clone)

    # TODO: Lets update all at once maybe, it would take less visits.
    updateLocalsScope(
        clone,
        locals_scope=locals_scope_clone,
        variable_translation=variable_translation,
    )

    argument_names = function_body.getParameters().getParameterNames()
    assert len(argument_names) == len(values), (argument_names, values)

    statements = []

    for argument_name, value in zip(argument_names, values):
        statements.append(
            StatementAssignmentVariable(
                variable=variable_translation[argument_name],
                source=value,
                source_ref=call_source_ref,
            ))

    body = makeStatementsSequence(statements=(statements, clone),
                                  allow_none=False,
                                  source_ref=function_source_ref)

    auto_releases = function_body.getFunctionVariablesWithAutoReleases()

    # TODO: Not possible to auto release with outline bodies too?
    if auto_releases:
        releases = [
            StatementReleaseVariable(variable=variable,
                                     source_ref=function_source_ref)
            for variable in auto_releases
        ]

        body = makeTryFinallyStatement(
            provider=outline_body,
            tried=body,
            final=releases,
            source_ref=function_source_ref,
        )

    outline_body.setChild("body", body)

    return outline_body
Exemplo n.º 2
0
def buildNamedExprNode(provider, node, source_ref):
    """Assignment expressions, Python3.8 or higher only."""

    outline_body = ExpressionOutlineBody(provider=provider,
                                         name="assignment_expr",
                                         source_ref=source_ref)

    tmp_value = outline_body.allocateTempVariable(temp_scope=None,
                                                  name="value")

    value = buildNode(provider=provider,
                      node=node.value,
                      source_ref=source_ref)

    locals_owner = provider
    while locals_owner.isExpressionOutlineFunction():
        locals_owner = locals_owner.getParentVariableProvider()

    variable_name = node.target.id

    if (locals_owner.isExpressionGeneratorObjectBody()
            and locals_owner.name == "<genexpr>"):
        locals_owner.addNonlocalsDeclaration((variable_name, ),
                                             user_provided=False,
                                             source_ref=source_ref)

    statements = (
        StatementAssignmentVariable(variable=tmp_value,
                                    source=value,
                                    source_ref=source_ref),
        StatementAssignmentVariableName(
            provider=locals_owner,
            variable_name=variable_name,
            source=ExpressionTempVariableRef(variable=tmp_value,
                                             source_ref=source_ref),
            source_ref=source_ref,
        ),
        StatementReturn(
            expression=ExpressionTempVariableRef(variable=tmp_value,
                                                 source_ref=source_ref),
            source_ref=source_ref,
        ),
    )

    outline_body.setChild(
        "body",
        makeStatementsSequenceFromStatement(statement=makeTryFinallyStatement(
            provider=provider,
            tried=statements,
            final=StatementReleaseVariable(variable=tmp_value,
                                           source_ref=source_ref),
            source_ref=source_ref,
        )),
    )

    return outline_body
def _buildPython2ListContraction(provider, node, 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.
    function_body = ExpressionOutlineBody(
        provider=provider, name="list_contraction", source_ref=source_ref
    )

    iter_tmp = function_body.allocateTempVariable(temp_scope=None, name=".0")

    container_tmp = function_body.allocateTempVariable(
        temp_scope=None, name="contraction_result"
    )

    statements, release_statements = _buildContractionBodyNode(
        provider=provider,
        node=node,
        emit_class=StatementListOperationAppend,
        iter_tmp=iter_tmp,
        temp_scope=None,
        start_value=[],
        container_tmp=container_tmp,
        function_body=function_body,
        assign_provider=True,
        for_asyncgen=False,
        source_ref=source_ref,
    )

    statements.append(
        StatementReturn(
            expression=ExpressionTempVariableRef(
                variable=container_tmp, source_ref=source_ref
            ),
            source_ref=source_ref,
        )
    )

    statement = makeTryFinallyStatement(
        provider=function_body,
        tried=statements,
        final=release_statements,
        source_ref=source_ref.atInternal(),
    )

    function_body.setChild(
        "body", makeStatementsSequenceFromStatement(statement=statement)
    )

    return function_body
def buildCallNode(provider, node, source_ref):
    called = buildNode(provider, node.func, source_ref)

    if python_version >= 0x350:
        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 >= 0x350
            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 >= 0x350

            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 >= 0x350

            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),
                makeExpressionMakeTuple(
                    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,
                    ),
                    defaults=(),
                    kw_defaults=None,
                    annotations=None,
                    source_ref=source_ref,
                ),
                values=helper_args,
                source_ref=source_ref,
            )

            outline_body.setChild(
                "body",
                makeStatementsSequenceFromStatements(
                    StatementAssignmentVariable(
                        variable=tmp_called, 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 >= 0x350

        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 < 0x350:
        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 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
Exemplo n.º 6
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_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=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.getLocalsScope()

    # 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.setChild("body", 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(
                    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,
            ),
            makeTryFinallyStatement(
                provider,
                tried=StatementTry(
                    tried=makeStatementsSequenceFromStatement(
                        statement=StatementReturn(
                            expression=makeExpressionAttributeLookup(
                                expression=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.setChild(
        "body",
        makeStatementsSequence(statements=statements,
                               allow_none=False,
                               source_ref=source_ref),
    )

    statements = [
        StatementAssignmentVariable(
            variable=tmp_bases,
            source=makeExpressionMakeTupleOrConstant(
                elements=buildNodeList(provider=provider,
                                       nodes=node.bases,
                                       source_ref=source_ref),
                user_provided=True,
                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=ExpressionDictOperationGet2(
                    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=makeExpressionMakeTuple(
                    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=makeExpressionMakeTuple(
                        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)
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_freevars=(),
        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 >= 0x370:
        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.setChild(
        "body",
        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.setChild(
        "body",
        makeStatementsSequenceFromStatement(
            statement=StatementsFrameGenerator(
                statements=mergeStatements(statements, False),
                code_object=code_object,
                source_ref=source_ref,
            )
        ),
    )

    return function_body