[pypy-svn] r10939 - in pypy/dist/pypy: objspace/flow translator

arigo at codespeak.net arigo at codespeak.net
Wed Apr 20 19:59:23 CEST 2005


Author: arigo
Date: Wed Apr 20 19:59:23 2005
New Revision: 10939

Modified:
   pypy/dist/pypy/objspace/flow/objspace.py
   pypy/dist/pypy/translator/annrpython.py
Log:
CanOnlyRaise wasn't a good idea.  Now we return again SomeImpossibleValue() 
for functions that can only raise exceptions, and there is special treatment 
for the call_args and simple_call operations.



Modified: pypy/dist/pypy/objspace/flow/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/objspace.py	(original)
+++ pypy/dist/pypy/objspace/flow/objspace.py	Wed Apr 20 19:59:23 2005
@@ -348,6 +348,7 @@
             args_w, kwds_w = args.unpack()
         except UnwrapException:
             args_w, kwds_w = '?', '?'
+        # NOTE: annrpython needs to know about the following two operations!
         if not kwds_w:
             # simple case
             w_res = self.do_operation('simple_call', w_callable, *args_w)

Modified: pypy/dist/pypy/translator/annrpython.py
==============================================================================
--- pypy/dist/pypy/translator/annrpython.py	(original)
+++ pypy/dist/pypy/translator/annrpython.py	Wed Apr 20 19:59:23 2005
@@ -228,8 +228,7 @@
         except KeyError: 
             # the function didn't reach any return statement so far.
             # (some functions actually never do, they always raise exceptions)
-            # interrupt the annotation of the caller in a 'soft' way.
-            raise CanOnlyRaise
+            return annmodel.SomeImpossibleValue()
 
     def reflowfromposition(self, position_key):
         fn, block, index = position_key
@@ -303,11 +302,6 @@
             #import traceback, sys
             #traceback.print_tb(sys.exc_info()[2])
             self.annotated[block] = False   # failed, hopefully temporarily
-            if annmodel.DEBUG:
-                import sys
-                self.why_not_annotated[block] = sys.exc_info()
-        except CanOnlyRaise:
-            pass   # end of the block not annotated, but it's not an error
         except Exception, e:
             # hack for debug tools only
             if not hasattr(e, '__annotator_block'):
@@ -358,7 +352,6 @@
 
     def flowin(self, fn, block):
         #print 'Flowing', block, [self.binding(a) for a in block.inputargs]
-        i = -1
         try:
             for i in range(len(block.operations)):
                 try:
@@ -366,15 +359,33 @@
                     self.consider_op(block.operations[i])
                 finally:
                     self.bookkeeper.leave()
-        except (BlockedInference, CanOnlyRaise):
-            if (i != len(block.operations)-1 or
-                block.exitswitch != Constant(last_exception)):
+
+        except BlockedInference, e:
+            if annmodel.DEBUG:
+                import sys
+                self.why_not_annotated[block] = sys.exc_info()
+
+            if (e.op is block.operations[-1] and
+                block.exitswitch == Constant(last_exception)):
+                # this is the case where the last operation of the block will
+                # always raise an exception which is immediately caught by
+                # an exception handler.  We then only follow the exceptional
+                # branches.
+                exits = [link for link in block.exits
+                              if link.exitcase is not None]
+
+            elif e.op.opname in ('simple_call', 'call_args'):
+                # XXX warning, keep the name of the call operations in sync
+                # with the flow object space.  These are the operations for
+                # which it is fine to always raise an exception.  We then
+                # swallow the BlockedInference and that's it.
+                return
+
+            else:
+                # other cases are problematic (but will hopefully be solved
+                # later by reflowing).  Throw the BlockedInference up to
+                # processblock().
                 raise
-            # this is the case where the last operation of the block can
-            # only raise an exception, which is caught by an exception
-            # handler.  we only follow the exceptional branches.
-            exits = [link for link in block.exits
-                     if link.exitcase is not None]
         else:
             # dead code removal: don't follow all exits if the exitswitch
             # is known
@@ -450,12 +461,12 @@
         # boom -- in the assert of setbinding()
         for arg in argcells:
             if isinstance(arg, annmodel.SomeImpossibleValue):
-                raise BlockedInference(self, info=op)
+                raise BlockedInference(self, op)
         resultcell = consider_meth(*argcells)
         if resultcell is None:
             resultcell = annmodel.SomeImpossibleValue()  # no return value
         elif resultcell == annmodel.SomeImpossibleValue():
-            raise BlockedInference(self, info=op) # the operation cannot succeed
+            raise BlockedInference(self, op) # the operation cannot succeed
         assert isinstance(resultcell, annmodel.SomeObject)
         assert isinstance(op.result, Variable)
         self.setbinding(op.result, resultcell)  # bind resultcell to op.result
@@ -509,30 +520,19 @@
     """This exception signals the type inference engine that the situation
     is currently blocked, and that it should try to progress elsewhere."""
 
-    def __init__(self, annotator, info=None):
+    def __init__(self, annotator, op):
         self.annotator = annotator
         try:
             self.break_at = annotator.bookkeeper.position_key
         except AttributeError:
             self.break_at = None
-        self.info = info
+        self.op = op
 
     def __repr__(self):
-        if self.info:
-            info = "[%s]" % self.info
-        else:
-            info = ""
         if not self.break_at:
             break_at = "?"
         else:
             break_at = self.annotator.whereami(self.break_at)
-        return "<BlockedInference break_at %s %s>" %(break_at, info)
+        return "<BlockedInference break_at %s [%s]>" %(break_at, self.op)
 
     __str__ = __repr__
-
-
-class CanOnlyRaise(Exception):
-    """A soft version of BlockedInference: the inference should not continue
-    in the current block, but this not necessarily an error: if the current
-    block never progresses past this point, then it means that the current
-    operation will always raise an exception at run-time."""



More information about the Pypy-commit mailing list