def buildExtSliceNode(provider, node, source_ref):
    elements = []

    for dim in node.slice.dims:
        dim_kind = getKind(dim)

        if dim_kind == "Slice":
            lower = buildNode(provider, dim.lower, source_ref, True)
            upper = buildNode(provider, dim.upper, source_ref, True)
            step = buildNode(provider, dim.step, source_ref, True)

            element = makeExpressionBuiltinSlice(start=lower,
                                                 stop=upper,
                                                 step=step,
                                                 source_ref=source_ref)
        elif dim_kind == "Ellipsis":
            element = ExpressionConstantEllipsisRef(source_ref=source_ref)
        elif dim_kind == "Index":
            element = buildNode(provider=provider,
                                node=dim.value,
                                source_ref=source_ref)
        else:
            assert False, dim

        elements.append(element)

    return makeExpressionMakeTupleOrConstant(elements=elements,
                                             user_provided=True,
                                             source_ref=source_ref)
示例#2
0
def buildSliceNode(provider, node, source_ref):
    """Python3.9 or higher, slice notations."""
    return makeExpressionBuiltinSlice(
        start=buildNode(provider, node.lower, source_ref, allow_none=True),
        stop=buildNode(provider, node.upper, source_ref, allow_none=True),
        step=buildNode(provider, node.step, source_ref, allow_none=True),
        source_ref=source_ref,
    )
def _buildInplaceAssignSliceNode(
    provider,
    lookup_source,
    lower,
    upper,
    tmp_variable1,
    tmp_variable2,
    tmp_variable3,
    tmp_variable4,
    operator,
    expression,
    source_ref,
):

    # Due to the 3 inputs, which we need to also put into temporary variables,
    # there are too many variables here, but they are needed.
    # pylint: disable=too-many-locals

    # First assign the target value, lower and upper to temporary variables.
    copy_to_tmp = StatementAssignmentVariable(variable=tmp_variable1,
                                              source=lookup_source,
                                              source_ref=source_ref)

    final_statements = [
        StatementReleaseVariable(variable=tmp_variable1, source_ref=source_ref)
    ]
    statements = []

    if lower is not None:
        statements.append(
            StatementAssignmentVariable(variable=tmp_variable2,
                                        source=lower,
                                        source_ref=source_ref))
        final_statements.append(
            StatementReleaseVariable(variable=tmp_variable2,
                                     source_ref=source_ref))

        lower_ref1 = ExpressionTempVariableRef(variable=tmp_variable2,
                                               source_ref=source_ref)
        lower_ref2 = ExpressionTempVariableRef(variable=tmp_variable2,
                                               source_ref=source_ref)
    else:
        assert tmp_variable2 is None

        lower_ref1 = lower_ref2 = None

    if upper is not None:
        statements.append(
            StatementAssignmentVariable(variable=tmp_variable3,
                                        source=upper,
                                        source_ref=source_ref))
        final_statements.append(
            StatementReleaseVariable(variable=tmp_variable3,
                                     source_ref=source_ref))

        upper_ref1 = ExpressionTempVariableRef(variable=tmp_variable3,
                                               source_ref=source_ref)
        upper_ref2 = ExpressionTempVariableRef(variable=tmp_variable3,
                                               source_ref=source_ref)
    else:
        assert tmp_variable3 is None

        upper_ref1 = upper_ref2 = None

    use_sliceobj = python_version >= 300

    # Second assign the in-place result over the original value.
    if use_sliceobj:
        statements += (
            StatementAssignmentVariable(
                variable=tmp_variable4,
                source=ExpressionSubscriptLookup(
                    expression=ExpressionTempVariableRef(
                        variable=tmp_variable1, source_ref=source_ref),
                    subscript=makeExpressionBuiltinSlice(
                        start=lower_ref2,
                        stop=upper_ref2,
                        step=None,
                        source_ref=source_ref,
                    ),
                    source_ref=source_ref,
                ),
                source_ref=source_ref,
            ),
            StatementAssignmentVariable(
                variable=tmp_variable4,
                source=makeExpressionOperationBinaryInplace(
                    operator=operator,
                    left=ExpressionTempVariableRef(variable=tmp_variable4,
                                                   source_ref=source_ref),
                    right=expression,
                    source_ref=source_ref,
                ),
                source_ref=source_ref,
            ),
            StatementAssignmentSubscript(
                expression=ExpressionTempVariableRef(variable=tmp_variable1,
                                                     source_ref=source_ref),
                subscript=makeExpressionBuiltinSlice(start=lower_ref1,
                                                     stop=upper_ref1,
                                                     step=None,
                                                     source_ref=source_ref),
                source=ExpressionTempVariableRef(variable=tmp_variable4,
                                                 source_ref=source_ref),
                source_ref=source_ref,
            ),
        )
    else:
        statements += (
            StatementAssignmentVariable(
                variable=tmp_variable4,
                source=ExpressionSliceLookup(
                    expression=ExpressionTempVariableRef(
                        variable=tmp_variable1, source_ref=source_ref),
                    lower=lower_ref2,
                    upper=upper_ref2,
                    source_ref=source_ref,
                ),
                source_ref=source_ref,
            ),
            StatementAssignmentVariable(
                variable=tmp_variable4,
                source=makeExpressionOperationBinaryInplace(
                    operator=operator,
                    left=ExpressionTempVariableRef(variable=tmp_variable4,
                                                   source_ref=source_ref),
                    right=expression,
                    source_ref=source_ref,
                ),
                source_ref=source_ref,
            ),
            StatementAssignmentSlice(
                expression=ExpressionTempVariableRef(variable=tmp_variable1,
                                                     source_ref=source_ref),
                lower=lower_ref1,
                upper=upper_ref1,
                source=ExpressionTempVariableRef(variable=tmp_variable4,
                                                 source_ref=source_ref),
                source_ref=source_ref,
            ),
        )

    final_statements.append(
        StatementReleaseVariable(variable=tmp_variable4,
                                 source_ref=source_ref))

    return (
        copy_to_tmp,
        makeTryFinallyStatement(
            provider=provider,
            tried=statements,
            final=final_statements,
            source_ref=source_ref,
        ),
    )
