[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pypy-svn
Subject:    [pypy-svn] rev 2225 - in pypy/trunk/src/pypy: interpreter
From:       arigo () codespeak ! net
Date:       2003-11-19 16:51:49
Message-ID: 20031119165149.C83325A2D9 () thoth ! codespeak ! net
[Download RAW message or body]

Author: arigo
Date: Wed Nov 19 17:51:48 2003
New Revision: 2225

Modified:
   pypy/trunk/src/pypy/interpreter/baseobjspace.py
   pypy/trunk/src/pypy/interpreter/pyframe.py
   pypy/trunk/src/pypy/objspace/flow/flowcontext.py
   pypy/trunk/src/pypy/objspace/flow/model.py
   pypy/trunk/src/pypy/objspace/flow/objspace.py
   pypy/trunk/src/pypy/objspace/flow/test/test_objspace.py
   pypy/trunk/src/pypy/tool/test.py
   pypy/trunk/src/pypy/translator/tool/make_dot.py
Log:
Exception support for the flow objspace.

M    pypy/interpreter/pyframe.py
M    pypy/interpreter/baseobjspace.py
M    pypy/tool/test.py

       Added a flag 'full_exceptions' in object spaces.
       Allows FlowObjSpace to signal that it doesn't
       really support all exception operations like
       normalization and traceback printing.

M    pypy/objspace/flow/model.py
M    pypy/translator/tool/make_dot.py

       FunctionGraphs now have additional 'end' blocks,
       listed in the 'exceptblocks' dict, one per
       possible exception class that it can raise.

M    pypy/objspace/flow/test/test_objspace.py
M    pypy/objspace/flow/flowcontext.py
M    pypy/objspace/flow/objspace.py

       The necessary logic.

The plan now is to have all operations tentatively raise exceptions like
KeyError, IndexError, OverflowError, so that they appear in the CFG; a later
simplification pass can apply the RPython specification that implicit uncaught
exceptions should not occur.


Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/trunk/src/pypy/interpreter/baseobjspace.py	Wed Nov 19 17:51:48 2003
@@ -19,6 +19,8 @@
 class ObjSpace:
     """Base class for the interpreter-level implementations of object spaces.
     http://codespeak.net/moin/pypy/moin.cgi/ObjectSpace"""
+    
+    full_exceptions = True  # full support for exceptions (normalization & more)
 
     def __init__(self):
         "Basic initialization of objects."
@@ -157,15 +159,15 @@
             # Match identical items.
             if self.is_true(self.is_(w_exc_type, w_item)):
                 return True
-            # Test within iterables (i.e. tuples)
             try:
-                exclst = self.unpackiterable(w_item)
-                check_list.extend(exclst)
-            except OperationError:
-                # w_item is not iterable; it should then be an Exception.
                 # Match subclasses.
                 if self.is_true(self.issubtype(w_exc_type, w_item)):
                     return True
+            except OperationError:
+                # Assume that this is a TypeError: w_item not a type,
+                # and assume that w_item is then actually a tuple.
+                exclst = self.unpackiterable(w_item)
+                check_list.extend(exclst)
         return False
 
     def call_function(self, w_func, *args_w, **kw_w):

Modified: pypy/trunk/src/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/pyframe.py	(original)
+++ pypy/trunk/src/pypy/interpreter/pyframe.py	Wed Nov 19 17:51:48 2003
@@ -159,10 +159,11 @@
             # push the exception to the value stack for inspection by the
             # exception handler (the code after the except:)
             operationerr = unroller.args[0]
-            w_normalized = normalize_exception(frame.space,
-                                               operationerr.w_type,
-                                               operationerr.w_value)
-            w_type, w_value = frame.space.unpacktuple(w_normalized, 2)
+            w_type  = operationerr.w_type
+            w_value = operationerr.w_value
+            if frame.space.full_exceptions:
+                w_normalized = normalize_exception(frame.space, w_type, w_value)
+                w_type, w_value = frame.space.unpacktuple(w_normalized, 2)
             # the stack setup is slightly different than in CPython:
             # instead of the traceback, we store the unroller object,
             # wrapped.

Modified: pypy/trunk/src/pypy/objspace/flow/flowcontext.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/flow/flowcontext.py	(original)
+++ pypy/trunk/src/pypy/objspace/flow/flowcontext.py	Wed Nov 19 17:51:48 2003
@@ -2,6 +2,7 @@
 from pypy.interpreter.miscutils import Stack
 from pypy.interpreter.pyframe \
      import ControlFlowException, ExitFrame, PyFrame
+from pypy.interpreter.error import OperationError
 from pypy.objspace.flow.model import *
 from pypy.objspace.flow.framestate import FrameState
 
@@ -152,10 +153,16 @@
                 block.patchframe(frame, self)
             except ExitFrame:
                 continue   # restarting a dead SpamBlock
-            w_result = frame.eval(self)
-            if w_result is not None:
-                link = Link([w_result], self.graph.returnblock)
+            try:
+                w_result = frame.eval(self)
+            except OperationError, e:
+                exc_type = self.space.unwrap(e.w_type)   # e.w_value ignored
+                link = Link([], self.graph.getexceptblock(exc_type))
                 self.crnt_block.closeblock(link)
+            else:
+                if w_result is not None:
+                    link = Link([w_result], self.graph.returnblock)
+                    self.crnt_block.closeblock(link)
         self.fixeggblocks()
 
     def fixeggblocks(self):

Modified: pypy/trunk/src/pypy/objspace/flow/model.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/flow/model.py	(original)
+++ pypy/trunk/src/pypy/objspace/flow/model.py	Wed Nov 19 17:51:48 2003
@@ -13,12 +13,24 @@
         self.returnblock = Block([return_var or Variable()])
         self.returnblock.operations = ()
         self.returnblock.exits      = ()
+        self.exceptblocks = {}  # Blocks corresponding to exception results
 
     def getargs(self):
         return self.startblock.inputargs
+
     def getreturnvar(self):
         return self.returnblock.inputargs[0]
 
+    def getexceptblock(self, exc_type):
+        try:
+            block = self.exceptblocks[exc_type]
+        except KeyError:
+            block = self.exceptblocks[exc_type] = Block([])
+            block.exc_type = exc_type
+            block.operations = ()
+            block.exits      = ()
+        return block
+
 class Link:
     def __init__(self, args, target, exitcase=None):
         assert len(args) == len(target.inputargs), "output args mismatch"
@@ -84,7 +96,7 @@
         return hash(self.value)
 
     def __repr__(self):
-        return '%r' % (self.value,)
+        return '(%r)' % (self.value,)
 
 class UndefinedConstant(Constant):
     # for local variables not defined yet.

Modified: pypy/trunk/src/pypy/objspace/flow/objspace.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/flow/objspace.py	(original)
+++ pypy/trunk/src/pypy/objspace/flow/objspace.py	Wed Nov 19 17:51:48 2003
@@ -14,11 +14,17 @@
 
 # ______________________________________________________________________
 class FlowObjSpace(ObjSpace):
+    full_exceptions = False
+    
     def initialize(self):
         import __builtin__
         self.w_builtins = Constant(__builtin__.__dict__)
         self.w_None     = Constant(None)
-        self.w_KeyError = Constant(KeyError)
+        self.w_False    = Constant(False)
+        self.w_True     = Constant(True)
+        for exc in [KeyError, ValueError]:
+            clsname = exc.__name__
+            setattr(self, 'w_'+clsname, Constant(exc))
         #self.make_builtins()
         #self.make_sys()
 

Modified: pypy/trunk/src/pypy/objspace/flow/test/test_objspace.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/flow/test/test_objspace.py	(original)
+++ pypy/trunk/src/pypy/objspace/flow/test/test_objspace.py	Wed Nov 19 17:51:48 2003
@@ -21,9 +21,8 @@
 
     def reallyshow(self, x):
         import os
-        from pypy.translator.test.make_dot import make_dot
-        from pypy.tool.udir import udir
-        dest = make_dot(x, udir, 'ps')
+        from pypy.translator.tool.make_dot import make_dot
+        dest = make_dot(x.name, x)
         os.system('gv %s' % str(dest))
 
     def show(self, x):
@@ -159,6 +158,50 @@
         x = self.codetest(self.break_continue)
         self.show(x)
 
+    #__________________________________________________________
+    def unpack_tuple(lst):
+        a, b, c = lst
+
+    def test_unpack_tuple(self):
+        x = self.codetest(self.unpack_tuple)
+        self.show(x)
+
+    #__________________________________________________________
+    def reverse_3(lst):
+        try:
+            a, b, c = lst
+        except:
+            return 0, 0, 0
+        else:
+            return c, b, a
+
+    def test_reverse_3(self):
+        x = self.codetest(self.reverse_3)
+        self.show(x)
+
+    #__________________________________________________________
+    def finallys(lst):
+        x = 1
+        try:
+            x = 2
+            try:
+                x = 3
+                a, = lst
+                x = 4
+            except KeyError:
+                return 5
+            except ValueError:
+                return 6
+            b, = lst
+            x = 7
+        finally:
+            x = 8
+        return x
+
+    def test_finallys(self):
+        x = self.codetest(self.finallys)
+        self.show(x)
+
 
 if __name__ == '__main__':
     test.main()

Modified: pypy/trunk/src/pypy/tool/test.py
==============================================================================
--- pypy/trunk/src/pypy/tool/test.py	(original)
+++ pypy/trunk/src/pypy/tool/test.py	Wed Nov 19 17:51:48 2003
@@ -44,7 +44,7 @@
     def addError(self, test, err):
         # XXX not nice:
         from pypy.interpreter.baseobjspace import OperationError
-        if isinstance(err[1], OperationError):
+        if isinstance(err[1], OperationError) and test.space.full_exceptions:
             if err[1].match(test.space, test.space.w_AssertionError):
                 self.addFailure(test, err)
                 return
@@ -58,7 +58,7 @@
         
     def addError(self, test, err):
         from pypy.interpreter.baseobjspace import OperationError
-        if isinstance(err[1], OperationError):
+        if isinstance(err[1], OperationError) and test.space.full_exceptions:
             if err[1].match(test.space, test.space.w_AssertionError):
                 self.addFailure(test, err)
                 return
@@ -121,7 +121,7 @@
             self.stream.writeln(self.separator2)
             t1 = self._exc_info_to_string(err)
             t2 = ''
-            if isinstance(err[1], OperationError):
+            if isinstance(err[1], OperationError) and test.space.full_exceptions:
                 t2 = '\nand at app-level:\n\n'
                 sio = StringIO.StringIO()
                 err[1].print_application_traceback(test.space, sio)

Modified: pypy/trunk/src/pypy/translator/tool/make_dot.py
==============================================================================
--- pypy/trunk/src/pypy/translator/tool/make_dot.py	(original)
+++ pypy/trunk/src/pypy/translator/tool/make_dot.py	Wed Nov 19 17:51:48 2003
@@ -87,7 +87,7 @@
         self.emit_node(name, label=data, shape="box", fillcolor="green", style="filled")
         #('%(name)s [fillcolor="green", shape=box, label="%(data)s"];' % locals())
         self.emit_edge(name, self.blockname(funcgraph.startblock), 'startblock')
-        self.emit_edge(name, self.blockname(funcgraph.returnblock), 'returnblock', style="dashed")
+        #self.emit_edge(name, self.blockname(funcgraph.returnblock), 'returnblock', style="dashed")
 
     def visit_Block(self, block):
         # do the block itself
@@ -100,6 +100,8 @@
         if not numblocks:
            shape = "box"
            fillcolor="green"
+           if hasattr(block, 'exc_type'):
+               lines.insert(0, 'exc_type: %s' % block.exc_type.__name__)
         elif numblocks == 1:
             shape = "box"
         else:

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic