[pypy-svn] r10874 - in pypy/branch/canonlyraise-pypy: . annotation objspace/flow translator

arigo at codespeak.net arigo at codespeak.net
Tue Apr 19 21:20:21 CEST 2005


Author: arigo
Date: Tue Apr 19 21:20:21 2005
New Revision: 10874

Added:
   pypy/branch/canonlyraise-pypy/
      - copied from r10864, pypy/dist/pypy/
Modified:
   pypy/branch/canonlyraise-pypy/annotation/binaryop.py
   pypy/branch/canonlyraise-pypy/annotation/builtin.py
   pypy/branch/canonlyraise-pypy/annotation/model.py
   pypy/branch/canonlyraise-pypy/objspace/flow/model.py
   pypy/branch/canonlyraise-pypy/translator/ann_override.py
   pypy/branch/canonlyraise-pypy/translator/annrpython.py
   pypy/branch/canonlyraise-pypy/translator/transform.py
Log:
Very temporary branch to share work in progress.


Modified: pypy/branch/canonlyraise-pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/branch/canonlyraise-pypy/annotation/binaryop.py	Tue Apr 19 21:20:21 2005
@@ -382,10 +382,6 @@
         result =  SomePBC(d)
         return result
 
-class __extend__(pairtype(SomeImpossibleValue, SomeImpossibleValue)):
-    def union((imp1, imp2)):
-        return SomeImpossibleValue(benign=imp1.benign and imp2.benign)
-
 class __extend__(pairtype(SomeImpossibleValue, SomeObject)):
     def union((imp1, obj2)):
         return obj2

Modified: pypy/branch/canonlyraise-pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/branch/canonlyraise-pypy/annotation/builtin.py	Tue Apr 19 21:20:21 2005
@@ -66,7 +66,8 @@
                     r.const = isinstance(s_obj.const, long)
                 else:
                     if type(s_obj) is not SomeObject: # only SomeObjects could be longs
