[pypy-svn] r9502 - in pypy/dist/pypy: annotation objspace/flow translator translator/test translator/tool

pedronis at codespeak.net pedronis at codespeak.net
Fri Feb 25 16:38:27 CET 2005


Author: pedronis
Date: Fri Feb 25 16:38:27 2005
New Revision: 9502

Modified:
   pypy/dist/pypy/annotation/binaryop.py
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/objspace/flow/flowcontext.py
   pypy/dist/pypy/objspace/flow/model.py
   pypy/dist/pypy/objspace/flow/objspace.py
   pypy/dist/pypy/translator/annrpython.py
   pypy/dist/pypy/translator/test/snippet.py
   pypy/dist/pypy/translator/test/test_annrpython.py
   pypy/dist/pypy/translator/test/test_pyrextrans.py
   pypy/dist/pypy/translator/tool/make_dot.py
Log:
- added another test involving exception handling

improved annotation of ex handling code: we pass this and yesterday added test,

notice that the improved logic works only on simplfied flow graph (changed some tests to respect this),

(I have added code that mark a block starting exc handling, thinking I could have needed the info,
right now it seems not the case)

- changed a bit the way we deal with functions never returning but only raising exceptions,

may want to write a test to see whether this effectively helps with the kind of code involved
in multimethods failing paths.



Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/dist/pypy/annotation/binaryop.py	Fri Feb 25 16:38:27 2005
@@ -36,6 +36,10 @@
             return obj1
         else:
             result = SomeObject()
+            is_type_of1 = getattr(obj1, 'is_type_of', None)
+            is_type_of2 = getattr(obj2, 'is_type_of', None)
+            if is_type_of1 and is_type_of1 == is_type_of2:
+                result.is_type_of = is_type_of1
             # try to preserve the origin of SomeObjects
             if obj1 == result:
                 return obj1
@@ -292,7 +296,16 @@
                 if isclassdef(classdef):
                     classdef = classdef.commonbase(d[x])
             d[x] = classdef
-        return SomePBC(d)
+        result =  SomePBC(d)
+        is_type_of1 = getattr(pbc1, 'is_type_of', None)
+        is_type_of2 = getattr(pbc2, 'is_type_of', None)
+        if is_type_of1 and is_type_of1 == is_type_of2:
+            result.is_type_of = is_type_of1
+        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)):

Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Fri Feb 25 16:38:27 2005
@@ -243,11 +243,13 @@
 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()
+    s1 = SomeImpossibleValue(benign=len(somevalues)>0)
     for s2 in somevalues:
         if s1 != s2:
             s1 = pair(s1, s2).union()

Modified: pypy/dist/pypy/objspace/flow/flowcontext.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/flowcontext.py	(original)
+++ pypy/dist/pypy/objspace/flow/flowcontext.py	Fri Feb 25 16:38:27 2005
@@ -196,11 +196,11 @@
             w_condition,)
 
     def guessexception(self, *classes):
-        outcome = self.guessbool(Constant(last_exception),
+        outcome = self.guessbool(Constant(last_exception, last_exception=True),
                                  cases = [None] + list(classes),
                                  replace_last_variable_except_in_first_case = [
-                                     Constant(last_exception),   # exc. class
-                                     Constant(last_exc_value)])  # exc. value
+                                     Constant(last_exception, last_exception=True),   # exc. class
+                                     Constant(last_exc_value, last_exc_value=True)])  # exc. value
         if outcome is None:
             w_exc_cls, w_exc_value = None, None
         else:

Modified: pypy/dist/pypy/objspace/flow/model.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/model.py	(original)
+++ pypy/dist/pypy/objspace/flow/model.py	Fri Feb 25 16:38:27 2005
@@ -67,11 +67,15 @@
                                           #  Constant(last_exception), see below
         self.exits      = []              # list of Link(s)
 
+        self.exc_handler = False          # block at the start of exception handling code
+
     def __str__(self):
         if self.operations:
             txt = "block@%d" % self.operations[0].offset
         else:
             txt = "codeless block"
+        if self.exc_handler:
+            txt = text +" EH"
         return txt
     
     def __repr__(self):
@@ -150,7 +154,7 @@
 
 
 class Constant:
-    def __init__(self, value):
+    def __init__(self, value, **flags):
         self.value = value     # a concrete value
         # try to be smart about constant mutable or immutable values
         key = type(self.value), self.value  # to avoid confusing e.g. 0 and 0.0
