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,
        )
    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,
        )
def _makeTryExceptSingleHandlerNode(provider, public_exc, tried,
                                    exception_name, handler_body, source_ref):
    # No need to create this in the first place if nothing is tried.
    if tried is None:
        return None

    if public_exc:
        preserver_id = provider.allocatePreserverId()

        handling = [
            StatementPreserveFrameException(preserver_id=preserver_id,
                                            source_ref=source_ref),
            StatementPublishException(source_ref=source_ref),
        ]
    else:
        handling = []

    if not handler_body.isStatementsSequence():
        handler_body = makeStatementsSequenceFromStatement(
            statement=handler_body)

    if not tried.isStatementsSequence():
        tried = makeStatementsSequenceFromStatement(statement=tried)

    handling.append(
        makeStatementConditional(
            condition=ExpressionComparisonExceptionMatch(
                left=ExpressionCaughtExceptionTypeRef(source_ref=source_ref),
                right=ExpressionBuiltinExceptionRef(
                    exception_name=exception_name, source_ref=source_ref),
                source_ref=source_ref,
            ),
            yes_branch=handler_body,
            no_branch=makeReraiseExceptionStatement(source_ref=source_ref),
            source_ref=source_ref,
        ))

    if python_version >= 0x300 and public_exc:
        handling = (makeTryFinallyStatement(
            provider=provider,
            tried=handling,
            final=StatementRestoreFrameException(
                preserver_id=preserver_id, source_ref=source_ref.atInternal()),
            source_ref=source_ref.atInternal(),
        ), )

    handling = makeStatementsSequenceFromStatements(*handling)

    return StatementTry(
        tried=tried,
        except_handler=handling,
        break_handler=None,
        continue_handler=None,
        return_handler=None,
        source_ref=source_ref,
    )
def makeTryExceptNoRaise(provider, temp_scope, tried, handling, no_raise,
                         source_ref):
    # This helper executes the core re-formulation of "no_raise" blocks, which
    # are the "else" blocks of "try"/"except" statements. In order to limit the
    # execution, we use an indicator variable instead, which will signal that
    # the tried block executed up to the end. And then we make the else block be
    # a conditional statement checking that.

    # Indicator variable, will end up with C bool type, and need not be released.
    tmp_handler_indicator_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="unhandled_indicator", temp_type="bool")

    statements = mergeStatements(
        (
            StatementAssignmentVariable(
                variable=tmp_handler_indicator_variable,
                source=makeConstantRefNode(constant=False,
                                           source_ref=source_ref),
                source_ref=no_raise.getSourceReference(),
            ),
            handling,
        ),
        allow_none=True,
    )

    handling = StatementsSequence(statements=statements, source_ref=source_ref)

    return makeStatementsSequenceFromStatements(
        StatementAssignmentVariable(
            variable=tmp_handler_indicator_variable,
            source=makeConstantRefNode(constant=True, source_ref=source_ref),
            source_ref=source_ref,
        ),
        StatementTry(
            tried=tried,
            except_handler=handling,
            break_handler=None,
            continue_handler=None,
            return_handler=None,
            source_ref=source_ref,
        ),
        makeStatementConditional(
            condition=ExpressionComparisonIs(
                left=ExpressionTempVariableRef(
                    variable=tmp_handler_indicator_variable,
                    source_ref=source_ref),
                right=makeConstantRefNode(constant=True,
                                          source_ref=source_ref),
                source_ref=source_ref,
            ),
            yes_branch=no_raise,
            no_branch=None,
            source_ref=source_ref,
        ),
    )
Ejemplo n.º 5
0
def buildConditionNode(provider, node, source_ref):
    # Conditional statements may have one or two branches. We will never see an
    # "elif", because that's already dealt with by module "ast", which turns it
    # into nested conditional statements.

    return makeStatementConditional(
        condition=buildNode(provider, node.test, source_ref),
        yes_branch=buildStatementsNode(provider=provider,
                                       nodes=node.body,
                                       source_ref=source_ref),
        no_branch=buildStatementsNode(
            provider=provider,
            nodes=node.orelse if node.orelse else None,
            source_ref=source_ref),
        source_ref=source_ref)
def buildAssertNode(provider, node, source_ref):
    # Build assert statements. These are re-formulated as described in the
    # developer manual too. They end up as conditional statement with raises of
    # AssertionError exceptions.

    # Underlying assumption:
    #
    # Assert x, y is the same as:
    # if not x:
    #     raise AssertionError, y

    # Therefore assert statements are really just conditional statements with a
    # static raise contained.
    #

    exception_value = buildNode(provider, node.msg, source_ref, True)

    if "no_asserts" in getPythonFlags():
        return None

    if exception_value is not None and python_version > 272:
        exception_value = ExpressionMakeTuple(
            elements=(exception_value,), source_ref=source_ref
        )

    raise_statement = StatementRaiseException(
        exception_type=ExpressionBuiltinExceptionRef(
            exception_name="AssertionError", source_ref=source_ref
        ),
        exception_value=exception_value,
        exception_trace=None,
        exception_cause=None,
        source_ref=source_ref,
    )

    return makeStatementConditional(
        condition=ExpressionOperationNot(
            operand=buildNode(provider, node.test, source_ref), source_ref=source_ref
        ),
        yes_branch=raise_statement,
        no_branch=None,
        source_ref=source_ref,
    )
def buildAssertNode(provider, node, source_ref):
    # Build assert statements. These are re-formulated as described in the
    # developer manual too. They end up as conditional statement with raises of
    # AssertionError exceptions.

    # Underlying assumption:
    #
    # Assert x, y is the same as:
    # if not x:
    #     raise AssertionError, y

    # Therefore assert statements are really just conditional statements with a
    # static raise contained.
    #

    exception_value = buildNode(provider, node.msg, source_ref, True)

    if "no_asserts" in getPythonFlags():
        return None

    if exception_value is not None and python_version > 272:
        exception_value = ExpressionMakeTuple(
            elements=(exception_value,), source_ref=source_ref
        )

    raise_statement = StatementRaiseException(
        exception_type=ExpressionBuiltinExceptionRef(
            exception_name="AssertionError", source_ref=source_ref
        ),
        exception_value=exception_value,
        exception_trace=None,
        exception_cause=None,
        source_ref=source_ref,
    )

    return makeStatementConditional(
        condition=ExpressionOperationNOT(
            operand=buildNode(provider, node.test, source_ref), source_ref=source_ref
        ),
        yes_branch=raise_statement,
        no_branch=None,
        source_ref=source_ref,
    )
