Пример #1
0
    def computeExpressionRaw(self, constraint_collection):
        # The tried block must be considered as a branch, if it is not empty
        # already.
        tried_statement_sequence = self.getBlockTry()

        # May be "None" from the outset, so guard against that, later in this
        # function we are going to remove it.
        if tried_statement_sequence is not None:
            result = tried_statement_sequence.computeStatementsSequence(
                constraint_collection = constraint_collection
            )

            # Might be changed.
            if result is not tried_statement_sequence:
                self.setBlockTry(result)
                tried_statement_sequence = result

        # The main expression itself.
        constraint_collection.onExpression(self.getExpression())

        final_statement_sequence = self.getBlockFinal()

        # TODO: The final must not assume that all of tried was executed,
        # instead it may have aborted after any part of it, which is a rather
        # complex definition.

        if final_statement_sequence is not None:
            collection_exception_handling = ConstraintCollectionBranch(
                parent = constraint_collection,
            )

            if tried_statement_sequence is not None:
                # Mark all variables as unknown that are written in the tried
                # block, so it destroys the assumptions for loop turn around.
                collection_exception_handling.degradePartiallyFromCode(tried_statement_sequence)

            # In case there are assignments hidden in the expression too.
            collection_exception_handling.degradePartiallyFromCode(self.getExpression())

            # Then assuming no exception, the no raise block if present.
            result = final_statement_sequence.computeStatementsSequence(
                constraint_collection = collection_exception_handling
            )

            if result is not final_statement_sequence:
                self.setBlockFinal(result)

                final_statement_sequence = result

        if tried_statement_sequence is None and \
           final_statement_sequence is None:
            # If the tried and final block is empty, go to the expression
            # directly.
            return self.getExpression(), "new_expression", """\
Removed try/finally expression with empty tried and final block."""
        else:
            if final_statement_sequence is not None:
                # Otherwise keep it as it, merging the finally block back into
                # the constraint collection.
                constraint_collection.mergeBranches(
                    collection_yes = collection_exception_handling,
                    collection_no  = None
                )


            # Otherwise keep it as it.
            return self, None, None
Пример #2
0
    def computeStatement(self, constraint_collection):
        # The tried block can be processed normally.
        tried_statement_sequence = self.getBlockTry()

        # May be "None" from the outset, so guard against that, later we are
        # going to remove it.
        if tried_statement_sequence is not None:
            result = tried_statement_sequence.computeStatementsSequence(
                constraint_collection = constraint_collection
            )

            if result is not tried_statement_sequence:
                self.setBlockTry(result)

                tried_statement_sequence = result

        if tried_statement_sequence is None:
            return None, "new_statements", """\
Removed try/except with empty tried block."""


        collection_exception_handling = ConstraintCollectionBranch(
            parent = constraint_collection,
        )

        collection_exception_handling.degradePartiallyFromCode(tried_statement_sequence)

        if self.getExceptionHandling() is not None:
            collection_exception_handling.computeBranch(
                branch = self.getExceptionHandling()
            )


        # Merge only, if the exception handling itself does exit.
        if self.getExceptionHandling() is None or \
           not self.getExceptionHandling().isStatementAborting():

            constraint_collection.mergeBranches(
                collection_yes = collection_exception_handling,
                collection_no  = None
            )

        # Without exception handlers remaining, nothing else to do. They may
        # e.g. be removed as only re-raising.
        if self.getExceptionHandling() and \
           self.getExceptionHandling().getStatements()[0].\
             isStatementReraiseException():
            return tried_statement_sequence, "new_statements", """\
Removed try/except without any remaining handlers."""

        # Remove exception handling, if it cannot happen.
        if not tried_statement_sequence.mayRaiseException(BaseException):
            return tried_statement_sequence, "new_statements", """\
Removed try/except with tried block that cannot raise."""

        new_statements = tried_statement_sequence.getStatements()
        # Determine statements inside the exception guard, that need not be in
        # a handler, because they wouldn't raise an exception. TODO: This
        # actual exception being watched for should be considered, by look
        # for any now.
        outside_pre = []
        while new_statements and \
              not new_statements[0].mayRaiseException(BaseException):
            outside_pre.append(new_statements[0])
            new_statements = list(new_statements)[1:]

        outside_post = []
        if self.getExceptionHandling() is not None and \
           self.getExceptionHandling().isStatementAborting():
            while new_statements and \
                  not new_statements[-1].mayRaiseException(BaseException):
                outside_post.insert(0, new_statements[-1])
                new_statements = list(new_statements)[:-1]

        if outside_pre or outside_post:
            tried_statement_sequence.setStatements(new_statements)

            from .NodeMakingHelpers import makeStatementsSequenceReplacementNode

            result = makeStatementsSequenceReplacementNode(
                statements = outside_pre + [self] + outside_post,
                node       = self
            )

            return result, "new_statements", """\
Moved statements of tried block that cannot raise."""

        return self, None, None