def buildDeleteStatementFromDecoded(provider, kind, detail, source_ref):
    if kind in ("Name", "Name_Exception"):
        # Note: Name_Exception is a "del" for exception handlers that doesn't
        # insist on the variable being defined, user code may do it too, and
        # that will be fine, so make that tolerant.
        return StatementDelVariableName(
            provider=provider,
            variable_name=detail,
            tolerant=kind == "Name_Exception",
            source_ref=source_ref,
        )
    elif kind == "Attribute":
        lookup_source, attribute_name = detail

        return StatementDelAttribute(
            expression=lookup_source,
            attribute_name=mangleName(attribute_name, provider),
            source_ref=source_ref,
        )
    elif kind == "Subscript":
        subscribed, subscript = detail

        return StatementDelSubscript(expression=subscribed,
                                     subscript=subscript,
                                     source_ref=source_ref)
    elif kind == "Slice":
        lookup_source, lower, upper = detail

        use_sliceobj = python_version >= 300

        if use_sliceobj:
            return StatementDelSubscript(
                expression=lookup_source,
                subscript=makeExpressionBuiltinSlice(start=lower,
                                                     stop=upper,
                                                     step=None,
                                                     source_ref=source_ref),
                source_ref=source_ref,
            )
        else:
            return StatementDelSlice(
                expression=lookup_source,
                lower=lower,
                upper=upper,
                source_ref=source_ref,
            )
    elif kind == "Tuple":
        result = []

        for sub_node in detail:
            result.append(
                buildDeleteStatementFromDecoded(
                    provider=provider,
                    kind=sub_node[0],
                    detail=sub_node[1],
                    source_ref=source_ref,
                ))

        return makeStatementsSequenceOrStatement(statements=result,
                                                 source_ref=source_ref)
    else:
        assert False, (kind, detail, source_ref)