Ejemplo n.º 8
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_variable = class_creation_function.getVariableForAssignment("__class__")

    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_argcount=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.getFunctionLocalsScope()

    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=makeConstantRefNode(
                constant=provider.getParentModule().getFullName(),
                source_ref=source_ref,
                user_provided=True,
            ),
            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 Python 3.3.
    if python_version >= 300:
        qualname = class_creation_function.getFunctionQualname()

        if python_version < 340:
            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 >= 340:
            qualname_assign = statements[-1]

    if python_version >= 360 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 >= 370:
            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 >= 370 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=makeSequenceCreationOrConstant(
                    sequence_kind="tuple",
                    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.setBody(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=ExpressionMakeTuple(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 < 370 else tmp_bases_orig,
                source=buildTupleCreationNode(
                    provider=provider, elements=node.bases, source_ref=source_ref
                ),
                source_ref=source_ref,
            )
        )

        if python_version >= 370:
            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(
                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,
        )

        # Might become empty behind our back during conversion, therefore make the
        # check at run time for 3.7 or higher.
        if python_version >= 370:
            unspecified_metaclass_expression = ExpressionConditional(
                condition=ExpressionTempVariableRef(
                    variable=tmp_bases, source_ref=source_ref
                ),
                expression_yes=unspecified_metaclass_expression,
                expression_no=makeExpressionBuiltinRef(
                    builtin_name="type", source_ref=source_ref
                ),
                source_ref=source_ref,
            )
    else:
        unspecified_metaclass_expression = makeExpressionBuiltinRef(
            builtin_name="type", source_ref=source_ref
        )

    call_prepare = StatementAssignmentVariable(
        variable=tmp_prepared,
        source=makeExpressionCall(
            called=ExpressionAttributeLookup(
                source=ExpressionTempVariableRef(
                    variable=tmp_metaclass, source_ref=source_ref
                ),
                attribute_name="__prepare__",
                source_ref=source_ref,
            ),
            args=ExpressionMakeTuple(
                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 >= 360:
        call_prepare = makeStatementsSequenceFromStatements(
            call_prepare,
            makeStatementConditional(
                condition=ExpressionAttributeCheck(
                    object_arg=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(
                            object_arg=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(
                            source=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(
                object_arg=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 >= 340:
        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 >= 370:
            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,
    )
Ejemplo n.º 9
0
    def wrapEvalBuiltin(source, globals_arg, locals_arg, source_ref):
        provider = node.getParentVariableProvider()

        outline_body = ExpressionOutlineBody(
            provider=node.getParentVariableProvider(),
            name="eval_call",
            source_ref=source_ref,
        )

        globals_ref, locals_ref, tried, final = wrapEvalGlobalsAndLocals(
            provider=provider,
            globals_node=globals_arg,
            locals_node=locals_arg,
            temp_scope=outline_body.getOutlineTempScope(),
            source_ref=source_ref,
        )

        # The wrapping should not relocate to the "source_ref".
        assert (
            globals_arg is None
            or globals_ref.getSourceReference() == globals_arg.getSourceReference()
        )
        assert (
            locals_arg is None
            or locals_ref.getSourceReference() == locals_arg.getSourceReference()
        )

        source_variable = outline_body.allocateTempVariable(
            temp_scope=None, name="source"
        )

        final.setStatements(
            final.getStatements()
            + (
                StatementDelVariable(
                    variable=source_variable, tolerant=True, source_ref=source_ref
                ),
            )
        )

        strip_choice = makeConstantRefNode(constant=(" \t",), source_ref=source_ref)

        if python_version >= 300:
            strip_choice = ExpressionConditional(
                condition=ExpressionComparisonIs(
                    left=ExpressionBuiltinType1(
                        value=ExpressionTempVariableRef(
                            variable=source_variable, source_ref=source_ref
                        ),
                        source_ref=source_ref,
                    ),
                    right=makeExpressionBuiltinRef(
                        builtin_name="bytes", source_ref=source_ref
                    ),
                    source_ref=source_ref,
                ),
                expression_yes=makeConstantRefNode(
                    constant=(b" \t",), source_ref=source_ref
                ),
                expression_no=strip_choice,
                source_ref=source_ref,
            )

        # Source needs some special treatment for eval, if it's a string, it
        # must be stripped.
        string_fixup = StatementAssignmentVariable(
            variable=source_variable,
            source=makeExpressionCall(
                called=ExpressionAttributeLookup(
                    source=ExpressionTempVariableRef(
                        variable=source_variable, source_ref=source_ref
                    ),
                    attribute_name="strip",
                    source_ref=source_ref,
                ),
                args=strip_choice,  # This is a tuple
                kw=None,
                source_ref=source_ref,
            ),
            source_ref=source_ref,
        )

        acceptable_builtin_types = [
            ExpressionBuiltinAnonymousRef(builtin_name="code", source_ref=source_ref)
        ]

        if python_version >= 270:
            acceptable_builtin_types.append(
                makeExpressionBuiltinRef(
                    builtin_name="memoryview", source_ref=source_ref
                )
            )

        statements = (
            StatementAssignmentVariable(
                variable=source_variable, source=source, source_ref=source_ref
            ),
            makeStatementConditional(
                condition=ExpressionOperationNOT(
                    operand=ExpressionBuiltinIsinstance(
                        instance=ExpressionTempVariableRef(
                            variable=source_variable, source_ref=source_ref
                        ),
                        classes=makeSequenceCreationOrConstant(
                            sequence_kind="tuple",
                            elements=acceptable_builtin_types,
                            source_ref=source_ref,
                        ),
                        source_ref=source_ref,
                    ),
                    source_ref=source_ref,
                ),
                yes_branch=string_fixup,
                no_branch=None,
                source_ref=source_ref,
            ),
            StatementReturn(
                expression=ExpressionBuiltinEval(
                    source_code=ExpressionTempVariableRef(
                        variable=source_variable, source_ref=source_ref
                    ),
                    globals_arg=globals_ref,
                    locals_arg=locals_ref,
                    source_ref=source_ref,
                ),
                source_ref=source_ref,
            ),
        )

        tried = makeStatementsSequence(
            statements=(tried,) + statements, allow_none=False, source_ref=source_ref
        )

        outline_body.setBody(
            makeStatementsSequenceFromStatement(
                statement=makeTryFinallyStatement(
                    provider=outline_body,
                    tried=tried,
                    final=final,
                    source_ref=source_ref,
                )
            )
        )

        return outline_body
def _buildForLoopNode(provider, node, sync, source_ref):
    # The for loop is re-formulated according to developer manual. An iterator
    # is created, and looped until it gives StopIteration. The else block is
    # taken if a for loop exits normally, i.e. because of iterator
    # exhaustion. We do this by introducing an indicator variable.

    # We handle async and sync both here, leading to cases, pylint: disable=too-many-locals

    source = buildNode(provider, node.iter, source_ref)

    # Temporary variables, we need one for the iterator, and one for the current
    # value.
    temp_scope = provider.allocateTempScope("for_loop")

    tmp_iter_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="for_iterator"
    )
    tmp_value_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="iter_value"
    )

    else_block = buildStatementsNode(
        provider=provider,
        nodes=node.orelse if node.orelse else None,
        source_ref=source_ref,
    )

    if else_block is not None:
        tmp_break_indicator = provider.allocateTempVariable(
            temp_scope=temp_scope, name="break_indicator"
        )

        statements = [
            StatementAssignmentVariable(
                variable=tmp_break_indicator,
                source=makeConstantRefNode(constant=True, source_ref=source_ref),
                source_ref=source_ref,
            )
        ]
    else:
        statements = []

    statements.append(StatementLoopBreak(source_ref=source_ref))

    handler_body = makeStatementsSequence(
        statements=statements, allow_none=False, source_ref=source_ref
    )

    if sync:
        next_node = ExpressionBuiltinNext1(
            value=ExpressionTempVariableRef(
                variable=tmp_iter_variable, source_ref=source_ref
            ),
            source_ref=source_ref,
        )
    else:
        next_node = ExpressionYieldFromWaitable(
            expression=ExpressionAsyncNext(
                value=ExpressionTempVariableRef(
                    variable=tmp_iter_variable, source_ref=source_ref
                ),
                source_ref=source_ref,
            ),
            source_ref=source_ref,
        )

    statements = (
        makeTryExceptSingleHandlerNode(
            tried=StatementAssignmentVariable(
                variable=tmp_value_variable, source=next_node, source_ref=source_ref
            ),
            exception_name="StopIteration" if sync else "StopAsyncIteration",
            handler_body=handler_body,
            source_ref=source_ref,
        ),
        buildAssignmentStatements(
            provider=provider,
            node=node.target,
            source=ExpressionTempVariableRef(
                variable=tmp_value_variable, source_ref=source_ref
            ),
            source_ref=source_ref,
        ),
    )

    pushBuildContext("loop_body")
    statements += (
        buildStatementsNode(provider=provider, nodes=node.body, source_ref=source_ref),
    )
    popBuildContext()

    loop_body = makeStatementsSequence(
        statements=statements, allow_none=True, source_ref=source_ref
    )

    cleanup_statements = [
        StatementReleaseVariable(variable=tmp_value_variable, source_ref=source_ref),
        StatementReleaseVariable(variable=tmp_iter_variable, source_ref=source_ref),
    ]

    if else_block is not None:
        statements = [
            StatementAssignmentVariable(
                variable=tmp_break_indicator,
                source=makeConstantRefNode(constant=False, source_ref=source_ref),
                source_ref=source_ref,
            )
        ]
    else:
        statements = []

    if sync:
        iter_source = ExpressionBuiltinIter1(
            value=source, source_ref=source.getSourceReference()
        )
    else:
        iter_source = ExpressionYieldFromWaitable(
            expression=ExpressionAsyncIter(
                value=source, source_ref=source.getSourceReference()
            ),
            source_ref=source.getSourceReference(),
        )

    statements += [
        # First create the iterator and store it.
        StatementAssignmentVariable(
            variable=tmp_iter_variable, source=iter_source, source_ref=source_ref
        ),
        makeTryFinallyStatement(
            provider=provider,
            tried=StatementLoop(body=loop_body, source_ref=source_ref),
            final=StatementsSequence(
                statements=cleanup_statements, source_ref=source_ref
            ),
            source_ref=source_ref,
        ),
    ]

    if else_block is not None:
        statements += [
            makeStatementConditional(
                condition=ExpressionComparisonIs(
                    left=ExpressionTempVariableRef(
                        variable=tmp_break_indicator, source_ref=source_ref
                    ),
                    right=makeConstantRefNode(constant=True, source_ref=source_ref),
                    source_ref=source_ref,
                ),
                yes_branch=else_block,
                no_branch=None,
                source_ref=source_ref,
            )
        ]

        statements = (
            makeTryFinallyStatement(
                provider=provider,
                tried=statements,
                final=StatementReleaseVariable(
                    variable=tmp_break_indicator, source_ref=source_ref
                ),
                source_ref=source_ref,
            ),
        )

    return makeStatementsSequenceFromStatements(*statements)
def buildTryExceptionNode(provider, node, source_ref):
    # Try/except nodes. Re-formulated as described in the developer
    # manual. Exception handlers made the assignment to variables explicit. Same
    # for the "del" as done for Python3. Also catches always work a tuple of
    # exception types and hides away that they may be built or not.

    # Many variables and branches, due to the re-formulation that is going on
    # here, which just has the complexity, pylint: disable=too-many-branches,too-many-locals

    tried = buildStatementsNode(
        provider=provider, nodes=node.body, source_ref=source_ref
    )

    handlers = []

    for handler in node.handlers:
        exception_expression, exception_assign, exception_block = (
            handler.type,
            handler.name,
            handler.body,
        )

        if exception_assign is None:
            statements = [
                buildStatementsNode(
                    provider=provider, nodes=exception_block, source_ref=source_ref
                )
            ]
        elif python_version < 300:
            statements = [
                buildAssignmentStatements(
                    provider=provider,
                    node=exception_assign,
                    source=ExpressionCaughtExceptionValueRef(
                        source_ref=source_ref.atInternal()
                    ),
                    source_ref=source_ref.atInternal(),
                ),
                buildStatementsNode(
                    provider=provider, nodes=exception_block, source_ref=source_ref
                ),
            ]
        else:
            # Python3 requires temporary assignment of exception assignment.
            target_info = decodeAssignTarget(
                provider=provider, node=exception_assign, source_ref=source_ref
            )

            kind, detail = target_info

            assert kind == "Name", kind
            kind = "Name_Exception"

            statements = [
                buildAssignmentStatements(
                    provider=provider,
                    node=exception_assign,
                    source=ExpressionCaughtExceptionValueRef(
                        source_ref=source_ref.atInternal()
                    ),
                    source_ref=source_ref.atInternal(),
                ),
                makeTryFinallyStatement(
                    provider=provider,
                    tried=buildStatementsNode(
                        provider=provider, nodes=exception_block, source_ref=source_ref
                    ),
                    final=buildDeleteStatementFromDecoded(
                        provider=provider,
                        kind=kind,
                        detail=detail,
                        source_ref=source_ref,
                    ),
                    source_ref=source_ref,
                ),
            ]

        handler_body = makeStatementsSequence(
            statements=statements, allow_none=True, source_ref=source_ref
        )

        exception_types = buildNode(
            provider=provider,
            node=exception_expression,
            source_ref=source_ref,
            allow_none=True,
        )

        # The exception types should be a tuple, so as to be most general.
        if exception_types is None:
            if handler is not node.handlers[-1]:
                raiseSyntaxError(
                    "default 'except:' must be last",
                    source_ref.atLineNumber(handler.lineno).atColumnNumber(
                        handler.col_offset
                    ),
                )

        handlers.append((exception_types, handler_body))

    # Re-raise by default
    exception_handling = makeReraiseExceptionStatement(source_ref=source_ref)

    for exception_type, handler in reversed(handlers):
        if exception_type is None:
            # A default handler was given, so use that indeed.
            exception_handling = handler
        else:
            exception_handling = StatementsSequence(
                statements=(
                    makeStatementConditional(
                        condition=ExpressionComparisonExceptionMatch(
                            left=ExpressionCaughtExceptionTypeRef(
                                source_ref=exception_type.source_ref
                            ),
                            right=exception_type,
                            source_ref=exception_type.source_ref,
                        ),
                        yes_branch=handler,
                        no_branch=exception_handling,
                        source_ref=exception_type.source_ref,
                    ),
                ),
                source_ref=exception_type.source_ref,
            )

    if exception_handling is None:
        # For Python3, we need not publish at all, if all we do is to revert
        # that immediately. For Python2, the publish may release previously
        # published exception, which has side effects potentially.
        if python_version < 300:
            exception_handling = StatementsSequence(
                statements=(
                    StatementPreserveFrameException(
                        preserver_id=0,  # unused with Python2
                        source_ref=source_ref.atInternal(),
                    ),
                    StatementPublishException(source_ref=source_ref.atInternal()),
                ),
                source_ref=source_ref.atInternal(),
            )
    else:
        if python_version < 300:
            exception_handling.setStatements(
                (
                    StatementPreserveFrameException(
                        preserver_id=0,  # unused with Python2
                        source_ref=source_ref.atInternal(),
                    ),
                    StatementPublishException(source_ref=source_ref.atInternal()),
                )
                + exception_handling.getStatements()
            )
        else:
            preserver_id = provider.allocatePreserverId()

            exception_handling = makeStatementsSequenceFromStatements(
                StatementPreserveFrameException(
                    preserver_id=preserver_id, source_ref=source_ref.atInternal()
                ),
                StatementPublishException(source_ref=source_ref.atInternal()),
                makeTryFinallyStatement(
                    provider=provider,
                    tried=exception_handling,
                    final=StatementRestoreFrameException(
                        preserver_id=preserver_id, source_ref=source_ref.atInternal()
                    ),
                    source_ref=source_ref,
                ),
            )

    no_raise = buildStatementsNode(
        provider=provider, nodes=node.orelse, source_ref=source_ref
    )

    if no_raise is None:
        if tried is None:
            return None

        return StatementTry(
            tried=tried,
            except_handler=exception_handling,
            break_handler=None,
            continue_handler=None,
            return_handler=None,
            source_ref=source_ref,
        )
    else:
        if tried is None:
            return no_raise

        return makeTryExceptNoRaise(
            provider=provider,
            temp_scope=provider.allocateTempScope("try_except"),
            handling=exception_handling,
            tried=tried,
            no_raise=no_raise,
            source_ref=source_ref,
        )
Ejemplo n.º 12
0
    def wrapEvalBuiltin(source, globals_arg, locals_arg, source_ref):
        provider = node.getParentVariableProvider()

        outline_body = ExpressionOutlineBody(
            provider=node.getParentVariableProvider(),
            name="eval_call",
            source_ref=source_ref,
        )

        globals_ref, locals_ref, tried, final = wrapEvalGlobalsAndLocals(
            provider=provider,
            globals_node=globals_arg,
            locals_node=locals_arg,
            temp_scope=outline_body.getOutlineTempScope(),
            source_ref=source_ref,
        )

        # The wrapping should not relocate to the "source_ref".
        assert (globals_arg is None or globals_ref.getSourceReference()
                == globals_arg.getSourceReference())
        assert (locals_arg is None or locals_ref.getSourceReference()
                == locals_arg.getSourceReference())

        source_variable = outline_body.allocateTempVariable(temp_scope=None,
                                                            name="source")

        final.setStatements(final.getStatements() + (StatementDelVariable(
            variable=source_variable, tolerant=True, source_ref=source_ref), ))

        strip_choice = makeConstantRefNode(constant=(" \t", ),
                                           source_ref=source_ref)

        if python_version >= 300:
            strip_choice = ExpressionConditional(
                condition=ExpressionComparisonIs(
                    left=ExpressionBuiltinType1(
                        value=ExpressionTempVariableRef(
                            variable=source_variable, source_ref=source_ref),
                        source_ref=source_ref,
                    ),
                    right=makeExpressionBuiltinRef(builtin_name="bytes",
                                                   source_ref=source_ref),
                    source_ref=source_ref,
                ),
                expression_yes=makeConstantRefNode(constant=(b" \t", ),
                                                   source_ref=source_ref),
                expression_no=strip_choice,
                source_ref=source_ref,
            )

        # Source needs some special treatment for eval, if it's a string, it
        # must be stripped.
        string_fixup = StatementAssignmentVariable(
            variable=source_variable,
            source=makeExpressionCall(
                called=ExpressionAttributeLookup(
                    source=ExpressionTempVariableRef(variable=source_variable,
                                                     source_ref=source_ref),
                    attribute_name="strip",
                    source_ref=source_ref,
                ),
                args=strip_choice,  # This is a tuple
                kw=None,
                source_ref=source_ref,
            ),
            source_ref=source_ref,
        )

        acceptable_builtin_types = [
            ExpressionBuiltinAnonymousRef(builtin_name="code",
                                          source_ref=source_ref)
        ]

        if python_version >= 270:
            acceptable_builtin_types.append(
                makeExpressionBuiltinRef(builtin_name="memoryview",
                                         source_ref=source_ref))

        statements = (
            StatementAssignmentVariable(variable=source_variable,
                                        source=source,
                                        source_ref=source_ref),
            makeStatementConditional(
                condition=ExpressionOperationNOT(
                    operand=ExpressionBuiltinIsinstance(
                        instance=ExpressionTempVariableRef(
                            variable=source_variable, source_ref=source_ref),
                        classes=makeSequenceCreationOrConstant(
                            sequence_kind="tuple",
                            elements=acceptable_builtin_types,
                            source_ref=source_ref,
                        ),
                        source_ref=source_ref,
                    ),
                    source_ref=source_ref,
                ),
                yes_branch=string_fixup,
                no_branch=None,
                source_ref=source_ref,
            ),
            StatementReturn(
                expression=ExpressionBuiltinEval(
                    source_code=ExpressionTempVariableRef(
                        variable=source_variable, source_ref=source_ref),
                    globals_arg=globals_ref,
                    locals_arg=locals_ref,
                    source_ref=source_ref,
                ),
                source_ref=source_ref,
            ),
        )

        tried = makeStatementsSequence(statements=(tried, ) + statements,
                                       allow_none=False,
                                       source_ref=source_ref)

        outline_body.setBody(
            makeStatementsSequenceFromStatement(
                statement=makeTryFinallyStatement(
                    provider=outline_body,
                    tried=tried,
                    final=final,
                    source_ref=source_ref,
                )))

        return outline_body
Ejemplo n.º 13
0
def wrapEvalGlobalsAndLocals(provider, globals_node, locals_node, temp_scope,
                             source_ref):
    """ Wrap the locals and globals arguments for "eval".

        This is called from the outside, and when the node tree
        already exists.
    """

    globals_keeper_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="globals")

    locals_keeper_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="locals")

    if locals_node is None:
        locals_node = ExpressionConstantNoneRef(source_ref=source_ref)

    if globals_node is None:
        globals_node = ExpressionConstantNoneRef(source_ref=source_ref)

    post_statements = []

    if provider.isExpressionClassBody():
        post_statements.append(
            StatementLocalsDictSync(
                locals_arg=ExpressionTempVariableRef(
                    variable=locals_keeper_variable, source_ref=source_ref),
                source_ref=source_ref.atInternal(),
            ))

    post_statements += [
        StatementReleaseVariable(variable=globals_keeper_variable,
                                 source_ref=source_ref),
        StatementReleaseVariable(variable=locals_keeper_variable,
                                 source_ref=source_ref),
    ]

    # The locals default is dependent on exec_mode, globals or locals.
    locals_default = ExpressionConditional(
        condition=ExpressionComparisonIs(
            left=ExpressionTempVariableRef(variable=globals_keeper_variable,
                                           source_ref=source_ref),
            right=ExpressionConstantNoneRef(source_ref=source_ref),
            source_ref=source_ref,
        ),
        expression_no=ExpressionTempVariableRef(
            variable=globals_keeper_variable, source_ref=source_ref),
        expression_yes=makeExpressionBuiltinLocals(provider=provider,
                                                   source_ref=source_ref),
        source_ref=source_ref,
    )

    pre_statements = [
        # First assign globals and locals temporary the values given.
        StatementAssignmentVariable(variable=globals_keeper_variable,
                                    source=globals_node,
                                    source_ref=source_ref),
        StatementAssignmentVariable(variable=locals_keeper_variable,
                                    source=locals_node,
                                    source_ref=source_ref),
        makeStatementConditional(
            condition=ExpressionComparisonIs(
                left=ExpressionTempVariableRef(variable=locals_keeper_variable,
                                               source_ref=source_ref),
                right=ExpressionConstantNoneRef(source_ref=source_ref),
                source_ref=source_ref,
            ),
            yes_branch=StatementAssignmentVariable(
                variable=locals_keeper_variable,
                source=locals_default,
                source_ref=source_ref,
            ),
            no_branch=None,
            source_ref=source_ref,
        ),
        makeStatementConditional(
            condition=ExpressionComparisonIs(
                left=ExpressionTempVariableRef(
                    variable=globals_keeper_variable, source_ref=source_ref),
                right=ExpressionConstantNoneRef(source_ref=source_ref),
                source_ref=source_ref,
            ),
            yes_branch=StatementAssignmentVariable(
                variable=globals_keeper_variable,
                source=ExpressionBuiltinGlobals(source_ref=source_ref),
                source_ref=source_ref,
            ),
            no_branch=None,
            source_ref=source_ref,
        ),
    ]

    return (
        ExpressionTempVariableRef(
            variable=globals_keeper_variable,
            source_ref=source_ref
            if globals_node is None else globals_node.getSourceReference(),
        ),
        ExpressionTempVariableRef(
            variable=locals_keeper_variable,
            source_ref=source_ref
            if locals_node is None else locals_node.getSourceReference(),
        ),
        makeStatementsSequence(pre_statements, False, source_ref),
        makeStatementsSequence(post_statements, False, source_ref),
    )
Ejemplo n.º 14
0
def buildWhileLoopNode(provider, node, source_ref):
    # The while loop is re-formulated according to developer manual. The
    # condition becomes an early condition to break the loop. The else block is
    # taken if a while loop exits normally, i.e. because of condition not being
    # true. We do this by introducing an indicator variable.

    else_block = buildStatementsNode(
        provider=provider,
        nodes=node.orelse if node.orelse else None,
        source_ref=source_ref,
    )

    if else_block is not None:
        temp_scope = provider.allocateTempScope("while_loop")

        tmp_break_indicator = provider.allocateTempVariable(
            temp_scope=temp_scope, name="break_indicator"
        )

        statements = (
            StatementAssignmentVariable(
                variable=tmp_break_indicator,
                source=makeConstantRefNode(constant=True, source_ref=source_ref),
                source_ref=source_ref,
            ),
            StatementLoopBreak(source_ref=source_ref),
        )
    else:
        statements = (StatementLoopBreak(source_ref=source_ref),)

    pushBuildContext("loop_body")
    loop_statements = buildStatementsNode(
        provider=provider, nodes=node.body, source_ref=source_ref
    )
    popBuildContext()

    # The loop body contains a conditional statement at the start that breaks
    # the loop if it fails.
    loop_body = makeStatementsSequence(
        statements=(
            makeStatementConditional(
                condition=ExpressionOperationNOT(
                    operand=buildNode(provider, node.test, source_ref),
                    source_ref=source_ref,
                ),
                yes_branch=StatementsSequence(
                    statements=statements, source_ref=source_ref
                ),
                no_branch=None,
                source_ref=source_ref,
            ),
            loop_statements,
        ),
        allow_none=True,
        source_ref=source_ref,
    )

    loop_statement = StatementLoop(body=loop_body, source_ref=source_ref)

    if else_block is None:
        return loop_statement
    else:
        statements = (
            StatementAssignmentVariable(
                variable=tmp_break_indicator,
                source=makeConstantRefNode(constant=False, source_ref=source_ref),
                source_ref=source_ref,
            ),
            loop_statement,
            makeStatementConditional(
                condition=ExpressionComparisonIs(
                    left=ExpressionTempVariableRef(
                        variable=tmp_break_indicator, source_ref=source_ref
                    ),
                    right=makeConstantRefNode(constant=True, source_ref=source_ref),
                    source_ref=source_ref,
                ),
                yes_branch=else_block,
                no_branch=None,
                source_ref=source_ref,
            ),
        )

        statements = (
            makeTryFinallyStatement(
                provider=provider,
                tried=statements,
                final=StatementReleaseVariable(
                    variable=tmp_break_indicator, source_ref=source_ref
                ),
                source_ref=source_ref,
            ),
        )

        return StatementsSequence(
            statements=mergeStatements(statements, False), source_ref=source_ref
        )
Ejemplo n.º 15
0
def buildPrintNode(provider, node, source_ref):
    # "print" statements, should only occur with Python2.

    if node.dest is not None:
        temp_scope = provider.allocateTempScope("print")

        tmp_target_variable = provider.allocateTempVariable(
            temp_scope=temp_scope, name="target"
        )

        target_default_statement = StatementAssignmentVariable(
            variable=tmp_target_variable,
            source=ExpressionImportModuleNameHard(
                module_name="sys", import_name="stdout", source_ref=source_ref
            ),
            source_ref=source_ref,
        )

        statements = [
            StatementAssignmentVariable(
                variable=tmp_target_variable,
                source=buildNode(
                    provider=provider, node=node.dest, source_ref=source_ref
                ),
                source_ref=source_ref,
            ),
            makeStatementConditional(
                condition=ExpressionComparisonIs(
                    left=ExpressionTempVariableRef(
                        variable=tmp_target_variable, source_ref=source_ref
                    ),
                    right=ExpressionConstantNoneRef(source_ref=source_ref),
                    source_ref=source_ref,
                ),
                yes_branch=target_default_statement,
                no_branch=None,
                source_ref=source_ref,
            ),
        ]

    values = buildNodeList(provider=provider, nodes=node.values, source_ref=source_ref)

    if node.dest is not None:
        print_statements = [
            StatementPrintValue(
                dest=ExpressionTempVariableRef(
                    variable=tmp_target_variable, source_ref=source_ref
                ),
                value=value,
                source_ref=source_ref,
            )
            for value in values
        ]

        if node.nl:
            print_statements.append(
                StatementPrintNewline(
                    dest=ExpressionTempVariableRef(
                        variable=tmp_target_variable, source_ref=source_ref
                    ),
                    source_ref=source_ref,
                )
            )

        statements.append(
            makeTryFinallyStatement(
                provider=provider,
                tried=print_statements,
                final=StatementReleaseVariable(
                    variable=tmp_target_variable, source_ref=source_ref
                ),
                source_ref=source_ref,
            )
        )
    else:
        statements = [
            StatementPrintValue(dest=None, value=value, source_ref=source_ref)
            for value in values
        ]

        if node.nl:
            statements.append(StatementPrintNewline(dest=None, source_ref=source_ref))

    return makeStatementsSequenceFromStatements(*statements)
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=attribute_name,
            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=ExpressionBuiltinSlice(
                    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",
                        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)
def _buildContractionBodyNode(
    provider,
    node,
    emit_class,
    start_value,
    container_tmp,
    iter_tmp,
    temp_scope,
    assign_provider,
    function_body,
    for_asyncgen,
    source_ref,
):

    # This uses lots of variables and branches. There is no good way
    # around that, and we deal with many cases, due to having generator
    # expressions sharing this code, pylint: disable=too-many-branches,too-many-locals,too-many-statements

    # Note: The assign_provider is only to cover Python2 list contractions,
    # assigning one of the loop variables to the outside scope.

    tmp_variables = []
    if emit_class is not ExpressionYield:
        tmp_variables.append(iter_tmp)

    if container_tmp is not None:
        tmp_variables.append(container_tmp)

    statements = []

    # First assign the iterator if we are an outline.
    if assign_provider:
        statements.append(
            StatementAssignmentVariable(
                variable=iter_tmp,
                source=_makeIteratorCreation(
                    provider=provider,
                    qual=node.generators[0],
                    for_asyncgen=False,
                    source_ref=source_ref,
                ),
                source_ref=source_ref.atInternal(),
            )
        )

    if for_asyncgen and python_version >= 370 and node.generators[0].is_async:
        statements.append(
            StatementAssignmentVariable(
                variable=iter_tmp,
                source=ExpressionTempVariableRef(
                    variable=iter_tmp, source_ref=source_ref
                ),
                source_ref=source_ref,
            )
        )

    if start_value is not None:
        statements.append(
            StatementAssignmentVariable(
                variable=container_tmp,
                source=makeConstantRefNode(constant=start_value, source_ref=source_ref),
                source_ref=source_ref.atInternal(),
            )
        )

    if hasattr(node, "elt"):
        if start_value is not None:
            current_body = emit_class(
                ExpressionTempVariableRef(
                    variable=container_tmp, source_ref=source_ref
                ),
                buildNode(
                    provider=function_body if not assign_provider else provider,
                    node=node.elt,
                    source_ref=source_ref,
                ),
                source_ref=source_ref,
            )
        else:
            assert emit_class is ExpressionYield

            current_body = emit_class(
                buildNode(provider=function_body, node=node.elt, source_ref=source_ref),
                source_ref=source_ref,
            )
    else:
        assert emit_class is StatementDictOperationSet

        current_body = StatementDictOperationSet(
            dict_arg=ExpressionTempVariableRef(
                variable=container_tmp, source_ref=source_ref
            ),
            key=buildNode(
                provider=function_body if not assign_provider else provider,
                node=node.key,
                source_ref=source_ref,
            ),
            value=buildNode(
                provider=function_body if not assign_provider else provider,
                node=node.value,
                source_ref=source_ref,
            ),
            source_ref=source_ref,
        )

    if current_body.isExpression():
        current_body = StatementExpressionOnly(
            expression=current_body, source_ref=source_ref
        )

    for count, qual in enumerate(reversed(node.generators)):
        tmp_value_variable = function_body.allocateTempVariable(
            temp_scope=temp_scope, name="iter_value_%d" % count
        )

        tmp_variables.append(tmp_value_variable)

        # The first iterated value is to be calculated outside of the function
        # and will be given as a parameter "_iterated", the others are built
        # inside the function.

        if qual is node.generators[0]:
            iterator_ref = makeVariableRefNode(variable=iter_tmp, source_ref=source_ref)

            if for_asyncgen and python_version >= 370:
                iterator_ref = ExpressionYieldFromWaitable(
                    expression=iterator_ref, source_ref=source_ref
                )

            tmp_iter_variable = None

            nested_statements = []
        else:
            # First create the iterator and store it, next should be loop body
            value_iterator = _makeIteratorCreation(
                provider=provider if assign_provider else function_body,
                qual=qual,
                for_asyncgen=False,
                source_ref=source_ref,
            )

            tmp_iter_variable = function_body.allocateTempVariable(
                temp_scope=temp_scope, name="contraction_iter_%d" % count
            )

            tmp_variables.append(tmp_iter_variable)

            nested_statements = [
                StatementAssignmentVariable(
                    variable=tmp_iter_variable,
                    source=value_iterator,
                    source_ref=source_ref,
                )
            ]

            iterator_ref = ExpressionTempVariableRef(
                variable=tmp_iter_variable, source_ref=source_ref
            )

        loop_statements = [
            makeTryExceptSingleHandlerNode(
                tried=StatementAssignmentVariable(
                    variable=tmp_value_variable,
                    source=_makeIteratorNext(
                        iterator_ref=iterator_ref, qual=qual, source_ref=source_ref
                    ),
                    source_ref=source_ref,
                ),
                exception_name=_getStopIterationName(qual),
                handler_body=StatementLoopBreak(source_ref=source_ref),
                source_ref=source_ref,
            ),
            buildAssignmentStatements(
                provider=provider if assign_provider else function_body,
                temp_provider=function_body,
                node=qual.target,
                source=ExpressionTempVariableRef(
                    variable=tmp_value_variable, source_ref=source_ref
                ),
                source_ref=source_ref,
            ),
        ]

        conditions = buildNodeList(
            provider=provider if assign_provider else function_body,
            nodes=qual.ifs,
            source_ref=source_ref,
        )

        if len(conditions) >= 1:
            loop_statements.append(
                makeStatementConditional(
                    condition=buildAndNode(values=conditions, source_ref=source_ref),
                    yes_branch=current_body,
                    no_branch=None,
                    source_ref=source_ref,
                )
            )
        else:
            loop_statements.append(current_body)

        nested_statements.append(
            StatementLoop(
                body=StatementsSequence(
                    statements=mergeStatements(loop_statements), source_ref=source_ref
                ),
                source_ref=source_ref,
            )
        )

        if tmp_iter_variable is not None:
            nested_statements.append(
                StatementReleaseVariable(
                    variable=tmp_iter_variable, source_ref=source_ref
                )
            )

        current_body = StatementsSequence(
            statements=mergeStatements(nested_statements, False), source_ref=source_ref
        )

    statements.append(current_body)
    statements = mergeStatements(statements)

    release_statements = [
        StatementReleaseVariable(variable=tmp_variable, source_ref=source_ref)
        for tmp_variable in tmp_variables
    ]

    return statements, release_statements
Ejemplo n.º 18
0
def _buildWithNode(provider, context_expr, assign_target, body, sync, source_ref):
    # Many details, pylint: disable=too-many-branches,too-many-locals
    with_source = buildNode(provider, context_expr, source_ref)

    if python_version < 0x380 and Options.is_fullcompat:
        source_ref = with_source.getCompatibleSourceReference()

    temp_scope = provider.allocateTempScope("with")

    tmp_source_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="source"
    )
    tmp_exit_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="exit"
    )
    tmp_enter_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="enter"
    )

    # Indicator variable, will end up with C bool type, and need not be released.
    tmp_indicator_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="indicator", temp_type="bool"
    )

    statements = (
        buildAssignmentStatements(
            provider=provider,
            node=assign_target,
            allow_none=True,
            source=ExpressionTempVariableRef(
                variable=tmp_enter_variable, source_ref=source_ref
            ),
            source_ref=source_ref,
        ),
        body,
    )

    with_body = makeStatementsSequence(
        statements=statements, allow_none=True, source_ref=source_ref
    )

    if body and python_version < 0x3A0:
        deepest = body

        while deepest.getVisitableNodes():
            deepest = deepest.getVisitableNodes()[-1]

        if python_version < 0x370:
            body_lineno = deepest.getCompatibleSourceReference().getLineNumber()
        else:
            body_lineno = deepest.getSourceReference().getLineNumber()

        with_exit_source_ref = source_ref.atLineNumber(body_lineno)
    else:
        with_exit_source_ref = source_ref

    # The "__enter__" and "__exit__" were normal attribute lookups under
    # CPython2.6, but that changed with CPython2.7.
    if python_version < 0x270:
        attribute_lookup_maker = makeExpressionAttributeLookup
    else:
        attribute_lookup_maker = ExpressionAttributeLookupSpecial

    enter_value = ExpressionCallEmpty(
        called=attribute_lookup_maker(
            expression=ExpressionTempVariableRef(
                variable=tmp_source_variable, source_ref=source_ref
            ),
            attribute_name="__enter__" if sync else "__aenter__",
            source_ref=source_ref,
        ),
        source_ref=source_ref,
    )

    exit_value_exception = ExpressionCallNoKeywords(
        called=ExpressionTempVariableRef(
            variable=tmp_exit_variable, source_ref=with_exit_source_ref
        ),
        args=makeExpressionMakeTuple(
            elements=(
                ExpressionCaughtExceptionTypeRef(source_ref=with_exit_source_ref),
                ExpressionCaughtExceptionValueRef(source_ref=with_exit_source_ref),
                ExpressionCaughtExceptionTracebackRef(source_ref=source_ref),
            ),
            source_ref=source_ref,
        ),
        source_ref=with_exit_source_ref,
    )

    exit_value_no_exception = ExpressionCallNoKeywords(
        called=ExpressionTempVariableRef(
            variable=tmp_exit_variable, source_ref=source_ref
        ),
        args=makeConstantRefNode(constant=(None, None, None), source_ref=source_ref),
        source_ref=with_exit_source_ref,
    )

    # For "async with", await the entered value and exit value must be awaited.
    if not sync:
        exit_value_exception = ExpressionYieldFromWaitable(
            expression=ExpressionAsyncWaitExit(
                expression=exit_value_exception, source_ref=source_ref
            ),
            source_ref=source_ref,
        )
        exit_value_no_exception = ExpressionYieldFromWaitable(
            ExpressionAsyncWaitExit(
                expression=exit_value_no_exception, source_ref=source_ref
            ),
            source_ref=source_ref,
        )

    # First assign the with context to a temporary variable.
    statements = [
        StatementAssignmentVariable(
            variable=tmp_source_variable, source=with_source, source_ref=source_ref
        )
    ]

    # Before 3.9, __aenter__ is immediately awaited, after we first do __aexit__ lookup.
    if not sync and python_version < 0x390:
        enter_value = ExpressionYieldFromWaitable(
            expression=ExpressionAsyncWaitEnter(
                expression=enter_value, source_ref=source_ref
            ),
            source_ref=source_ref,
        )

    attribute_enter_assignment = StatementAssignmentVariable(
        variable=tmp_enter_variable, source=enter_value, source_ref=source_ref
    )

    attribute_exit_assignment = StatementAssignmentVariable(
        variable=tmp_exit_variable,
        source=attribute_lookup_maker(
            expression=ExpressionTempVariableRef(
                variable=tmp_source_variable, source_ref=source_ref
            ),
            attribute_name="__exit__" if sync else "__aexit__",
            source_ref=source_ref,
        ),
        source_ref=source_ref,
    )

    # Next, assign "__enter__" and "__exit__" attributes to temporary variables, and
    # depending on Python versions switch the order of these lookups and the order of
    # awaiting enter.
    # Normal "with" statements are enter, exit ordered after 3.6, and "async with"
    # are since 3.9, and since 3.9 the enter is not awaited, until an exit is present.
    if python_version >= 0x390 and not sync:
        enter_await_statement = StatementAssignmentVariable(
            variable=tmp_enter_variable,
            source=ExpressionYieldFromWaitable(
                expression=ExpressionAsyncWaitEnter(
                    expression=ExpressionTempVariableRef(
                        variable=tmp_enter_variable, source_ref=source_ref
                    ),
                    source_ref=source_ref,
                ),
                source_ref=source_ref,
            ),
            source_ref=source_ref,
        )

        attribute_assignments = (
            attribute_enter_assignment,
            attribute_exit_assignment,
            enter_await_statement,
        )
    elif python_version >= 0x360 and sync:
        attribute_assignments = (attribute_enter_assignment, attribute_exit_assignment)
    else:
        attribute_assignments = (attribute_exit_assignment, attribute_enter_assignment)

    statements.extend(attribute_assignments)

    statements.append(
        StatementAssignmentVariable(
            variable=tmp_indicator_variable,
            source=makeConstantRefNode(constant=True, source_ref=source_ref),
            source_ref=source_ref,
        )
    )

    statements += (
        makeTryFinallyStatement(
            provider=provider,
            tried=makeTryExceptSingleHandlerNodeWithPublish(
                provider=provider,
                tried=with_body,
                exception_name="BaseException",
                handler_body=StatementsSequence(
                    statements=(
                        # Prevents final block from calling __exit__ as
                        # well.
                        StatementAssignmentVariable(
                            variable=tmp_indicator_variable,
                            source=makeConstantRefNode(
                                constant=False, source_ref=source_ref
                            ),
                            source_ref=source_ref,
                        ),
                        makeStatementConditional(
                            condition=exit_value_exception,
                            no_branch=makeReraiseExceptionStatement(
                                source_ref=with_exit_source_ref
                            ),
                            yes_branch=None,
                            source_ref=with_exit_source_ref,
                        ),
                    ),
                    source_ref=source_ref,
                ),
                public_exc=python_version >= 0x270,
                source_ref=source_ref,
            ),
            final=makeStatementConditional(
                condition=ExpressionComparisonIs(
                    left=ExpressionTempVariableRef(
                        variable=tmp_indicator_variable, source_ref=source_ref
                    ),
                    right=makeConstantRefNode(constant=True, source_ref=source_ref),
                    source_ref=source_ref,
                ),
                yes_branch=StatementExpressionOnly(
                    expression=exit_value_no_exception, source_ref=source_ref
                ),
                no_branch=None,
                source_ref=source_ref,
            ),
            source_ref=source_ref,
        ),
    )

    return makeTryFinallyStatement(
        provider=provider,
        tried=statements,
        final=(
            StatementReleaseVariable(
                variable=tmp_source_variable, source_ref=with_exit_source_ref
            ),
            StatementReleaseVariable(
                variable=tmp_enter_variable, source_ref=with_exit_source_ref
            ),
            StatementReleaseVariable(
                variable=tmp_exit_variable, source_ref=with_exit_source_ref
            ),
        ),
        source_ref=source_ref,
    )
def makeTryExceptNoRaise(provider, temp_scope, tried, handling, no_raise, source_ref):
    # This helper executes the core re-formulation of "no_raise" blocks, which
    # are the "else" blocks of "try"/"except" statements. In order to limit the
    # execution, we use an indicator variable instead, which will signal that
    # the tried block executed up to the end. And then we make the else block be
    # a conditional statement checking that.

    tmp_handler_indicator_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="unhandled_indicator"
    )

    statements = mergeStatements(
        (
            StatementAssignmentVariable(
                variable=tmp_handler_indicator_variable,
                source=makeConstantRefNode(constant=False, source_ref=source_ref),
                source_ref=no_raise.getSourceReference().atInternal(),
            ),
            handling,
        ),
        allow_none=True,
    )

    handling = StatementsSequence(statements=statements, source_ref=source_ref)

    tried = (
        StatementTry(
            tried=tried,
            except_handler=handling,
            break_handler=None,
            continue_handler=None,
            return_handler=None,
            source_ref=source_ref,
        ),
        makeStatementConditional(
            condition=ExpressionComparisonIs(
                left=ExpressionTempVariableRef(
                    variable=tmp_handler_indicator_variable, source_ref=source_ref
                ),
                right=makeConstantRefNode(constant=True, source_ref=source_ref),
                source_ref=source_ref,
            ),
            yes_branch=no_raise,
            no_branch=None,
            source_ref=source_ref,
        ),
    )

    final = StatementReleaseVariable(
        variable=tmp_handler_indicator_variable, source_ref=source_ref.atInternal()
    )

    return makeStatementsSequenceFromStatements(
        StatementAssignmentVariable(
            variable=tmp_handler_indicator_variable,
            source=makeConstantRefNode(constant=True, source_ref=source_ref),
            source_ref=source_ref.atInternal(),
        ),
        makeTryFinallyStatement(
            provider=provider, tried=tried, final=final, source_ref=source_ref
        ),
    )