Пример #3
0
    def computeStatement(self, constraint_collection):
        # The tried block must be considered as a branch, if it is not empty
        # already.
        tried_statement_sequence = self.getBlockTry()

        # May be "None" from the outset, so guard against that, later in this
        # function we are going to remove it.
        if tried_statement_sequence is not None:
            result = tried_statement_sequence.computeStatementsSequence(
                constraint_collection = constraint_collection
            )

            # Might be changed.
            if result is not tried_statement_sequence:
                self.setBlockTry(result)
                tried_statement_sequence = result

        final_statement_sequence = self.getBlockFinal()

        if final_statement_sequence is not None:
            # TODO: The must not assume that all of tried was executed, instead
            # it may have aborted after any part of it, which is a rather
            # a complex situation, so we just invalidate all writes.

            collection_exception_handling = ConstraintCollectionBranch(
                parent = constraint_collection,
            )

            if tried_statement_sequence is not None:
                collection_exception_handling.degradePartiallyFromCode(tried_statement_sequence)

            # Then assuming no exception, the no raise block if present.
            result = final_statement_sequence.computeStatementsSequence(
                constraint_collection = collection_exception_handling
            )

            if result is not final_statement_sequence:
                self.setBlockFinal(result)
                final_statement_sequence = result

            # If we are not aborting, we need to merge.
            if not self.isStatementAborting():
                # Merge back as a branch.
                constraint_collection.mergeBranches(
                    collection_yes = collection_exception_handling,
                    collection_no  = None
                )

        if tried_statement_sequence is None:
            # If the tried block is empty, go to the final block directly, if
            # any.
            return final_statement_sequence, "new_statements", """\
Removed try/finally with empty tried block."""
        elif final_statement_sequence is None:
            # If the final block is empty, just need to execute the tried block
            # then.
            return tried_statement_sequence, "new_statements", """\
Removed try/finally with empty final block."""
        elif not tried_statement_sequence.mayRaiseExceptionOrAbort(
                BaseException
            ):
            # There may be no need to try/finally at all then. TODO: The code
            # below, which reduces the scope, could do this too, but would be
            # less elegant in its report.

            tried_statement_sequence.setChild(
                "statements",
                tried_statement_sequence.getStatements() +
                final_statement_sequence.getStatements()
            )

            return tried_statement_sequence, "new_statements", """\
Removed try/finally with try block that cannot raise."""
        else:
            new_statements = tried_statement_sequence.getStatements()
            # Determine statements inside the exception guard, that need not be in
            # a handler, because they wouldn't raise an exception. TODO: This
            # actual exception being watched for should be considered, by look
            # for any now.
            outside_pre = []
            while new_statements and \
                  not new_statements[0].mayRaiseException(BaseException) and \
                  not new_statements[0].mayReturn() and \
                  not new_statements[0].mayBreak() and \
                  not new_statements[0].mayContinue():

                outside_pre.append(new_statements[0])
                new_statements = list(new_statements)[1:]

            if outside_pre:
                tried_statement_sequence.setStatements(new_statements)

                from .NodeMakingHelpers import makeStatementsSequenceReplacementNode

                result = makeStatementsSequenceReplacementNode(
                    statements = outside_pre + [self],
                    node       = self
                )

                return result, "new_statements", """\
Moved statements of tried block that cannot abort to the outside."""

            return self, None, None
Пример #4
0
    def computeStatement(self, constraint_collection):
        # The tried block can be processed normally.
        tried_statement_sequence = self.getBlockTry()

        # May be "None" from the outset, so guard against that, later we are
        # going to remove it.
        if tried_statement_sequence is not None:
            result = tried_statement_sequence.computeStatementsSequence(constraint_collection=constraint_collection)

            if result is not tried_statement_sequence:
                self.setBlockTry(result)

                tried_statement_sequence = result

        if tried_statement_sequence is None:
            return (
                None,
                "new_statements",
                """\
Removed try/except with empty tried block.""",
            )

        collection_exception_handling = ConstraintCollectionBranch(parent=constraint_collection)

        collection_exception_handling.degradePartiallyFromCode(tried_statement_sequence)

        if self.getExceptionHandling() is not None:
            collection_exception_handling.computeBranch(branch=self.getExceptionHandling())

        # Merge only, if the exception handling itself does exit.
        if self.getExceptionHandling() is None or not self.getExceptionHandling().isStatementAborting():

            constraint_collection.mergeBranches(collection_yes=collection_exception_handling, collection_no=None)

        # Without exception handlers remaining, nothing else to do. They may
        # e.g. be removed as only re-raising.
        if self.getExceptionHandling() and self.getExceptionHandling().getStatements()[0].isStatementReraiseException():
            return (
                tried_statement_sequence,
                "new_statements",
                """\
Removed try/except without any remaining handlers.""",
            )

        # Remove exception handling, if it cannot happen.
        if not tried_statement_sequence.mayRaiseException(BaseException):
            return (
                tried_statement_sequence,
                "new_statements",
                """\
Removed try/except with tried block that cannot raise.""",
            )

        new_statements = tried_statement_sequence.getStatements()
        # Determine statements inside the exception guard, that need not be in
        # a handler, because they wouldn't raise an exception. TODO: This
        # actual exception being watched for should be considered, by look
        # for any now.
        outside_pre = []
        while new_statements and not new_statements[0].mayRaiseException(BaseException):
            outside_pre.append(new_statements[0])
            new_statements = list(new_statements)[1:]

        outside_post = []
        if self.getExceptionHandling() is not None and self.getExceptionHandling().isStatementAborting():
            while new_statements and not new_statements[-1].mayRaiseException(BaseException):
                outside_post.insert(0, new_statements[-1])
                new_statements = list(new_statements)[:-1]

        if outside_pre or outside_post:
            tried_statement_sequence.setStatements(new_statements)

            from .NodeMakingHelpers import makeStatementsSequenceReplacementNode

            result = makeStatementsSequenceReplacementNode(statements=outside_pre + [self] + outside_post, node=self)

            return (
                result,
                "new_statements",
                """\
Moved statements of tried block that cannot raise.""",
            )

        return self, None, None