[pypy-svn] r50790 - in pypy/dist/pypy/translator/cli: . test

antocuni at codespeak.net antocuni at codespeak.net
Sat Jan 19 23:13:56 CET 2008


Author: antocuni
Date: Sat Jan 19 23:13:56 2008
New Revision: 50790

Modified:
   pypy/dist/pypy/translator/cli/dotnet.py
   pypy/dist/pypy/translator/cli/metavm.py
   pypy/dist/pypy/translator/cli/opcodes.py
   pypy/dist/pypy/translator/cli/test/test_dotnet.py
Log:
a hack to be able to construct delegates of type EventHandler from RPython



Modified: pypy/dist/pypy/translator/cli/dotnet.py
==============================================================================
--- pypy/dist/pypy/translator/cli/dotnet.py	(original)
+++ pypy/dist/pypy/translator/cli/dotnet.py	Sat Jan 19 23:13:56 2008
@@ -519,3 +519,21 @@
     def specialize_call(self, hop):
         v_type, = hop.inputargs(*hop.args_r)
         return hop.genop('cli_typeof', [v_type], hop.r_result.lowleveltype)
+
+
+def eventhandler(obj):
+    return CLR.System.EventHandler(obj)
+
+class Entry(ExtRegistryEntry):
+    _about_ = eventhandler
+
+    def compute_result_annotation(self, s_value):
+        from pypy.translator.cli.query import load_class_maybe
+        cliType = load_class_maybe('System.EventHandler')
+        return SomeOOInstance(cliType._INSTANCE)
+
+    def specialize_call(self, hop):
+        v_obj, = hop.inputargs(*hop.args_r)
+        methodname = hop.args_r[0].methodname
+        c_methodname = hop.inputconst(ootype.Void, methodname)
+        return hop.genop('cli_eventhandler', [v_obj, c_methodname], hop.r_result.lowleveltype)

Modified: pypy/dist/pypy/translator/cli/metavm.py
==============================================================================
--- pypy/dist/pypy/translator/cli/metavm.py	(original)
+++ pypy/dist/pypy/translator/cli/metavm.py	Sat Jan 19 23:13:56 2008
@@ -9,6 +9,13 @@
 
 STRING_HELPER_CLASS = '[pypylib]pypy.runtime.String'
 
+def functype_to_cts(cts, FUNC):
+    ret_type = cts.lltype_to_cts(FUNC.RESULT)
+    arg_types = [cts.lltype_to_cts(arg).typename()
+                 for arg in FUNC.ARGS
+                 if arg is not ootype.Void]
+    return ret_type, arg_types
+
 class _Call(_OOCall):
     
     def render(self, generator, op):
@@ -22,10 +29,7 @@
         for func_arg in args[1:]: # push parameters
             self._load_arg_or_null(generator, func_arg)
         cts = generator.cts
-        ret_type = cts.lltype_to_cts(funcdesc._TYPE.RESULT)
-        arg_types = [cts.lltype_to_cts(arg).typename()
-                     for arg in funcdesc._TYPE.ARGS
-                     if arg is not ootype.Void]
+        ret_type, arg_types = functype_to_cts(cts, funcdesc._TYPE)
         arg_list = ', '.join(arg_types)
         signature = '%s %s::%s(%s)' % (ret_type, funcdesc._cls._name, funcdesc._name, arg_list)
         generator.call_signature(signature)
@@ -59,10 +63,7 @@
             # special case for string: don't use methods, but plain functions
             METH = this.concretetype._METHODS[method_name]
             cts = generator.cts
-            ret_type = cts.lltype_to_cts(METH.RESULT)
-            arg_types = [cts.lltype_to_cts(arg).typename()
-                         for arg in METH.ARGS
-                         if arg is not ootype.Void]
+            ret_type, arg_types = functype_to_cts(cts, METH)
             arg_types.insert(0, cts.lltype_to_cts(ootype.String).typename())
             arg_list = ', '.join(arg_types)
             signature = '%s %s::%s(%s)' % (ret_type, STRING_HELPER_CLASS, method_name, arg_list)