Ejemplo n.º 20
0
def getClassBasesMroConversionHelper():
    helper_name = "_mro_entries_conversion"

    result = makeInternalHelperFunctionBody(
        name=helper_name,
        parameters=ParameterSpec(
            ps_name=helper_name,
            ps_normal_args=("bases",),
            ps_list_star_arg=None,
            ps_dict_star_arg=None,
            ps_default_count=0,
            ps_kw_only_args=(),
        ),
    )

    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(
            object_arg=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(
                        source=ExpressionTempVariableRef(
                            variable=tmp_item_variable, source_ref=internal_source_ref
                        ),
                        attribute_name="__mro_entries__",
                        source_ref=internal_source_ref,
                    ),
                    args=ExpressionMakeTuple(
                        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(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.setBody(
        makeStatementsSequenceFromStatement(
            makeTryFinallyStatement(
                provider=result,
                tried=tried,
                final=final,
                source_ref=internal_source_ref,
            )
        )
    )

    return result
Ejemplo n.º 21
0
def buildPrintNode(provider, node, source_ref):
    # "print" statements, should only occur with Python2.

    if node.dest is not None:
        temp_scope = provider.allocateTempScope("print")

        tmp_target_variable = provider.allocateTempVariable(
            temp_scope=temp_scope, name="target")

        target_default_statement = StatementAssignmentVariable(
            variable=tmp_target_variable,
            source=makeExpressionImportModuleNameHard(module_name="sys",
                                                      import_name="stdout",
                                                      source_ref=source_ref),
            source_ref=source_ref,
        )

        statements = [
            StatementAssignmentVariable(
                variable=tmp_target_variable,
                source=buildNode(provider=provider,
                                 node=node.dest,
                                 source_ref=source_ref),
                source_ref=source_ref,
            ),
            makeStatementConditional(
                condition=ExpressionComparisonIs(
                    left=ExpressionTempVariableRef(
                        variable=tmp_target_variable, source_ref=source_ref),
                    right=ExpressionConstantNoneRef(source_ref=source_ref),
                    source_ref=source_ref,
                ),
                yes_branch=target_default_statement,
                no_branch=None,
                source_ref=source_ref,
            ),
        ]

    values = buildNodeList(provider=provider,
                           nodes=node.values,
                           source_ref=source_ref)

    if node.dest is not None:
        print_statements = [
            StatementPrintValue(
                dest=ExpressionTempVariableRef(variable=tmp_target_variable,
                                               source_ref=source_ref),
                value=value,
                source_ref=source_ref,
            ) for value in values
        ]

        if node.nl:
            print_statements.append(
                StatementPrintNewline(
                    dest=ExpressionTempVariableRef(
                        variable=tmp_target_variable, source_ref=source_ref),
                    source_ref=source_ref,
                ))

        statements.append(
            makeTryFinallyStatement(
                provider=provider,
                tried=print_statements,
                final=StatementReleaseVariable(variable=tmp_target_variable,
                                               source_ref=source_ref),
                source_ref=source_ref,
            ))
    else:
        statements = [
            StatementPrintValue(dest=None, value=value, source_ref=source_ref)
            for value in values
        ]

        if node.nl:
            statements.append(
                StatementPrintNewline(dest=None, source_ref=source_ref))

    return makeStatementsSequenceFromStatements(*statements)
def _buildForLoopNode(provider, node, sync, source_ref):
    # The for loop is re-formulated according to developer manual. An iterator
    # is created, and looped until it gives StopIteration. The else block is
    # taken if a for loop exits normally, i.e. because of iterator
    # exhaustion. We do this by introducing an indicator variable.

    # We handle async and sync both here, leading to cases, pylint: disable=too-many-locals

    source = buildNode(provider, node.iter, source_ref)

    # Temporary variables, we need one for the iterator, and one for the current
    # value.
    temp_scope = provider.allocateTempScope("for_loop")

    tmp_iter_variable = provider.allocateTempVariable(temp_scope=temp_scope,
                                                      name="for_iterator")
    tmp_value_variable = provider.allocateTempVariable(temp_scope=temp_scope,
                                                       name="iter_value")

    else_block = buildStatementsNode(
        provider=provider,
        nodes=node.orelse if node.orelse else None,
        source_ref=source_ref,
    )

    if else_block is not None:
        # Indicator variable, will end up with C bool type, and need not be released.
        tmp_break_indicator = provider.allocateTempVariable(
            temp_scope=temp_scope, name="break_indicator", temp_type="bool")

        statements = [
            StatementAssignmentVariable(
                variable=tmp_break_indicator,
                source=makeConstantRefNode(constant=True,
                                           source_ref=source_ref),
                source_ref=source_ref,
            )
        ]
    else:
        statements = []

    statements.append(StatementLoopBreak(source_ref=source_ref))

    handler_body = makeStatementsSequence(statements=statements,
                                          allow_none=False,
                                          source_ref=source_ref)

    if sync:
        next_node = ExpressionBuiltinNext1(
            value=ExpressionTempVariableRef(variable=tmp_iter_variable,
                                            source_ref=source_ref),
            source_ref=source_ref,
        )
    else:
        next_node = ExpressionYieldFromWaitable(
            expression=ExpressionAsyncNext(
                value=ExpressionTempVariableRef(variable=tmp_iter_variable,
                                                source_ref=source_ref),
                source_ref=source_ref,
            ),
            source_ref=source_ref,
        )

    statements = (
        makeTryExceptSingleHandlerNode(
            tried=StatementAssignmentVariable(variable=tmp_value_variable,
                                              source=next_node,
                                              source_ref=source_ref),
            exception_name="StopIteration" if sync else "StopAsyncIteration",
            handler_body=handler_body,
            source_ref=source_ref,
        ),
        buildAssignmentStatements(
            provider=provider,
            node=node.target,
            source=ExpressionTempVariableRef(variable=tmp_value_variable,
                                             source_ref=source_ref),
            source_ref=source_ref,
        ),
    )

    pushBuildContext("loop_body")
    statements += (buildStatementsNode(provider=provider,
                                       nodes=node.body,
                                       source_ref=source_ref), )
    popBuildContext()

    loop_body = makeStatementsSequence(statements=statements,
                                       allow_none=True,
                                       source_ref=source_ref)

    cleanup_statements = [
        StatementReleaseVariable(variable=tmp_value_variable,
                                 source_ref=source_ref),
        StatementReleaseVariable(variable=tmp_iter_variable,
                                 source_ref=source_ref),
    ]

    if else_block is not None:
        statements = [
            StatementAssignmentVariable(
                variable=tmp_break_indicator,
                source=makeConstantRefNode(constant=False,
                                           source_ref=source_ref),
                source_ref=source_ref,
            )
        ]
    else:
        statements = []

    if sync:
        iter_source = ExpressionBuiltinIter1(
            value=source, source_ref=source.getSourceReference())
    else:
        iter_source = ExpressionYieldFromWaitable(
            expression=ExpressionAsyncIter(
                value=source, source_ref=source.getSourceReference()),
            source_ref=source.getSourceReference(),
        )

    statements += (
        # First create the iterator and store it.
        StatementAssignmentVariable(variable=tmp_iter_variable,
                                    source=iter_source,
                                    source_ref=source_ref),
        makeTryFinallyStatement(
            provider=provider,
            tried=StatementLoop(loop_body=loop_body, source_ref=source_ref),
            final=StatementsSequence(statements=cleanup_statements,
                                     source_ref=source_ref),
            source_ref=source_ref,
        ),
    )

    if else_block is not None:
        statements.append(
            makeStatementConditional(
                condition=ExpressionComparisonIs(
                    left=ExpressionTempVariableRef(
                        variable=tmp_break_indicator, source_ref=source_ref),
                    right=makeConstantRefNode(constant=True,
                                              source_ref=source_ref),
                    source_ref=source_ref,
                ),
                yes_branch=else_block,
                no_branch=None,
                source_ref=source_ref,
            ))

    return makeStatementsSequenceFromStatements(*statements)
Ejemplo n.º 23
0
def buildExecNode(provider, node, source_ref):
    # "exec" statements, should only occur with Python2.

    # This is using many variables, due to the many details this is
    # dealing with. The locals and globals need to be dealt with in
    # temporary variables, and we need handling of indicators, so
    # that is just the complexity, pylint: disable=too-many-locals

    exec_globals = node.globals
    exec_locals = node.locals
    body = node.body

    # Handle exec(a,b,c) to be same as exec a, b, c
    if exec_locals is None and exec_globals is None and getKind(
            body) == "Tuple":
        parts = body.elts
        body = parts[0]

        if len(parts) > 1:
            exec_globals = parts[1]

            if len(parts) > 2:
                exec_locals = parts[2]
        else:
            return StatementRaiseException(
                exception_type=ExpressionBuiltinExceptionRef(
                    exception_name="TypeError", source_ref=source_ref),
                exception_value=makeConstantRefNode(
                    constant="""\
exec: arg 1 must be a string, file, or code object""",
                    source_ref=source_ref,
                ),
                exception_trace=None,
                exception_cause=None,
                source_ref=source_ref,
            )

    temp_scope = provider.allocateTempScope("exec")

    locals_value = buildNode(provider, exec_locals, source_ref, True)

    if locals_value is None:
        locals_value = ExpressionConstantNoneRef(source_ref=source_ref)

    globals_value = buildNode(provider, exec_globals, source_ref, True)

    if globals_value is None:
        globals_value = ExpressionConstantNoneRef(source_ref=source_ref)

    source_code = buildNode(provider, body, source_ref)

    source_variable = provider.allocateTempVariable(temp_scope=temp_scope,
                                                    name="exec_source")

    globals_keeper_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="globals")

    locals_keeper_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="locals")

    plain_indicator_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="plain")

    tried = (
        # First evaluate the source code expressions.
        StatementAssignmentVariable(variable=source_variable,
                                    source=source_code,
                                    source_ref=source_ref),
        # Assign globals and locals temporary the values given, then fix it
        # up, taking note in the "plain" temporary variable, if it was an
        # "exec" statement with None arguments, in which case the copy back
        # will be necessary.
        StatementAssignmentVariable(
            variable=globals_keeper_variable,
            source=globals_value,
            source_ref=source_ref,
        ),
        StatementAssignmentVariable(variable=locals_keeper_variable,
                                    source=locals_value,
                                    source_ref=source_ref),
        StatementAssignmentVariable(
            variable=plain_indicator_variable,
            source=makeConstantRefNode(constant=False, source_ref=source_ref),
            source_ref=source_ref,
        ),
        makeStatementConditional(
            condition=ExpressionComparisonIs(
                left=ExpressionTempVariableRef(
                    variable=globals_keeper_variable, source_ref=source_ref),
                right=ExpressionConstantNoneRef(source_ref=source_ref),
                source_ref=source_ref,
            ),
            yes_branch=makeStatementsSequenceFromStatements(
                StatementAssignmentVariable(
                    variable=globals_keeper_variable,
                    source=ExpressionBuiltinGlobals(source_ref=source_ref),
                    source_ref=source_ref,
                ),
                makeStatementConditional(
                    condition=ExpressionComparisonIs(
                        left=ExpressionTempVariableRef(
                            variable=locals_keeper_variable,
                            source_ref=source_ref),
                        right=ExpressionConstantNoneRef(source_ref=source_ref),
                        source_ref=source_ref,
                    ),
                    yes_branch=makeStatementsSequenceFromStatements(
                        StatementAssignmentVariable(
                            variable=locals_keeper_variable,
                            source=makeExpressionBuiltinLocals(
                                provider=provider, source_ref=source_ref),
                            source_ref=source_ref,
                        ),
                        StatementAssignmentVariable(
                            variable=plain_indicator_variable,
                            source=makeConstantRefNode(constant=True,
                                                       source_ref=source_ref),
                            source_ref=source_ref,
                        ),
                    ),
                    no_branch=None,
                    source_ref=source_ref,
                ),
            ),
            no_branch=makeStatementsSequenceFromStatements(
                makeStatementConditional(
                    condition=ExpressionComparisonIs(
                        left=ExpressionTempVariableRef(
                            variable=locals_keeper_variable,
                            source_ref=source_ref),
                        right=ExpressionConstantNoneRef(source_ref=source_ref),
                        source_ref=source_ref,
                    ),
                    yes_branch=makeStatementsSequenceFromStatement(
                        statement=StatementAssignmentVariable(
                            variable=locals_keeper_variable,
                            source=ExpressionTempVariableRef(
                                variable=globals_keeper_variable,
                                source_ref=source_ref),
                            source_ref=source_ref,
                        )),
                    no_branch=None,
                    source_ref=source_ref,
                )),
            source_ref=source_ref,
        ),
        makeTryFinallyStatement(
            provider=provider,
            tried=StatementExec(
                source_code=ExpressionTempVariableRef(variable=source_variable,
                                                      source_ref=source_ref),
                globals_arg=ExpressionTempVariableRef(
                    variable=globals_keeper_variable, source_ref=source_ref),
                locals_arg=ExpressionTempVariableRef(
                    variable=locals_keeper_variable, source_ref=source_ref),
                source_ref=source_ref,
            ),
            final=makeStatementConditional(
                condition=ExpressionComparisonIs(
                    left=ExpressionTempVariableRef(
                        variable=plain_indicator_variable,
                        source_ref=source_ref),
                    right=makeConstantRefNode(constant=True,
                                              source_ref=source_ref),
                    source_ref=source_ref,
                ),
                yes_branch=StatementLocalsDictSync(
                    locals_arg=ExpressionTempVariableRef(
                        variable=locals_keeper_variable,
                        source_ref=source_ref),
                    source_ref=source_ref,
                ),
                no_branch=None,
                source_ref=source_ref,
            ),
            source_ref=source_ref,
        ),
    )

    final = (
        StatementReleaseVariable(variable=source_variable,
                                 source_ref=source_ref),
        StatementReleaseVariable(variable=globals_keeper_variable,
                                 source_ref=source_ref),
        StatementReleaseVariable(variable=locals_keeper_variable,
                                 source_ref=source_ref),
        StatementReleaseVariable(variable=plain_indicator_variable,
                                 source_ref=source_ref),
    )

    return makeTryFinallyStatement(provider=provider,
                                   tried=tried,
                                   final=final,
                                   source_ref=source_ref)
