[pypy-commit] pypy exc-later: Use annotations to represent the exception behaviour of operations

rlamy noreply at buildbot.pypy.org
Sun Nov 22 13:00:01 EST 2015


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: exc-later
Changeset: r80833:9c9c044a9aff
Date: 2015-11-22 01:50 +0000
http://bitbucket.org/pypy/pypy/changeset/9c9c044a9aff/

Log:	Use annotations to represent the exception behaviour of operations

diff --git a/rpython/annotator/annrpython.py b/rpython/annotator/annrpython.py
--- a/rpython/annotator/annrpython.py
+++ b/rpython/annotator/annrpython.py
@@ -11,7 +11,7 @@
 from rpython.translator import simplify, transform
 from rpython.annotator import model as annmodel, signature
 from rpython.annotator.model import (
-        typeof, SomeExceptCase, s_ImpossibleValue)
+        typeof, SomeExceptCase, s_ImpossibleValue, SomeInstance)
 from rpython.annotator.bookkeeper import Bookkeeper
 from rpython.rtyper.normalizecalls import perform_normalizations
 
@@ -488,31 +488,20 @@
 
         if block.canraise:
             op = block.raising_op
-            can_only_throw = op.get_can_only_throw(self)
-            if can_only_throw is not None:
-                # filter out those exceptions which cannot
-                # occur for this specific, typed operation.
-                s_exception = self.bookkeeper.new_exception(can_only_throw)
-                for link in exits:
-                    case = link.exitcase
-                    if case is None:
-                        self.follow_link(graph, link, {})
-                        continue
-                    if s_exception == s_ImpossibleValue:
-                        break
-                    s_case = SomeExceptCase(
-                            self.bookkeeper.getuniqueclassdef(case))
-                    s_matching_exc = s_exception.intersection(s_case)
-                    if s_matching_exc != s_ImpossibleValue:
-                        self.follow_raise_link(graph, link, s_matching_exc)
-                    s_exception = s_exception.difference(s_case)
-            else:
-                for link in exits:
-                    if link.exitcase is None:
-                        self.follow_link(graph, link, {})
-                    else:
-                        s_exception = self.bookkeeper.valueoftype(link.exitcase)
-                        self.follow_raise_link(graph, link, s_exception)
+            s_exception = self.get_exception(op)
+            for link in exits:
+                case = link.exitcase
+                if case is None:
+                    self.follow_link(graph, link, {})
+                    continue
+                if s_exception == s_ImpossibleValue:
+                    break
+                s_case = SomeExceptCase(
+                        self.bookkeeper.getuniqueclassdef(case))
+                s_matching_exc = s_exception.intersection(s_case)
+                if s_matching_exc != s_ImpossibleValue:
+                    self.follow_raise_link(graph, link, s_matching_exc)
+                s_exception = s_exception.difference(s_case)
         else:
             if isinstance(block.exitswitch, Variable):
                 knowntypedata = getattr(block.exitswitch.annotation,
@@ -615,6 +604,16 @@
         assert isinstance(op.result, Variable)
         self.setbinding(op.result, resultcell)  # bind resultcell to op.result
 
+    def get_exception(self, operation):
+        """
+        Return the annotation for all exceptions that `operation` may raise.
+        """
+        can_only_throw = operation.get_can_only_throw(self)
+        if can_only_throw is None:
+            return SomeInstance(self.bookkeeper.getuniqueclassdef(Exception))
+        else:
+            return self.bookkeeper.new_exception(can_only_throw)
+
 
 class BlockedInference(Exception):
     """This exception signals the type inference engine that the situation
diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py
--- a/rpython/annotator/model.py
+++ b/rpython/annotator/model.py
@@ -445,6 +445,22 @@
         else:
             return None
 
+    def intersection(self, other):
+        assert isinstance(other, SomeExceptCase)
+        if self.classdef.issubclass(other.case):
+            return self
+        elif other.case.issubclass(self.classdef):
+            return SomeInstance(other.case)
+        else:
+            return s_ImpossibleValue
+
+    def difference(self, other):
+        assert isinstance(other, SomeExceptCase)
+        if self.classdef.issubclass(other.case):
+            return s_ImpossibleValue
+        else:
+            return self
+
     def can_be_none(self):
         return self.can_be_None
 


More information about the pypy-commit mailing list