@@ -197,6 +198,25 @@
         generator.ilasm.opcode('ldtoken', fullname)
         generator.ilasm.call('class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)')
 
+class _EventHandler(MicroInstruction):
+    def render(self, generator, op):
+        cts = generator.cts
+        v_obj, c_methname = op.args
+        assert c_methname.concretetype is ootype.Void
+        TYPE = v_obj.concretetype
+        classname = TYPE._name
+        methname = 'o' + c_methname.value # XXX: do proper mangling
+        _, meth = TYPE._lookup(methname)
+        METH = ootype.typeOf(meth)
+        ret_type, arg_types = functype_to_cts(cts, METH)
+        arg_list = ', '.join(arg_types)
+        generator.load(v_obj)
+        desc = '%s class %s::%s(%s)' % (ret_type, classname, methname, arg_list)
+        generator.ilasm.opcode('ldftn instance', desc)
+        generator.ilasm.opcode('newobj', 'instance void class [mscorlib]System.EventHandler::.ctor(object, native int)')
+
+
+
 OOTYPE_TO_MNEMONIC = {
     ootype.Signed: 'i4',
     ootype.SignedLongLong: 'i8',
@@ -222,4 +242,5 @@
 GetArrayElem = _GetArrayElem()
 SetArrayElem = _SetArrayElem()
 TypeOf = _TypeOf()
+EventHandler = _EventHandler()
 CastPrimitive = _CastPrimitive()

Modified: pypy/dist/pypy/translator/cli/opcodes.py
==============================================================================
--- pypy/dist/pypy/translator/cli/opcodes.py	(original)
+++ pypy/dist/pypy/translator/cli/opcodes.py	Sat Jan 19 23:13:56 2008
@@ -1,7 +1,7 @@
 from pypy.translator.cli.metavm import  Call, CallMethod, \
      IndirectCall, GetField, SetField, DownCast, NewCustomDict,\
      MapException, Box, Unbox, NewArray, GetArrayElem, SetArrayElem,\
-     TypeOf, CastPrimitive
+     TypeOf, CastPrimitive, EventHandler
 from pypy.translator.oosupport.metavm import PushArg, PushAllArgs, StoreResult, InstructionList,\
     New, RuntimeNew, CastTo, PushPrimitive, OOString, OOUnicode
 from pypy.translator.cli.cts import WEAKREF
@@ -43,6 +43,7 @@
     'cli_setelem':              [SetArrayElem],
     'cli_typeof':               [TypeOf],
     'cli_arraylength':          'ldlen',
+    'cli_eventhandler':         [EventHandler],
     'oois':                     'ceq',
     'oononnull':                [PushAllArgs, 'ldnull', 'ceq']+Not,
     'instanceof':               [CastTo, 'ldnull', 'cgt.un'],

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	Sat Jan 19 23:13:56 2008
@@ -7,7 +7,7 @@
 from pypy.translator.cli.test.runtest import CliTest
 from pypy.translator.cli.dotnet import SomeCliClass, SomeCliStaticMethod,\
      NativeInstance, CLR, box, unbox, OverloadingResolver, NativeException,\
-     native_exc, new_array, init_array, typeof
+     native_exc, new_array, init_array, typeof, eventhandler
 
 System = CLR.System
 Math = CLR.System.Math
@@ -417,6 +417,23 @@
         res = self.interpret(fn, [], backendopt=False)
         assert res is True
 
+    def test_delegate(self):
+        class Foo:
+            def __init__(self):
+                self.x = 0
+            def m(self, sender, args):
+                self.x = 42
+
+        def fn(flag):
+            f = Foo()
+            if flag:
+                f.m(None, None)
+            delegate = eventhandler(f.m)
+            delegate.Invoke(None, None)
+            return f.x
+        res = self.interpret(fn, [False])
+        assert res == 42
+
 class TestPythonnet(TestDotnetRtyping):
     # don't interpreter functions but execute them directly through pythonnet
     def interpret(self, f, args, backendopt='ignored'):



More information about the Pypy-commit mailing list