def buildLambdaNode(provider, node, source_ref):
    # Many details to deal with, pylint: disable=too-many-locals

    assert getKind(node) == "Lambda"

    function_kind, flags = detectFunctionBodyKind(nodes=(node.body,))

    outer_body, function_body, code_object = buildFunctionWithParsing(
        provider=provider,
        function_kind=function_kind,
        name="<lambda>",
        function_doc=None,
        flags=flags,
        node=node,
        source_ref=source_ref,
    )

    if function_kind == "Function":
        code_body = function_body
    else:
        code_body = ExpressionGeneratorObjectBody(
            provider=function_body,
            name="<lambda>",
            code_object=code_object,
            flags=set(),
            source_ref=source_ref,
        )
        code_body.qualname_provider = provider

    if function_kind == "Generator":
        function_body.setBody(
            makeStatementsSequenceFromStatement(
                statement=StatementReturn(
                    expression=ExpressionMakeGeneratorObject(
                        generator_ref=ExpressionFunctionRef(
                            function_body=code_body, source_ref=source_ref
                        ),
                        source_ref=source_ref,
                    ),
                    source_ref=source_ref,
                )
            )
        )

    defaults = buildNodeList(provider, node.args.defaults, source_ref)
    kw_defaults = buildParameterKwDefaults(
        provider=provider, node=node, function_body=function_body, source_ref=source_ref
    )

    body = buildNode(provider=code_body, node=node.body, source_ref=source_ref)

    if function_kind == "Generator":
        if python_version < 270:
            tmp_return_value = code_body.allocateTempVariable(
                temp_scope=None, name="yield_return"
            )

            statements = (
                StatementAssignmentVariable(
                    variable=tmp_return_value, source=body, source_ref=source_ref
                ),
                makeStatementConditional(
                    condition=ExpressionComparisonIsNOT(
                        left=ExpressionTempVariableRef(
                            variable=tmp_return_value, source_ref=source_ref
                        ),
                        right=ExpressionConstantNoneRef(source_ref=source_ref),
                        source_ref=source_ref,
                    ),
                    yes_branch=StatementExpressionOnly(
                        expression=ExpressionYield(
                            expression=ExpressionTempVariableRef(
                                variable=tmp_return_value, source_ref=source_ref
                            ),
                            source_ref=source_ref,
                        ),
                        source_ref=source_ref,
                    ),
                    no_branch=None,
                    source_ref=source_ref,
                ),
            )
            body = makeTryFinallyStatement(
                provider=provider,
                tried=statements,
                final=StatementReleaseVariable(
                    variable=tmp_return_value, source_ref=source_ref
                ),
                source_ref=source_ref,
            )
        else:
            body = StatementExpressionOnly(expression=body, source_ref=source_ref)
    else:
        body = StatementReturn(expression=body, source_ref=source_ref)

    if function_kind == "Generator":
        frame_class = StatementsFrameGenerator
    else:
        frame_class = StatementsFrameFunction

    body = frame_class(
        statements=mergeStatements((body,)),
        code_object=code_object,
        source_ref=body.getSourceReference(),
    )

    body = makeStatementsSequenceFromStatement(statement=body)

    code_body.setBody(body)

    annotations = buildParameterAnnotations(provider, node, source_ref)

    return ExpressionFunctionCreation(
        function_ref=ExpressionFunctionRef(
            function_body=outer_body, source_ref=source_ref
        ),
        defaults=defaults,
        kw_defaults=kw_defaults,
        annotations=annotations,
        source_ref=source_ref,
    )
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)
Ejemplo n.º 26
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=ExpressionConditionalAnd(
                left=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,
                ),
                right=ExpressionBuiltinIssubclass(
                    cls=ExpressionTempVariableRef(
                        variable=tmp_item_variable,
                        source_ref=internal_source_ref),
                    classes=makeConstantRefNode(
                        constant=type, source_ref=internal_source_ref),
                    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
Ejemplo n.º 27
0
def _buildWithNode(
    provider, context_expr, assign_target, body, body_lineno, sync, source_ref
):
    # Many details, pylint: disable=too-many-locals
    with_source = buildNode(provider, context_expr, source_ref)

    if Options.isFullCompat():
        source_ref = with_source.getCompatibleSourceReference()

    temp_scope = provider.allocateTempScope("with")

    tmp_source_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="source"
    )
    tmp_exit_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="exit"
    )
    tmp_enter_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="enter"
    )
    tmp_indicator_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="indicator"
    )

    statements = (
        buildAssignmentStatements(
            provider=provider,
            node=assign_target,
            allow_none=True,
            source=ExpressionTempVariableRef(
                variable=tmp_enter_variable, source_ref=source_ref
            ),
            source_ref=source_ref,
        ),
        body,
    )

    with_body = makeStatementsSequence(
        statements=statements, allow_none=True, source_ref=source_ref
    )

    if Options.isFullCompat():
        if body:
            deepest = body

            while deepest.getVisitableNodes():
                deepest = deepest.getVisitableNodes()[-1]

            body_lineno = deepest.getCompatibleSourceReference().getLineNumber()

        with_exit_source_ref = source_ref.atLineNumber(body_lineno)
    else:
        with_exit_source_ref = source_ref

    # The "__enter__" and "__exit__" were normal attribute lookups under
    # CPython2.6, but that changed with CPython2.7.
    if python_version < 270:
        attribute_lookup_class = ExpressionAttributeLookup
    else:
        attribute_lookup_class = ExpressionAttributeLookupSpecial

    enter_value = ExpressionCallEmpty(
        called=attribute_lookup_class(
            source=ExpressionTempVariableRef(
                variable=tmp_source_variable, source_ref=source_ref
            ),
            attribute_name="__enter__" if sync else "__aenter__",
            source_ref=source_ref,
        ),
        source_ref=source_ref,
    )

    exit_value_exception = ExpressionCallNoKeywords(
        called=ExpressionTempVariableRef(
            variable=tmp_exit_variable, source_ref=with_exit_source_ref
        ),
        args=ExpressionMakeTuple(
            elements=(
                ExpressionCaughtExceptionTypeRef(source_ref=with_exit_source_ref),
                ExpressionCaughtExceptionValueRef(source_ref=with_exit_source_ref),
                ExpressionCaughtExceptionTracebackRef(source_ref=source_ref),
            ),
            source_ref=source_ref,
        ),
        source_ref=with_exit_source_ref,
    )

    exit_value_no_exception = ExpressionCallNoKeywords(
        called=ExpressionTempVariableRef(
            variable=tmp_exit_variable, source_ref=source_ref
        ),
        args=makeConstantRefNode(constant=(None, None, None), source_ref=source_ref),
        source_ref=with_exit_source_ref,
    )

    # For "async with", await the entered value and exit value must be awaited.
    if not sync:
        enter_value = ExpressionYieldFromWaitable(
            expression=ExpressionAsyncWaitEnter(
                expression=enter_value, source_ref=source_ref
            ),
            source_ref=source_ref,
        )
        exit_value_exception = ExpressionYieldFromWaitable(
            expression=ExpressionAsyncWaitExit(
                expression=exit_value_exception, source_ref=source_ref
            ),
            source_ref=source_ref,
        )
        exit_value_no_exception = ExpressionYieldFromWaitable(
            ExpressionAsyncWaitExit(
                expression=exit_value_no_exception, source_ref=source_ref
            ),
            source_ref=source_ref,
        )

    statements = [
        # First assign the with context to a temporary variable.
        StatementAssignmentVariable(
            variable=tmp_source_variable, source=with_source, source_ref=source_ref
        )
    ]

    attribute_assignments = [
        # Next, assign "__enter__" and "__exit__" attributes to temporary
        # variables.
        StatementAssignmentVariable(
            variable=tmp_exit_variable,
            source=attribute_lookup_class(
                source=ExpressionTempVariableRef(
                    variable=tmp_source_variable, source_ref=source_ref
                ),
                attribute_name="__exit__" if sync else "__aexit__",
                source_ref=source_ref,
            ),
            source_ref=source_ref,
        ),
        StatementAssignmentVariable(
            variable=tmp_enter_variable, source=enter_value, source_ref=source_ref
        ),
    ]

    if python_version >= 360 and sync:
        attribute_assignments.reverse()

    statements += attribute_assignments

    statements.append(
        StatementAssignmentVariable(
            variable=tmp_indicator_variable,
            source=makeConstantRefNode(constant=True, source_ref=source_ref),
            source_ref=source_ref,
        )
    )

    statements += [
        makeTryFinallyStatement(
            provider=provider,
            tried=makeTryExceptSingleHandlerNodeWithPublish(
                provider=provider,
                tried=with_body,
                exception_name="BaseException",
                handler_body=StatementsSequence(
                    statements=(
                        # Prevents final block from calling __exit__ as
                        # well.
                        StatementAssignmentVariable(
                            variable=tmp_indicator_variable,
                            source=makeConstantRefNode(
                                constant=False, source_ref=source_ref
                            ),
                            source_ref=source_ref,
                        ),
                        makeStatementConditional(
                            condition=exit_value_exception,
                            no_branch=makeReraiseExceptionStatement(
                                source_ref=with_exit_source_ref
                            ),
                            yes_branch=None,
                            source_ref=with_exit_source_ref,
                        ),
                    ),
                    source_ref=source_ref,
                ),
                public_exc=python_version >= 270,
                source_ref=source_ref,
            ),
            final=makeStatementConditional(
                condition=ExpressionComparisonIs(
                    left=ExpressionTempVariableRef(
                        variable=tmp_indicator_variable, source_ref=source_ref
                    ),
                    right=makeConstantRefNode(constant=True, source_ref=source_ref),
                    source_ref=source_ref,
                ),
                yes_branch=StatementExpressionOnly(
                    expression=exit_value_no_exception, source_ref=source_ref
                ),
                no_branch=None,
                source_ref=source_ref,
            ),
            source_ref=source_ref,
        )
    ]

    return makeTryFinallyStatement(
        provider=provider,
        tried=statements,
        final=(
            StatementReleaseVariable(
                variable=tmp_source_variable, source_ref=with_exit_source_ref
            ),
            StatementReleaseVariable(
                variable=tmp_enter_variable, source_ref=with_exit_source_ref
            ),
            StatementReleaseVariable(
                variable=tmp_exit_variable, source_ref=with_exit_source_ref
            ),
            StatementReleaseVariable(
                variable=tmp_indicator_variable, source_ref=with_exit_source_ref
            ),
        ),
        source_ref=source_ref,
    )