def decodeAssignTarget(provider, node, source_ref, allow_none=False):
    # Many cases to deal with, because of the different assign targets,
    # pylint: disable=too-many-branches,too-many-return-statements

    if node is None and allow_none:
        return None

    if type(node) is str:
        return "Name", mangleName(node, provider)

    kind = getKind(node)

    if hasattr(node, "ctx"):
        assert getKind(node.ctx) in ("Store", "Del")

    if kind == "Name":
        return kind, mangleName(node.id, provider)
    elif kind == "Attribute":
        return kind, (buildNode(provider, node.value, source_ref), node.attr)
    elif kind == "Subscript":
        slice_kind = getKind(node.slice)

        if slice_kind == "Index":
            return (
                "Subscript",
                (
                    buildNode(provider, node.value, source_ref),
                    buildNode(provider, node.slice.value, source_ref),
                ),
            )
        elif slice_kind == "Slice":
            lower = buildNode(provider, node.slice.lower, source_ref, True)
            upper = buildNode(provider, node.slice.upper, source_ref, True)

            if node.slice.step is not None:
                step = buildNode(provider, node.slice.step, source_ref)

                return (
                    "Subscript",
                    (
                        buildNode(provider, node.value, source_ref),
                        makeExpressionBuiltinSlice(start=lower,
                                                   stop=upper,
                                                   step=step,
                                                   source_ref=source_ref),
                    ),
                )
            else:
                return (
                    "Slice",
                    (buildNode(provider, node.value,
                               source_ref), lower, upper),
                )
        elif slice_kind == "ExtSlice":
            return (
                "Subscript",
                (
                    buildNode(provider, node.value, source_ref),
                    buildExtSliceNode(provider, node, source_ref),
                ),
            )
        elif slice_kind == "Ellipsis":
            return (
                "Subscript",
                (
                    buildNode(provider, node.value, source_ref),
                    ExpressionConstantEllipsisRef(source_ref=source_ref),
                ),
            )
        elif python_version >= 390:
            return (
                "Subscript",
                (
                    buildNode(provider, node.value, source_ref),
                    buildNode(provider, node.slice, source_ref),
                ),
            )
        else:
            assert False, slice_kind
    elif kind in ("Tuple", "List"):
        return (
            "Tuple",
            tuple(
                decodeAssignTarget(
                    provider=provider,
                    node=sub_node,
                    source_ref=source_ref,
                    allow_none=False,
                ) for sub_node in node.elts),
        )
    elif kind == "Starred":
        return (
            "Starred",
            decodeAssignTarget(
                provider=provider,
                node=node.value,
                source_ref=source_ref,
                allow_none=False,
            ),
        )
    else:
        assert False, (source_ref, kind)