-                        r.const = False
+                        pass # r.const = False -- XXX can't do this,
+                             # could break the assert in AnnRPython.setbinding
                 return r
                 
             assert not issubclass(typ, (int,long)) or typ in (bool, int), (

Modified: pypy/branch/canonlyraise-pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/branch/canonlyraise-pypy/annotation/model.py	Tue Apr 19 21:20:21 2005
@@ -253,13 +253,11 @@
 class SomeImpossibleValue(SomeObject):
     """The empty set.  Instances are placeholders for objects that
     will never show up at run-time, e.g. elements of an empty list."""
-    def __init__(self, benign=False):
-        self.benign = benign
 
 
 def unionof(*somevalues):
     "The most precise SomeValue instance that contains all the values."
-    s1 = SomeImpossibleValue(benign=len(somevalues)>0)
+    s1 = SomeImpossibleValue()
     for s2 in somevalues:
         if s1 != s2:
             s1 = pair(s1, s2).union()

Modified: pypy/branch/canonlyraise-pypy/objspace/flow/model.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/model.py	(original)
+++ pypy/branch/canonlyraise-pypy/objspace/flow/model.py	Tue Apr 19 21:20:21 2005
@@ -26,21 +26,21 @@
     def getreturnvar(self):
         return self.returnblock.inputargs[0]
 
-    def hasonlyexceptionreturns(self):
-        try:
-            return self._onlyex
-        except AttributeError: 
-            def visit(link):
-                if isinstance(link, Link):
-                    if link.target == self.returnblock: 
-                        raise ValueError(link) 
-            try:
-                traverse(visit, self)
-            except ValueError:
-                self._onlyex = False 
-            else:
-                self._onlyex = True
-            return self._onlyex 
+##    def hasonlyexceptionreturns(self):
+##        try:
+##            return self._onlyex
+##        except AttributeError: 
+##            def visit(link):
+##                if isinstance(link, Link):
+##                    if link.target == self.returnblock: 
+##                        raise ValueError(link) 
+##            try:
+##                traverse(visit, self)
+##            except ValueError:
+##                self._onlyex = False 
+##            else:
+##                self._onlyex = True
+##            return self._onlyex 
 
     def show(self):
         from pypy.translator.tool.graphpage import SingleGraphPage

Modified: pypy/branch/canonlyraise-pypy/translator/ann_override.py
==============================================================================
--- pypy/dist/pypy/translator/ann_override.py	(original)
+++ pypy/branch/canonlyraise-pypy/translator/ann_override.py	Tue Apr 19 21:20:21 2005
@@ -10,7 +10,7 @@
 from pypy.objspace.std.objspace import StdObjSpace
 
 def hole(*args):
-    return annmodel.SomeImpossibleValue(benign=True)
+    pass   # no result (similar to setattr and setitem)
 
 def ignore(*args):
     bk = getbookkeeper()

Modified: pypy/branch/canonlyraise-pypy/translator/annrpython.py
==============================================================================
--- pypy/dist/pypy/translator/annrpython.py	(original)
+++ pypy/branch/canonlyraise-pypy/translator/annrpython.py	Tue Apr 19 21:20:21 2005
@@ -226,13 +226,10 @@
         try:
             return self.bindings[v]
         except KeyError: 
-            # let's see if the graph only has exception returns 
-            if graph.hasonlyexceptionreturns(): 
-                # XXX for functions with exceptions what to 
-                #     do anyway? 
-                #return self.bookkeeper.immutablevalue(None)
-                return annmodel.SomeImpossibleValue(benign=True)
-            return annmodel.SomeImpossibleValue()
+            # 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 CanOnlyRaiseException
 
     def reflowfromposition(self, position_key):
         fn, block, index = position_key
@@ -309,6 +306,8 @@
             if annmodel.DEBUG:
                 import sys
                 self.why_not_annotated[block] = sys.exc_info()
+        except CanOnlyRaiseException:
+            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'):
@@ -430,14 +429,12 @@
         argcells = [self.binding(a) for a in op.args]
         consider_meth = getattr(self,'consider_op_'+op.opname,
                                 self.default_consider_op)
-        # because benign SomeImpossibleValues are meant to propagate without leaving
-        # dangling blocked blocks around, and because of the None case below,
         # let's be careful about avoiding propagated SomeImpossibleValues
         # to enter an op; the latter can result in violations of the
         # more general results invariant: e.g. if SomeImpossibleValue enters is_
         #  is_(SomeImpossibleValue, None) -> SomeBool
         #  is_(SomeInstance(not None), None) -> SomeBool(const=False) ...
-        # boom
+        # boom -- in the assert of setbinding()
         for arg in argcells:
             if isinstance(arg, annmodel.SomeImpossibleValue):
                 raise BlockedInference(self, info=op)
@@ -519,3 +516,10 @@
         return "<BlockedInference break_at %s %s>" %(break_at, info)
 
     __str__ = __repr__
+
+
+class CanOnlyRaiseException(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."""

Modified: pypy/branch/canonlyraise-pypy/translator/transform.py
==============================================================================
--- pypy/dist/pypy/translator/transform.py	(original)
+++ pypy/branch/canonlyraise-pypy/translator/transform.py	Tue Apr 19 21:20:21 2005
@@ -265,6 +265,36 @@
                 if len(block.exits) == 1:
                     block.exitswitch = None
                     block.exits[0].exitcase = None
+                elif len(block.exits) == 0:
+                    # this is the CanOnlyRaiseException case.
+                    # search the operation that cannot succeed
+                    can_succeed    = [op for op in block.operations
+                                         if op.result in self.bindings]
+                    cannot_succeed = [op for op in block.operations
+                                         if op.result not in self.bindings]
+                    n = len(can_succeed)
+                    # check consistency
+                    assert can_succeed == block.operations[:n]
+                    assert cannot_succeed == block.operations[n:]
+                    assert 0 <= n < len(block.operations)
+                    # chop off the unreachable end of the block
+                    del block.operations[n+1:]
+                    s_none = annmodel.SomePBC({None: True})
+                    self.bindings[block.operations[n].result] = s_none
+                    # insert the equivalent of 'raise SystemError'
+                    # XXX no sane way to get the graph from the block!
+                    fn = self.annotated[block]
+                    assert fn in self.translator.flowgraphs, (
+                        "Cannot find the graph that this block belong to! "
+                        "fn=%r" % (fn,))
+                    graph = self.translator.flowgraphs[fn]
+                    c1 = Constant(SystemError)
+                    c2 = Constant(SystemError(
+                        "Call to %r should have raised an exception" % (fn,)))
+                    errlink = Link([c1, c2], graph.exceptblock)
+                    block.recloseblock(errlink)
+                    # XXX do something about the annotation of the
+                    #     exceptblock.inputargs
 
 
 def transform_graph(ann):



More information about the Pypy-commit mailing list