def _makeTryExceptSingleHandlerNode(
    provider, public_exc, tried, exception_name, handler_body, source_ref
):
    # No need to create this in the first place if nothing is tried.
    if tried is None:
        return None

    if public_exc:
        preserver_id = provider.allocatePreserverId()

        handling = [
            StatementPreserveFrameException(
                preserver_id=preserver_id, source_ref=source_ref
            ),
            StatementPublishException(source_ref=source_ref),
        ]
    else:
        handling = []

    if not handler_body.isStatementsSequence():
        handler_body = makeStatementsSequenceFromStatement(statement=handler_body)

    if not tried.isStatementsSequence():
        tried = makeStatementsSequenceFromStatement(statement=tried)

    handling.append(
        makeStatementConditional(
            condition=ExpressionComparisonExceptionMatch(
                left=ExpressionCaughtExceptionTypeRef(source_ref=source_ref),
                right=ExpressionBuiltinExceptionRef(
                    exception_name=exception_name, source_ref=source_ref
                ),
                source_ref=source_ref,
            ),
            yes_branch=handler_body,
            no_branch=makeReraiseExceptionStatement(source_ref=source_ref),
            source_ref=source_ref,
        )
    )

    if python_version >= 300 and public_exc:
        handling = (
            makeTryFinallyStatement(
                provider=provider,
                tried=handling,
                final=StatementRestoreFrameException(
                    preserver_id=preserver_id, source_ref=source_ref.atInternal()
                ),
                source_ref=source_ref.atInternal(),
            ),
        )

    handling = makeStatementsSequenceFromStatements(*handling)

    return StatementTry(
        tried=tried,
        except_handler=handling,
        break_handler=None,
        continue_handler=None,
        return_handler=None,
        source_ref=source_ref,
    )