def buildAssignmentStatementsFromDecoded(provider, kind, detail, source,
                                         source_ref):
    # This is using many variable names on purpose, so as to give names to the
    # unpacked detail values, and has many branches due to the many cases
    # dealt with, pylint: disable=too-many-branches,too-many-locals,too-many-statements

    if kind == "Name":
        return StatementAssignmentVariableName(
            provider=provider,
            variable_name=detail,
            source=source,
            source_ref=source_ref,
        )
    elif kind == "Attribute":
        lookup_source, attribute_name = detail

        return StatementAssignmentAttribute(
            expression=lookup_source,
            attribute_name=mangleName(attribute_name, provider),
            source=source,
            source_ref=source_ref,
        )
    elif kind == "Subscript":
        subscribed, subscript = detail

        return StatementAssignmentSubscript(
            expression=subscribed,
            subscript=subscript,
            source=source,
            source_ref=source_ref,
        )
    elif kind == "Slice":
        lookup_source, lower, upper = detail

        # For Python3 there is no slicing operation, this is always done
        # with subscript using a slice object. For Python2, it is only done
        # if no "step" is provided.
        use_sliceobj = python_version >= 300

        if use_sliceobj:
            return StatementAssignmentSubscript(
                expression=lookup_source,
                source=source,
                subscript=makeExpressionBuiltinSlice(start=lower,
                                                     stop=upper,
                                                     step=None,
                                                     source_ref=source_ref),
                source_ref=source_ref,
            )

        else:
            return StatementAssignmentSlice(
                expression=lookup_source,
                lower=lower,
                upper=upper,
                source=source,
                source_ref=source_ref,
            )
    elif kind == "Tuple":
        temp_scope = provider.allocateTempScope("tuple_unpack")

        source_iter_var = provider.allocateTempVariable(temp_scope=temp_scope,
                                                        name="source_iter")

        element_vars = [
            provider.allocateTempVariable(temp_scope=temp_scope,
                                          name="element_%d" %
                                          (element_index + 1))
            for element_index in range(len(detail))
        ]

        starred_list_var = None
        starred_index = None

        statements = []

        for element_index, element in enumerate(detail):
            if element[0] == "Starred":
                if starred_index is not None:
                    raiseSyntaxError(
                        "two starred expressions in assignment"
                        if python_version < 390 else
                        "multiple starred expressions in assignment",
                        source_ref.atColumnNumber(0),
                    )

                starred_index = element_index

        for element_index, element in enumerate(detail):
            element_var = element_vars[element_index]

            if starred_list_var is not None:
                statements.insert(
                    starred_index + 1,
                    StatementAssignmentVariable(
                        variable=element_var,
                        source=ExpressionListOperationPop(
                            list_arg=ExpressionTempVariableRef(
                                variable=starred_list_var,
                                source_ref=source_ref),
                            source_ref=source_ref,
                        ),
                        source_ref=source_ref,
                    ),
                )
            elif element[0] != "Starred":
                statements.append(
                    StatementAssignmentVariable(
                        variable=element_var,
                        source=ExpressionSpecialUnpack(
                            value=ExpressionTempVariableRef(
                                variable=source_iter_var,
                                source_ref=source_ref),
                            count=element_index + 1,
                            expected=starred_index or len(detail),
                            starred=starred_index is not None,
                            source_ref=source_ref,
                        ),
                        source_ref=source_ref,
                    ))
            else:
                assert starred_index == element_index
                starred_list_var = element_var

                statements.append(
                    StatementAssignmentVariable(
                        variable=element_var,
                        source=ExpressionBuiltinList(
                            value=ExpressionTempVariableRef(
                                variable=source_iter_var,
                                source_ref=source_ref),
                            source_ref=source_ref,
                        ),
                        source_ref=source_ref,
                    ))

        if starred_list_var is None:
            statements.append(
                StatementSpecialUnpackCheck(
                    iterator=ExpressionTempVariableRef(
                        variable=source_iter_var, source_ref=source_ref),
                    count=len(detail),
                    source_ref=source_ref,
                ))
        else:
            statements.insert(
                starred_index + 1,
                makeStatementConditional(
                    condition=makeComparisonExpression(
                        comparator="Lt",
                        left=ExpressionBuiltinLen(
                            value=ExpressionTempVariableRef(
                                variable=starred_list_var,
                                source_ref=source_ref),
                            source_ref=source_ref,
                        ),
                        right=makeConstantRefNode(
                            constant=len(statements) - starred_index - 1,
                            source_ref=source_ref,
                        ),
                        source_ref=source_ref,
                    ),
                    yes_branch=makeRaiseExceptionExpressionFromTemplate(
                        exception_type="ValueError",
                        template="""\
not enough values to unpack (expected at least %d, got %%d)""" %
                        (len(statements) - 1),
                        template_args=makeBinaryOperationNode(
                            operator="Add",
                            left=ExpressionBuiltinLen(
                                value=ExpressionTempVariableRef(
                                    variable=starred_list_var,
                                    source_ref=source_ref),
                                source_ref=source_ref,
                            ),
                            right=makeConstantRefNode(constant=starred_index,
                                                      source_ref=source_ref),
                            source_ref=source_ref,
                        ),
                        source_ref=source_ref,
                    ).asStatement(),
                    no_branch=None,
                    source_ref=source_ref,
                ),
            )

        if python_version >= 370:
            iter_creation_class = ExpressionBuiltinIterForUnpack
        else:
            iter_creation_class = ExpressionBuiltinIter1

        statements = [
            StatementAssignmentVariable(
                variable=source_iter_var,
                source=iter_creation_class(value=source,
                                           source_ref=source_ref),
                source_ref=source_ref,
            ),
            makeTryFinallyStatement(
                provider=provider,
                tried=statements,
                final=(StatementReleaseVariable(variable=source_iter_var,
                                                source_ref=source_ref), ),
                source_ref=source_ref,
            ),
        ]

        # When all is done, copy over to the actual assignment targets, starred
        # or not makes no difference here anymore.
        for element_index, element in enumerate(detail):
            if element[0] == "Starred":
                element = element[1]

            element_var = element_vars[element_index]

            statements.append(
                buildAssignmentStatementsFromDecoded(
                    provider=provider,
                    kind=element[0],
                    detail=element[1],
                    source=ExpressionTempVariableRef(variable=element_var,
                                                     source_ref=source_ref),
                    source_ref=source_ref,
                ))

            # Need to release temporary variables right after successful
            # usage.
            statements.append(
                StatementDelVariable(variable=element_var,
                                     tolerant=True,
                                     source_ref=source_ref))

        final_statements = []

        for element_var in element_vars:
            final_statements.append(
                StatementReleaseVariable(variable=element_var,
                                         source_ref=source_ref))

        return makeTryFinallyStatement(
            provider=provider,
            tried=statements,
            final=final_statements,
            source_ref=source_ref,
        )
    elif kind == "Starred":
        raiseSyntaxError(
            "starred assignment target must be in a list or tuple",
            source_ref.atColumnNumber(0),
        )
    else:
        assert False, (kind, source_ref, detail)