@@ -159,7 +163,11 @@
         except TypeError:
             key = id(self.value)
         self.key = key
-
+        if not flags:
+            self.flags = None
+        else:
+            self.flags = flags
+            
     def __eq__(self, other):
         return self.__class__ is other.__class__ and self.key == other.key
 
@@ -169,6 +177,9 @@
     def __hash__(self):
         return hash(self.key)
 
+    def has_flag(self, flag_name):
+        return self.flags and flag_name in self.flags
+
     def __repr__(self):
         # try to limit the size of the repr to make it more readable
         r = repr(self.value)
@@ -177,7 +188,12 @@
             r = '%s %s' % (type(self.value).__name__, self.value.__name__)
         elif len(r) > 60 or (len(r) > 30 and type(self.value) is not str):
             r = r[:20] + '...' + r[-8:]
-        return '(%s)' % r
+        if self.flags:
+            flags = ' '.join([':'+f for f in self.flags.keys()])
+            flags = ' '+flags
+        else:
+            flags = ''
+        return '(%s%s)' % (r, flags)
 
 # hack! it is useful to have UNDEFINED be an instance of Constant too.
 # PyFrame then automatically uses this Constant as a marker for

Modified: pypy/dist/pypy/objspace/flow/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/objspace.py	(original)
+++ pypy/dist/pypy/objspace/flow/objspace.py	Fri Feb 25 16:38:27 2005
@@ -164,6 +164,11 @@
         from pypy.objspace.flow import specialcase
         specialcase.setup(self)
 
+    def exception_match(self, w_exc_type, w_check_class):
+        self.executioncontext.crnt_block.exc_handler = True
+        return ObjSpace.exception_match(self, w_exc_type, w_check_class)
+
+
     def build_flow(self, func, constargs={}):
         """
         """
@@ -322,7 +327,7 @@
                 # one specified by 'outcome', and not a subclass of it,
                 # unless 'outcome' is Exception.
                 if outcome is not Exception:
-                    w_exc_cls = Constant(outcome)
+                    w_exc_cls = Constant(outcome, last_exception=True)
                 raise OperationError(w_exc_cls, w_exc_value)
 
 # ______________________________________________________________________

Modified: pypy/dist/pypy/translator/annrpython.py
==============================================================================
--- pypy/dist/pypy/translator/annrpython.py	(original)
+++ pypy/dist/pypy/translator/annrpython.py	Fri Feb 25 16:38:27 2005
@@ -10,7 +10,6 @@
 from pypy.objspace.flow.model import SpaceOperation, FunctionGraph
 from pypy.objspace.flow.model import last_exception, last_exc_value
 
-
 class AnnotatorError(Exception):
     pass
 
@@ -217,7 +216,8 @@
             if graph.hasonlyexceptionreturns(): 
                 # XXX for functions with exceptions what to 
                 #     do anyway? 
-                return self.bookkeeper.immutablevalue(None)
+                #return self.bookkeeper.immutablevalue(None)
+                return annmodel.SomeImpossibleValue(benign=True)
             return annmodel.SomeImpossibleValue()
 
     def reflowfromposition(self, position_key):
@@ -354,19 +354,32 @@
                    and issubclass(link.exitcase, Exception):
                 last_exception_object = annmodel.SomeObject()
                 last_exc_value_object = annmodel.SomeObject()
-                last_exc_value_vars = last_exception_object.is_type_of = []
+                last_exc_value_vars = []
                 in_except_block = True
+                last_exception_unknown = True
+                last_exception_unused = True
                 
             cells = []
             renaming = dict(zip(link.args,link.target.inputargs))
             for a,v in zip(link.args,link.target.inputargs):
                 if a == Constant(last_exception):
                     assert in_except_block
+                    assert last_exception_unknown
                     cells.append(last_exception_object)
+                    last_exception_unused = False
                 elif a == Constant(last_exc_value):
                     assert in_except_block
                     cells.append(last_exc_value_object)
                     last_exc_value_vars.append(v)
+                elif isinstance(a, Constant) and a.has_flag('last_exception'):
+                    assert in_except_block
+                    assert last_exception_unused
+                    if last_exception_unknown:
+                        cell = last_exception_object = self.bookkeeper.immutablevalue(a.value)
+                    else:
+                        cell = last_exception_object
+                    cells.append(cell)
+                    last_exception_unknown = False
                 else:
                     cell = self.binding(a)
                     if link.exitcase is True and knownvars is not None and a in knownvars \