def _buildContractionBodyNode(
    provider,
    node,
    emit_class,
    start_value,
    container_tmp,
    iter_tmp,
    temp_scope,
    assign_provider,
    function_body,
    for_asyncgen,
    source_ref,
):

    # This uses lots of variables and branches. There is no good way
    # around that, and we deal with many cases, due to having generator
    # expressions sharing this code, pylint: disable=too-many-branches,too-many-locals

    # Note: The assign_provider is only to cover Python2 list contractions,
    # assigning one of the loop variables to the outside scope.

    tmp_variables = []
    if emit_class is not ExpressionYield:
        tmp_variables.append(iter_tmp)

    if container_tmp is not None:
        tmp_variables.append(container_tmp)

    statements = []

    # First assign the iterator if we are an outline.
    if assign_provider:
        statements.append(
            StatementAssignmentVariable(
                variable=iter_tmp,
                source=_makeIteratorCreation(
                    provider=provider,
                    qual=node.generators[0],
                    for_asyncgen=False,
                    source_ref=source_ref,
                ),
                source_ref=source_ref.atInternal(),
            ))

    if for_asyncgen and python_version >= 370 and node.generators[0].is_async:
        statements.append(
            StatementAssignmentVariable(
                variable=iter_tmp,
                source=ExpressionTempVariableRef(variable=iter_tmp,
                                                 source_ref=source_ref),
                source_ref=source_ref,
            ))

    if start_value is not None:
        statements.append(
            StatementAssignmentVariable(
                variable=container_tmp,
                source=makeConstantRefNode(constant=start_value,
                                           source_ref=source_ref),
                source_ref=source_ref.atInternal(),
            ))

    if hasattr(node, "elt"):
        if start_value is not None:
            current_body = emit_class(
                ExpressionTempVariableRef(variable=container_tmp,
                                          source_ref=source_ref),
                buildNode(
                    provider=function_body
                    if not assign_provider else provider,
                    node=node.elt,
                    source_ref=source_ref,
                ),
                source_ref=source_ref,
            )
        else:
            assert emit_class is ExpressionYield

            current_body = emit_class(
                buildNode(provider=function_body,
                          node=node.elt,
                          source_ref=source_ref),
                source_ref=source_ref,
            )
    else:
        current_body = emit_class(
            dict_arg=ExpressionTempVariableRef(variable=container_tmp,
                                               source_ref=source_ref),
            key=buildNode(
                provider=function_body if not assign_provider else provider,
                node=node.key,
                source_ref=source_ref,
            ),
            value=buildNode(
                provider=function_body if not assign_provider else provider,
                node=node.value,
                source_ref=source_ref,
            ),
            source_ref=source_ref,
        )

    if current_body.isExpression():
        current_body = StatementExpressionOnly(expression=current_body,
                                               source_ref=source_ref)

    for count, qual in enumerate(reversed(node.generators)):
        tmp_value_variable = function_body.allocateTempVariable(
            temp_scope=temp_scope, name="iter_value_%d" % count)

        tmp_variables.append(tmp_value_variable)

        # The first iterated value is to be calculated outside of the function
        # and will be given as a parameter "_iterated", the others are built
        # inside the function.

        if qual is node.generators[0]:
            iterator_ref = makeVariableRefNode(variable=iter_tmp,
                                               source_ref=source_ref)

            if for_asyncgen and python_version >= 370:
                iterator_ref = ExpressionYieldFromWaitable(
                    expression=iterator_ref, source_ref=source_ref)

            tmp_iter_variable = None

            nested_statements = []
        else:
            # First create the iterator and store it, next should be loop body
            value_iterator = _makeIteratorCreation(
                provider=provider if assign_provider else function_body,
                qual=qual,
                for_asyncgen=False,
                source_ref=source_ref,
            )

            tmp_iter_variable = function_body.allocateTempVariable(
                temp_scope=temp_scope, name="contraction_iter_%d" % count)

            tmp_variables.append(tmp_iter_variable)

            nested_statements = [
                StatementAssignmentVariable(
                    variable=tmp_iter_variable,
                    source=value_iterator,
                    source_ref=source_ref,
                )
            ]

            iterator_ref = ExpressionTempVariableRef(
                variable=tmp_iter_variable, source_ref=source_ref)

        loop_statements = [
            makeTryExceptSingleHandlerNode(
                tried=StatementAssignmentVariable(
                    variable=tmp_value_variable,
                    source=_makeIteratorNext(iterator_ref=iterator_ref,
                                             qual=qual,
                                             source_ref=source_ref),
                    source_ref=source_ref,
                ),
                exception_name=_getStopIterationName(qual),
                handler_body=StatementLoopBreak(source_ref=source_ref),
                source_ref=source_ref,
            ),
            buildAssignmentStatements(
                provider=provider if assign_provider else function_body,
                temp_provider=function_body,
                node=qual.target,
                source=ExpressionTempVariableRef(variable=tmp_value_variable,
                                                 source_ref=source_ref),
                source_ref=source_ref,
            ),
        ]

        conditions = buildNodeList(
            provider=provider if assign_provider else function_body,
            nodes=qual.ifs,
            source_ref=source_ref,
        )

        if len(conditions) >= 1:
            loop_statements.append(
                makeStatementConditional(
                    condition=buildAndNode(values=conditions,
                                           source_ref=source_ref),
                    yes_branch=current_body,
                    no_branch=None,
                    source_ref=source_ref,
                ))
        else:
            loop_statements.append(current_body)

        nested_statements.append(
            StatementLoop(
                body=StatementsSequence(
                    statements=mergeStatements(loop_statements),
                    source_ref=source_ref),
                source_ref=source_ref,
            ))

        if tmp_iter_variable is not None:
            nested_statements.append(
                StatementReleaseVariable(variable=tmp_iter_variable,
                                         source_ref=source_ref))

        current_body = StatementsSequence(statements=mergeStatements(
            nested_statements, False),
                                          source_ref=source_ref)

    statements.append(current_body)
    statements = mergeStatements(statements)

    release_statements = [
        StatementReleaseVariable(variable=tmp_variable, source_ref=source_ref)
        for tmp_variable in tmp_variables
    ]

    return statements, release_statements