示例#7
0
def buildSubscriptNode(provider, node, source_ref):
    # Subscript expression nodes, various types are dispatched here.

    assert getKind(node.ctx) == "Load", source_ref

    # The subscript "[]" operator is one of many different things. This is
    # expressed by this kind, there are "slice" lookups (two values, even if one
    # is using default), and then "index" lookups. The form with three argument
    # is really an "index" lookup, with a slice object. And the "..." lookup is
    # also an index loop-up, with it as the argument. So this splits things into
    # two different operations, "subscript" with a single "subscript" object. Or
    # a slice lookup with a lower and higher boundary. These things should
    # behave similar, but they are different slots.
    kind = getKind(node.slice)

    if kind == "Index":
        return ExpressionSubscriptLookup(
            expression=buildNode(provider, node.value, source_ref),
            subscript=buildNode(provider, node.slice.value, source_ref),
            source_ref=source_ref,
        )
    elif kind == "Slice":
        lower = buildNode(
            provider=provider,
            node=node.slice.lower,
            source_ref=source_ref,
            allow_none=True,
        )
        upper = buildNode(
            provider=provider,
            node=node.slice.upper,
            source_ref=source_ref,
            allow_none=True,
        )
        step = buildNode(
            provider=provider,
            node=node.slice.step,
            source_ref=source_ref,
            allow_none=True,
        )

        # For Python3 there is no slicing operation, this is always done
        # with subscript using a slice object. For Python2, it is only done
        # if no "step" is provided.
        use_sliceobj = step is not None or python_version >= 300

        if use_sliceobj:
            return ExpressionSubscriptLookup(
                expression=buildNode(provider, node.value, source_ref),
                subscript=makeExpressionBuiltinSlice(start=lower,
                                                     stop=upper,
                                                     step=step,
                                                     source_ref=source_ref),
                source_ref=source_ref,
            )
        else:
            return ExpressionSliceLookup(
                expression=buildNode(provider, node.value, source_ref),
                lower=lower,
                upper=upper,
                source_ref=source_ref,
            )
    elif kind == "ExtSlice":
        return ExpressionSubscriptLookup(
            expression=buildNode(provider, node.value, source_ref),
            subscript=buildExtSliceNode(provider, node, source_ref),
            source_ref=source_ref,
        )
    elif kind == "Ellipsis":
        return ExpressionSubscriptLookup(
            expression=buildNode(provider, node.value, source_ref),
            subscript=ExpressionConstantEllipsisRef(source_ref=source_ref),
            source_ref=source_ref,
        )
    elif python_version >= 390:
        return ExpressionSubscriptLookup(
            expression=buildNode(provider, node.value, source_ref),
            subscript=buildNode(provider, node.slice, source_ref),
            source_ref=source_ref,
        )
    else:
        assert False, kind