@@ -382,6 +395,9 @@
                         cell.is_type_of = renamed_is_type_of
                     cells.append(cell)
 
+            if in_except_block:
+                last_exception_object.is_type_of = last_exc_value_vars
+
             self.addpendingblock(fn, link.target, cells)
         if block in self.notify:
             # reflow from certain positions when this block is done

Modified: pypy/dist/pypy/translator/test/snippet.py
==============================================================================
--- pypy/dist/pypy/translator/test/snippet.py	(original)
+++ pypy/dist/pypy/translator/test/snippet.py	Fri Feb 25 16:38:27 2005
@@ -729,6 +729,10 @@
     def m(self):
         return 1
 
+class Exc4(Exc3):
+    def m(self):
+        return 1
+
 class Sp:
     def o(self):
         raise Exc3
@@ -745,11 +749,33 @@
             return e.m()
         return 0
 
+class Mod3:
+    def __init__(self, s):
+        self.s = s
+
+    def p(self):
+        s = self.s
+        try:
+            s.o()
+        except Exc4, e1:
+            return e1.m()
+        except Exc3, e2:
+            try:
+                return e2.m()
+            except Exc4, e3:
+                return e3.m()
+        return 0
+
+
 mod = Mod(Sp())
+mod3 = Mod3(Sp())
 
 def exc_deduction_our_exc_plus_others():
     return mod.p()
 
+def exc_deduction_our_excs_plus_others():
+    return mod3.p()
+
 
 class BltinCode:
   def __init__(self, func, framecls):

Modified: pypy/dist/pypy/translator/test/test_annrpython.py
==============================================================================
--- pypy/dist/pypy/translator/test/test_annrpython.py	(original)
+++ pypy/dist/pypy/translator/test/test_annrpython.py	Fri Feb 25 16:38:27 2005
@@ -115,12 +115,10 @@
         assert s.knowntype == int
 
     def test_lists(self):
-        fun = self.make_fun(snippet.poor_man_rev_range)
         a = RPythonAnnotator()
-        a.build_types(fun, [int])
+        end_cell = a.build_types(snippet.poor_man_rev_range, [int])
         # result should be a list of integers
-        assert a.gettype(fun.getreturnvar()) == list
-        end_cell = a.binding(fun.getreturnvar())
+        assert end_cell.knowntype == list
         assert end_cell.s_item.knowntype == int
 
     def test_factorial(self):
@@ -489,6 +487,11 @@
         s = a.build_types(snippet.exc_deduction_our_exc_plus_others, [])
         assert isinstance(s, annmodel.SomeInteger)
 
+    def test_exc_deduction_our_excs_plus_others(self):
+        a = RPythonAnnotator()
+        s = a.build_types(snippet.exc_deduction_our_excs_plus_others, [])
+        assert isinstance(s, annmodel.SomeInteger)
+
     def test_slice_union(self):
         a = RPythonAnnotator()
         s = a.build_types(snippet.slice_union, [int])

Modified: pypy/dist/pypy/translator/test/test_pyrextrans.py
==============================================================================
--- pypy/dist/pypy/translator/test/test_pyrextrans.py	(original)
+++ pypy/dist/pypy/translator/test/test_pyrextrans.py	Fri Feb 25 16:38:27 2005
@@ -108,8 +108,7 @@
 class TestTypedTestCase:
 
     def getcompiled(self, func):
-        t = Translator(func) 
-        t.simplify()
+        t = Translator(func, simplifying=True) 
         # builds starting-types from func_defs 
         argstypelist = []
         if func.func_defaults:

Modified: pypy/dist/pypy/translator/tool/make_dot.py
==============================================================================
--- pypy/dist/pypy/translator/tool/make_dot.py	(original)
+++ pypy/dist/pypy/translator/tool/make_dot.py	Fri Feb 25 16:38:27 2005
@@ -137,7 +137,11 @@
             shape = "octagon"
 
         iargs = " ".join(map(repr, block.inputargs))
-        data = "%s(%s)\\ninputargs: %s\\n\\n" % (name, block.__class__.__name__, iargs)
+        if block.exc_handler:
+            eh = 'EH'
+        else:
+            eh = ''
+        data = "%s(%s %s)\\ninputargs: %s\\n\\n" % (name, block.__class__.__name__, eh, iargs)
         if block.operations and self.func:
             maxoffs = max([op.offset for op in block.operations])
             if maxoffs >= 0:



More information about the Pypy-commit mailing list