[pypy-svn] r34602 - in pypy/dist/pypy/translator: cli cli/test oosupport

antocuni at codespeak.net antocuni at codespeak.net
Tue Nov 14 17:09:52 CET 2006


Author: antocuni
Date: Tue Nov 14 17:09:50 2006
New Revision: 34602

Modified:
   pypy/dist/pypy/translator/cli/cts.py
   pypy/dist/pypy/translator/cli/dotnet.py
   pypy/dist/pypy/translator/cli/function.py
   pypy/dist/pypy/translator/cli/support.py
   pypy/dist/pypy/translator/cli/test/test_dotnet.py
   pypy/dist/pypy/translator/oosupport/function.py
Log:
Added support for handling native exceptions when using .NET-types.

It's a bit involved because .NET exceptions don't share a common root
with RPython exceptions, so we need to cheat a bit by creating a fake
class that will be recognized by the backend and rendered as
appropriate.

This means, for example, that instead of writing something like this:

try: 
    f()
except CLR.System.Exception:
    ...

we need to create the fake object first.

SystemException = NativeException(CLR.System.Exception)

try:
    f()
except SystemException:
    ...

Please note that the call to NativeException is *not* RPython, so you
need to call it at initialization-time.

Thanks to pedronis for the original idea.



Modified: pypy/dist/pypy/translator/cli/cts.py
==============================================================================
--- pypy/dist/pypy/translator/cli/cts.py	(original)
+++ pypy/dist/pypy/translator/cli/cts.py	Tue Nov 14 17:09:50 2006
@@ -147,8 +147,12 @@
         elif isinstance(t, lltype.Ptr) and isinstance(t.TO, lltype.OpaqueType):
             return self.__class('[mscorlib]System.Object', include_class)
         elif isinstance(t, ootype.Instance):
-            name = self.db.pending_class(t)
-            return self.__class(name, include_class)
+            native_class = t._hints.get('native_class', None)
+            if native_class:
+                return self.__class(native_class, include_class)
+            else:
+                name = self.db.pending_class(t)
+                return self.__class(name, include_class)
         elif isinstance(t, ootype.Record):
             name = self.db.pending_record(t)
             return self.__class(name, include_class)

Modified: pypy/dist/pypy/translator/cli/dotnet.py
==============================================================================
--- pypy/dist/pypy/translator/cli/dotnet.py	(original)
+++ pypy/dist/pypy/translator/cli/dotnet.py	Tue Nov 14 17:09:50 2006
@@ -1,3 +1,5 @@
+import types
+
 from pypy.annotation.pairtype import pair, pairtype
 from pypy.annotation.model import SomeObject, SomeOOInstance, SomeInteger, s_None,\
      s_ImpossibleValue, lltype_to_annotation, annotation_to_lltype, SomeChar, SomeString
@@ -66,6 +68,7 @@
         INSTANCE = hop.args_r[0].cli_class._INSTANCE
         cINST = hop.inputconst(ootype.Void, INSTANCE)
         vlist = hop.inputargs(*hop.args_r)[1:] # discard the first argument
+        hop.exception_is_here()
         return hop.genop("new", [cINST]+vlist, resulttype=hop.r_result.lowleveltype)
 
 class CliStaticMethodRepr(Repr):
@@ -265,6 +268,7 @@
     # TODO: check that x is really of type TYPE
     return x
 
+
 class Entry(ExtRegistryEntry):
     _about_ = box
 
@@ -298,3 +302,27 @@
             return hop.genop('oodowncast', [v_obj], hop.r_result.lowleveltype)
         else:
             return hop.genop('cliunbox', [v_obj, v_type], hop.r_result.lowleveltype)
+
+
+
+native_exc = {}
+def NativeException(cliClass):
+    try:
+        return native_exc[cliClass._name]
+    except KeyError:
+        res = _create_NativeException(cliClass)
+        native_exc[cliClass._name] = res
+        return res
+
+def _create_NativeException(cliClass):
+    from pypy.translator.cli.query import getattr_ex
+    TYPE = cliClass._INSTANCE
+    if PythonNet.__name__ == 'CLR':
+        # we are using pythonnet -- use the .NET class
+        name = '%s.%s' % (TYPE._namespace, TYPE._classname)
+        res = getattr_ex(PythonNet, name)
+    else:
+        # we are not using pythonnet -- create a fake class
+        res = types.ClassType(TYPE._classname, (Exception,), {})
+    res._rpython_hints = {'native_class': cliClass._name}
+    return res