def buildTryExceptionNode(provider, node, source_ref):
    # Try/except nodes. Re-formulated as described in the developer
    # manual. Exception handlers made the assignment to variables explicit. Same
    # for the "del" as done for Python3. Also catches always work a tuple of
    # exception types and hides away that they may be built or not.

    # Many variables and branches, due to the re-formulation that is going on
    # here, which just has the complexity, pylint: disable=too-many-branches,too-many-locals

    tried = buildStatementsNode(provider=provider,
                                nodes=node.body,
                                source_ref=source_ref)

    handlers = []

    for handler in node.handlers:
        exception_expression, exception_assign, exception_block = (
            handler.type,
            handler.name,
            handler.body,
        )

        if exception_assign is None:
            statements = [
                buildStatementsNode(provider=provider,
                                    nodes=exception_block,
                                    source_ref=source_ref)
            ]
        elif python_version < 0x300:
            statements = [
                buildAssignmentStatements(
                    provider=provider,
                    node=exception_assign,
                    source=ExpressionCaughtExceptionValueRef(
                        source_ref=source_ref.atInternal()),
                    source_ref=source_ref.atInternal(),
                ),
                buildStatementsNode(provider=provider,
                                    nodes=exception_block,
                                    source_ref=source_ref),
            ]
        else:
            # Python3 requires temporary assignment of exception assignment.
            target_info = decodeAssignTarget(provider=provider,
                                             node=exception_assign,
                                             source_ref=source_ref)

            kind, detail = target_info

            assert kind == "Name", kind
            kind = "Name_Exception"

            statements = [
                buildAssignmentStatements(
                    provider=provider,
                    node=exception_assign,
                    source=ExpressionCaughtExceptionValueRef(
                        source_ref=source_ref.atInternal()),
                    source_ref=source_ref.atInternal(),
                ),
                makeTryFinallyStatement(
                    provider=provider,
                    tried=buildStatementsNode(provider=provider,
                                              nodes=exception_block,
                                              source_ref=source_ref),
                    final=buildDeleteStatementFromDecoded(
                        provider=provider,
                        kind=kind,
                        detail=detail,
                        source_ref=source_ref,
                    ),
                    source_ref=source_ref,
                ),
            ]

        handler_body = makeStatementsSequence(statements=statements,
                                              allow_none=True,
                                              source_ref=source_ref)

        exception_types = buildNode(
            provider=provider,
            node=exception_expression,
            source_ref=source_ref,
            allow_none=True,
        )

        # The exception types should be a tuple, so as to be most general.
        if exception_types is None:
            if handler is not node.handlers[-1]:
                raiseSyntaxError(
                    "default 'except:' must be last",
                    source_ref.atLineNumber(handler.lineno).atColumnNumber(
                        handler.col_offset),
                )

        handlers.append((exception_types, handler_body))

    # Re-raise by default
    exception_handling = makeReraiseExceptionStatement(source_ref=source_ref)

    for exception_type, handler in reversed(handlers):
        if exception_type is None:
            # A default handler was given, so use that indeed.
            exception_handling = handler
        else:
            exception_handling = StatementsSequence(
                statements=(makeStatementConditional(
                    condition=ExpressionComparisonExceptionMatch(
                        left=ExpressionCaughtExceptionTypeRef(
                            source_ref=exception_type.source_ref),
                        right=exception_type,
                        source_ref=exception_type.source_ref,
                    ),
                    yes_branch=handler,
                    no_branch=exception_handling,
                    source_ref=exception_type.source_ref,
                ), ),
                source_ref=exception_type.source_ref,
            )

    if exception_handling is None:
        # For Python3, we need not publish at all, if all we do is to revert
        # that immediately. For Python2, the publish may release previously
        # published exception, which has side effects potentially.
        if python_version < 0x300:
            exception_handling = StatementsSequence(
                statements=(
                    StatementPreserveFrameException(
                        preserver_id=0,  # unused with Python2
                        source_ref=source_ref.atInternal(),
                    ),
                    StatementPublishException(
                        source_ref=source_ref.atInternal()),
                ),
                source_ref=source_ref.atInternal(),
            )
    else:
        if python_version < 0x300:
            exception_handling.setChild(
                "statements",
                (
                    StatementPreserveFrameException(
                        preserver_id=0,  # unused with Python2
                        source_ref=source_ref.atInternal(),
                    ),
                    StatementPublishException(
                        source_ref=source_ref.atInternal()),
                ) + exception_handling.subnode_statements,
            )
        else:
            preserver_id = provider.allocatePreserverId()

            exception_handling = makeStatementsSequenceFromStatements(
                StatementPreserveFrameException(
                    preserver_id=preserver_id,
                    source_ref=source_ref.atInternal()),
                StatementPublishException(source_ref=source_ref.atInternal()),
                makeTryFinallyStatement(
                    provider=provider,
                    tried=exception_handling,
                    final=StatementRestoreFrameException(
                        preserver_id=preserver_id,
                        source_ref=source_ref.atInternal()),
                    source_ref=source_ref,
                ),
            )

    no_raise = buildStatementsNode(provider=provider,
                                   nodes=node.orelse,
                                   source_ref=source_ref)

    if no_raise is None:
        if tried is None:
            return None

        return StatementTry(
            tried=tried,
            except_handler=exception_handling,
            break_handler=None,
            continue_handler=None,
            return_handler=None,
            source_ref=source_ref,
        )
    else:
        if tried is None:
            return no_raise

        return makeTryExceptNoRaise(
            provider=provider,
            temp_scope=provider.allocateTempScope("try_except"),
            handling=exception_handling,
            tried=tried,
            no_raise=no_raise,
            source_ref=source_ref,
        )
Ejemplo n.º 31
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,
    )
def buildLambdaNode(provider, node, source_ref):
    # Many details to deal with, pylint: disable=too-many-locals

    assert getKind(node) == "Lambda"

    function_kind, flags = detectFunctionBodyKind(nodes=(node.body, ))

    outer_body, function_body, code_object = buildFunctionWithParsing(
        provider=provider,
        function_kind=function_kind,
        name="<lambda>",
        function_doc=None,
        flags=flags,
        node=node,
        source_ref=source_ref,
    )

    if function_kind == "Function":
        code_body = function_body
    else:
        code_body = ExpressionGeneratorObjectBody(
            provider=function_body,
            name="<lambda>",
            code_object=code_object,
            flags=set(),
            source_ref=source_ref,
        )
        code_body.qualname_provider = provider

    if function_kind == "Generator":
        function_body.setBody(
            makeStatementsSequenceFromStatement(statement=StatementReturn(
                expression=ExpressionMakeGeneratorObject(
                    generator_ref=ExpressionFunctionRef(
                        function_body=code_body, source_ref=source_ref),
                    source_ref=source_ref,
                ),
                source_ref=source_ref,
            )))

    defaults = buildNodeList(provider, node.args.defaults, source_ref)
    kw_defaults = buildParameterKwDefaults(provider=provider,
                                           node=node,
                                           function_body=function_body,
                                           source_ref=source_ref)

    body = buildNode(provider=code_body, node=node.body, source_ref=source_ref)

    if function_kind == "Generator":
        if python_version < 270:
            tmp_return_value = code_body.allocateTempVariable(
                temp_scope=None, name="yield_return")

            statements = (
                StatementAssignmentVariable(variable=tmp_return_value,
                                            source=body,
                                            source_ref=source_ref),
                makeStatementConditional(
                    condition=ExpressionComparisonIsNOT(
                        left=ExpressionTempVariableRef(
                            variable=tmp_return_value, source_ref=source_ref),
                        right=ExpressionConstantNoneRef(source_ref=source_ref),
                        source_ref=source_ref,
                    ),
                    yes_branch=StatementExpressionOnly(
                        expression=ExpressionYield(
                            expression=ExpressionTempVariableRef(
                                variable=tmp_return_value,
                                source_ref=source_ref),
                            source_ref=source_ref,
                        ),
                        source_ref=source_ref,
                    ),
                    no_branch=None,
                    source_ref=source_ref,
                ),
            )
            body = makeTryFinallyStatement(
                provider=provider,
                tried=statements,
                final=StatementReleaseVariable(variable=tmp_return_value,
                                               source_ref=source_ref),
                source_ref=source_ref,
            )
        else:
            body = StatementExpressionOnly(expression=body,
                                           source_ref=source_ref)
    else:
        body = StatementReturn(expression=body, source_ref=source_ref)

    if function_kind == "Generator":
        frame_class = StatementsFrameGenerator
    else:
        frame_class = StatementsFrameFunction

    body = frame_class(
        statements=mergeStatements((body, )),
        code_object=code_object,
        source_ref=body.getSourceReference(),
    )

    body = makeStatementsSequenceFromStatement(statement=body)

    code_body.setBody(body)

    annotations = buildParameterAnnotations(provider, node, source_ref)

    return ExpressionFunctionCreation(
        function_ref=ExpressionFunctionRef(function_body=outer_body,
                                           source_ref=source_ref),
        defaults=defaults,
        kw_defaults=kw_defaults,
        annotations=annotations,
        source_ref=source_ref,
    )
Ejemplo n.º 33
0
def _buildWithNode(provider, context_expr, assign_target, body, sync,
                   source_ref):
    # Many details, pylint: disable=too-many-locals
    with_source = buildNode(provider, context_expr, source_ref)

    if python_version < 380 and Options.isFullCompat():
        source_ref = with_source.getCompatibleSourceReference()

    temp_scope = provider.allocateTempScope("with")

    tmp_source_variable = provider.allocateTempVariable(temp_scope=temp_scope,
                                                        name="source")
    tmp_exit_variable = provider.allocateTempVariable(temp_scope=temp_scope,
                                                      name="exit")
    tmp_enter_variable = provider.allocateTempVariable(temp_scope=temp_scope,
                                                       name="enter")
    tmp_indicator_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="indicator")

    statements = (
        buildAssignmentStatements(
            provider=provider,
            node=assign_target,
            allow_none=True,
            source=ExpressionTempVariableRef(variable=tmp_enter_variable,
                                             source_ref=source_ref),
            source_ref=source_ref,
        ),
        body,
    )

    with_body = makeStatementsSequence(statements=statements,
                                       allow_none=True,
                                       source_ref=source_ref)

    if body:
        deepest = body

        while deepest.getVisitableNodes():
            deepest = deepest.getVisitableNodes()[-1]

        if python_version < 370:
            body_lineno = deepest.getCompatibleSourceReference().getLineNumber(
            )
        else:
            body_lineno = deepest.getSourceReference().getLineNumber()

        with_exit_source_ref = source_ref.atLineNumber(body_lineno)
    else:
        with_exit_source_ref = source_ref

    # The "__enter__" and "__exit__" were normal attribute lookups under
    # CPython2.6, but that changed with CPython2.7.
    if python_version < 270:
        attribute_lookup_class = ExpressionAttributeLookup
    else:
        attribute_lookup_class = ExpressionAttributeLookupSpecial

    enter_value = ExpressionCallEmpty(
        called=attribute_lookup_class(
            source=ExpressionTempVariableRef(variable=tmp_source_variable,
                                             source_ref=source_ref),
            attribute_name="__enter__" if sync else "__aenter__",
            source_ref=source_ref,
        ),
        source_ref=source_ref,
    )

    exit_value_exception = ExpressionCallNoKeywords(
        called=ExpressionTempVariableRef(variable=tmp_exit_variable,
                                         source_ref=with_exit_source_ref),
        args=ExpressionMakeTuple(
            elements=(
                ExpressionCaughtExceptionTypeRef(
                    source_ref=with_exit_source_ref),
                ExpressionCaughtExceptionValueRef(
                    source_ref=with_exit_source_ref),
                ExpressionCaughtExceptionTracebackRef(source_ref=source_ref),
            ),
            source_ref=source_ref,
        ),
        source_ref=with_exit_source_ref,
    )

    exit_value_no_exception = ExpressionCallNoKeywords(
        called=ExpressionTempVariableRef(variable=tmp_exit_variable,
                                         source_ref=source_ref),
        args=makeConstantRefNode(constant=(None, None, None),
                                 source_ref=source_ref),
        source_ref=with_exit_source_ref,
    )

    # For "async with", await the entered value and exit value must be awaited.
    if not sync:
        enter_value = ExpressionYieldFromWaitable(
            expression=ExpressionAsyncWaitEnter(expression=enter_value,
                                                source_ref=source_ref),
            source_ref=source_ref,
        )
        exit_value_exception = ExpressionYieldFromWaitable(
            expression=ExpressionAsyncWaitExit(expression=exit_value_exception,
                                               source_ref=source_ref),
            source_ref=source_ref,
        )
        exit_value_no_exception = ExpressionYieldFromWaitable(
            ExpressionAsyncWaitExit(expression=exit_value_no_exception,
                                    source_ref=source_ref),
            source_ref=source_ref,
        )

    statements = [
        # First assign the with context to a temporary variable.
        StatementAssignmentVariable(variable=tmp_source_variable,
                                    source=with_source,
                                    source_ref=source_ref)
    ]

    attribute_assignments = [
        # Next, assign "__enter__" and "__exit__" attributes to temporary
        # variables.
        StatementAssignmentVariable(
            variable=tmp_exit_variable,
            source=attribute_lookup_class(
                source=ExpressionTempVariableRef(variable=tmp_source_variable,
                                                 source_ref=source_ref),
                attribute_name="__exit__" if sync else "__aexit__",
                source_ref=source_ref,
            ),
            source_ref=source_ref,
        ),
        StatementAssignmentVariable(variable=tmp_enter_variable,
                                    source=enter_value,
                                    source_ref=source_ref),
    ]

    if python_version >= 360 and sync:
        attribute_assignments.reverse()

    statements += attribute_assignments

    statements.append(
        StatementAssignmentVariable(
            variable=tmp_indicator_variable,
            source=makeConstantRefNode(constant=True, source_ref=source_ref),
            source_ref=source_ref,
        ))

    statements += [
        makeTryFinallyStatement(
            provider=provider,
            tried=makeTryExceptSingleHandlerNodeWithPublish(
                provider=provider,
                tried=with_body,
                exception_name="BaseException",
                handler_body=StatementsSequence(
                    statements=(
                        # Prevents final block from calling __exit__ as
                        # well.
                        StatementAssignmentVariable(
                            variable=tmp_indicator_variable,
                            source=makeConstantRefNode(constant=False,
                                                       source_ref=source_ref),
                            source_ref=source_ref,
                        ),
                        makeStatementConditional(
                            condition=exit_value_exception,
                            no_branch=makeReraiseExceptionStatement(
                                source_ref=with_exit_source_ref),
                            yes_branch=None,
                            source_ref=with_exit_source_ref,
                        ),
                    ),
                    source_ref=source_ref,
                ),
                public_exc=python_version >= 270,
                source_ref=source_ref,
            ),
            final=makeStatementConditional(
                condition=ExpressionComparisonIs(
                    left=ExpressionTempVariableRef(
                        variable=tmp_indicator_variable,
                        source_ref=source_ref),
                    right=makeConstantRefNode(constant=True,
                                              source_ref=source_ref),
                    source_ref=source_ref,
                ),
                yes_branch=StatementExpressionOnly(
                    expression=exit_value_no_exception, source_ref=source_ref),
                no_branch=None,
                source_ref=source_ref,
            ),
            source_ref=source_ref,
        )
    ]

    return makeTryFinallyStatement(
        provider=provider,
        tried=statements,
        final=(
            StatementReleaseVariable(variable=tmp_source_variable,
                                     source_ref=with_exit_source_ref),
            StatementReleaseVariable(variable=tmp_enter_variable,
                                     source_ref=with_exit_source_ref),
            StatementReleaseVariable(variable=tmp_exit_variable,
                                     source_ref=with_exit_source_ref),
            StatementReleaseVariable(variable=tmp_indicator_variable,
                                     source_ref=with_exit_source_ref),
        ),
        source_ref=source_ref,
    )
Ejemplo n.º 34
0
def buildMatchNode(provider, node, source_ref):
    """Python3.10 or higher, match statements."""

    subject_node = buildNode(provider, node.subject, source_ref)

    temp_scope = provider.allocateTempScope("match_statement")

    # The value matched against, must be released in the end.
    tmp_subject = provider.allocateTempVariable(temp_scope, "subject")

    # Indicator variable, will end up with C bool type, and need not be released.
    tmp_indicator_variable = provider.allocateTempVariable(
        temp_scope=temp_scope, name="indicator", temp_type="bool")

    cases = []

    for case in node.cases:
        cases.append(
            _buildCase(
                provider=provider,
                case=case,
                tmp_subject=tmp_subject,
                source_ref=source_ref,
            ))

    case_statements = []

    for case in cases:
        conditions, assignments, guard, branch_code = case

        # Set indicator variable at end of branch code, unless it's last branch
        # where there would be no usage of it.
        if case is not cases[-1]:
            branch_code = makeStatementsSequence(
                statements=(
                    branch_code,
                    StatementAssignmentVariable(
                        variable=tmp_indicator_variable,
                        source=makeConstantRefNode(constant=True,
                                                   source_ref=source_ref),
                        source_ref=source_ref,
                    ),
                ),
                allow_none=True,
                source_ref=source_ref,
            )

        if guard is not None:
            branch_code = makeStatementConditional(
                condition=guard,
                yes_branch=branch_code,
                no_branch=None,
                source_ref=source_ref,
            )

        del guard

        branch_code = makeStatementsSequence(
            statements=(assignments, branch_code),
            allow_none=True,
            source_ref=source_ref,
        )

        del assignments

        if conditions is not None:
            branch_code = makeStatementConditional(
                condition=makeAndNode(values=conditions,
                                      source_ref=source_ref),
                yes_branch=branch_code,
                no_branch=None,
                source_ref=source_ref,
            )

        del conditions

        if case is not cases[0]:
            statement = makeStatementConditional(
                condition=makeComparisonExpression(
                    comparator="Is",
                    left=ExpressionTempVariableRef(
                        variable=tmp_indicator_variable,
                        source_ref=source_ref),
                    right=makeConstantRefNode(constant=False,
                                              source_ref=source_ref),
                    source_ref=source_ref,
                ),
                yes_branch=branch_code,
                no_branch=None,
                source_ref=source_ref,
            )