Modified: pypy/dist/pypy/translator/cli/function.py
==============================================================================
--- pypy/dist/pypy/translator/cli/function.py	(original)
+++ pypy/dist/pypy/translator/cli/function.py	Tue Nov 14 17:09:50 2006
@@ -25,6 +25,13 @@
     def _create_generator(self, ilasm):
         return self # Function implements the Generator interface
 
+    def record_ll_meta_exc(self, ll_meta_exc):
+        # record the type only if it doesn't belong to a native_class
+        ll_exc = ll_meta_exc._inst.class_._INSTANCE
+        native_class = ll_exc._hints.get('native_class', None)
+        if native_class is None:
+            OOFunction.record_ll_meta_exc(self, ll_meta_exc)
+
     def begin_try(self):
         self.ilasm.begin_try()
 

Modified: pypy/dist/pypy/translator/cli/support.py
==============================================================================
--- pypy/dist/pypy/translator/cli/support.py	(original)
+++ pypy/dist/pypy/translator/cli/support.py	Tue Nov 14 17:09:50 2006
@@ -9,6 +9,7 @@
     import CLR as PythonNet
 except ImportError:
     class _PythonNet:
+        __name__ = None
         def __getattr__(self, attr):
             py.test.skip('Must use pythonnet for being able to access .NET libraries')
     PythonNet = _PythonNet()

Modified: pypy/dist/pypy/translator/cli/test/test_dotnet.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/test_dotnet.py	(original)
+++ pypy/dist/pypy/translator/cli/test/test_dotnet.py	Tue Nov 14 17:09:50 2006
@@ -6,7 +6,7 @@
      ROOT, overload, Instance, new
 from pypy.translator.cli.test.runtest import CliTest
 from pypy.translator.cli.dotnet import SomeCliClass, SomeCliStaticMethod,\
-     NativeInstance, CLR, box, unbox, OverloadingResolver
+     NativeInstance, CLR, box, unbox, OverloadingResolver, NativeException
 
 System = CLR.System
 Math = CLR.System.Math
@@ -199,6 +199,29 @@
             return x.get_Item(0)
         assert self.interpret(fn, []) is None
 
+    def test_native_exception_precise(self):
+        ArgumentOutOfRangeException = NativeException(CLR.System.ArgumentOutOfRangeException)
+        def fn():
+            x = ArrayList()
+            try:
+                x.get_Item(0)
+                return False
+            except ArgumentOutOfRangeException:
+                return True
+        assert self.interpret(fn, []) == True
+
+    def test_native_exception_superclass(self):
+        SystemException = NativeException(CLR.System.Exception)
+        def fn():
+            x = ArrayList()
+            try:
+                x.get_Item(0)
+                return False
+            except SystemException:
+                return True
+        assert self.interpret(fn, []) == True
+
+
 class TestPythonnet(TestDotnetRtyping):
     # don't interpreter functions but execute them directly through pythonnet
     def interpret(self, f, args):

Modified: pypy/dist/pypy/translator/oosupport/function.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/function.py	(original)
+++ pypy/dist/pypy/translator/oosupport/function.py	Tue Nov 14 17:09:50 2006
@@ -132,12 +132,15 @@
                 continue # see above
             assert issubclass(link.exitcase, Exception)
             ll_meta_exc = link.llexitcase
-            self.db.constant_generator.record_const(ll_meta_exc)
+            self.record_ll_meta_exc(ll_meta_exc)
             self.begin_catch(link.llexitcase)
             self.store_exception_and_link(link)
             target_label = self._get_block_name(link.target)
             self.end_catch(target_label)
 
+    def record_ll_meta_exc(self, ll_meta_exc):
+        self.db.constant_generator.record_const(ll_meta_exc)
+
     def store_exception_and_link(self, link):
         raise NotImplementedError
             



More information about the Pypy-commit mailing list