[pypy-svn] r37668 - in pypy/dist/pypy/translator/cli: . src test
antocuni at codespeak.net
antocuni at codespeak.net
Wed Jan 31 14:41:49 CET 2007
Author: antocuni
Date: Wed Jan 31 14:41:46 2007
New Revision: 37668
Added:
pypy/dist/pypy/translator/cli/src/support.cs
Modified:
pypy/dist/pypy/translator/cli/dotnet.py
pypy/dist/pypy/translator/cli/rte.py
pypy/dist/pypy/translator/cli/support.py
pypy/dist/pypy/translator/cli/test/test_dotnet.py
Log:
Add support for casting arbitrary RPython instances to System.Object
using the box() function.
This is very easy in the translated code, but tricky when using Python
for .NET: see also the comment at the end of box().
Modified: pypy/dist/pypy/translator/cli/dotnet.py
==============================================================================
--- pypy/dist/pypy/translator/cli/dotnet.py (original)
+++ pypy/dist/pypy/translator/cli/dotnet.py Wed Jan 31 14:41:46 2007
@@ -289,6 +289,20 @@
ootype.UnsignedLongLong, ootype.Bool, ootype.Float,
ootype.Char, ootype.String]
+class BoxedSpace:
+ objects = {}
+ index = 0
+ def put(cls, obj):
+ index = cls.index
+ cls.objects[index] = obj
+ cls.index += 1
+ return index
+ put = classmethod(put)
+
+ def get(cls, index):
+ return cls.objects[index]
+ get = classmethod(get)
+
def box(x):
t = type(x)
if t is int:
@@ -310,12 +324,25 @@
return CLR.System.String(x)
elif isinstance(x, PythonNet.System.Object):
return x
+ elif x is None:
+ return None
else:
- assert False
+ # cast RPython instances to System.Object is trivial when
+ # translated but not when interpreting, because Python for
+ # .NET doesn't support passing aribrary Python objects to
+ # .NET. To solve, we store them in the BoxedSpace, then we
+ # return an opaque objects, which will be used by unbox to
+ # retrieve the original RPython instance.
+ index = BoxedSpace.put(x)
+ res = PythonNet.pypy.test.ObjectWrapper(index)
+ return res
def unbox(x, TYPE):
# TODO: check that x is really of type TYPE
-
+
+ if isinstance(x, PythonNet.pypy.test.ObjectWrapper):
+ return BoxedSpace.get(x.index)
+
# this is a workaround against a pythonnet limitation: you can't
# directly get the, e.g., python int from the System.Int32 object:
# a simple way to do this is to put it into an ArrayList and
@@ -336,7 +363,7 @@
hop.exception_cannot_occur()
TYPE = v_obj.concretetype
- if (TYPE is ootype.String or isinstance(TYPE, NativeInstance)):
+ if (TYPE is ootype.String or isinstance(TYPE, (ootype.Instance, ootype.BuiltinType, NativeInstance))):
return hop.genop('ooupcast', [v_obj], hop.r_result.lowleveltype)
else:
if TYPE not in BOXABLE_TYPES:
@@ -352,12 +379,17 @@
assert x_s.ootype == CLR.System.Object._INSTANCE
assert type_s.is_constant()
TYPE = type_s.const
- assert TYPE in BOXABLE_TYPES
- return OverloadingResolver.lltype_to_annotation(TYPE)
+ if isinstance(TYPE, (type, types.ClassType)):
+ # it's a user-defined class, so we return SomeInstance
+ classdef = self.bookkeeper.getuniqueclassdef(TYPE)
+ return SomeInstance(classdef, can_be_None=x_s.can_be_None)
+ else:
+ assert TYPE in BOXABLE_TYPES
+ return OverloadingResolver.lltype_to_annotation(TYPE)
def specialize_call(self, hop):
v_obj, v_type = hop.inputargs(*hop.args_r)
- if v_type.value is ootype.String:
+ if v_type.value is ootype.String or isinstance(v_type.value, (type, types.ClassType)):
return hop.genop('oodowncast', [v_obj], hop.r_result.lowleveltype)
else:
return hop.genop('cliunbox', [v_obj, v_type], hop.r_result.lowleveltype)
Modified: pypy/dist/pypy/translator/cli/rte.py
==============================================================================
--- pypy/dist/pypy/translator/cli/rte.py (original)
+++ pypy/dist/pypy/translator/cli/rte.py Wed Jan 31 14:41:46 2007
@@ -97,6 +97,11 @@
Target.compile.im_func(cls, sources, out)
compile = classmethod(compile)
+class Support(Target):
+ SOURCES = ['support.cs']
+ OUTPUT = 'support.dll'
+ FLAGS = ['/t:library']
+
def get_pypy_dll():
if os.environ.get('PYPYLIB', '').lower() == 'unix':
DLL = UnixDLL
Added: pypy/dist/pypy/translator/cli/src/support.cs
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/cli/src/support.cs Wed Jan 31 14:41:46 2007
@@ -0,0 +1,12 @@
+using System;
+
+namespace pypy.test {
+ public class ObjectWrapper {
+ public int index;
+
+ public ObjectWrapper(int index)
+ {
+ this.index = index;
+ }
+ }
+}
Modified: pypy/dist/pypy/translator/cli/support.py
==============================================================================
--- pypy/dist/pypy/translator/cli/support.py (original)
+++ pypy/dist/pypy/translator/cli/support.py Wed Jan 31 14:41:46 2007
@@ -1,12 +1,14 @@
import py
from pypy.rpython.ootypesystem import ootype
+from pypy.translator.cli.rte import Support
from pypy.tool.ansi_print import ansi_log
-log = py.log.Producer("cli")
+log = py.log.Producer("cli")
py.log.setconsumer("cli", ansi_log)
try:
import CLR as PythonNet
+ PythonNet.System.Reflection.Assembly.LoadFile(Support.get())
except ImportError:
class _PythonNet:
__name__ = None
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 Wed Jan 31 14:41:46 2007
@@ -124,6 +124,27 @@
assert isinstance(s, annmodel.SomeOOInstance)
assert s.can_be_None == True
+ def test_box_instance(self):
+ class Foo:
+ pass
+ def fn():
+ return box(Foo())
+ a = RPythonAnnotator()
+ s = a.build_types(fn, [])
+ assert isinstance(s, annmodel.SomeOOInstance)
+ assert s.ootype._name == '[mscorlib]System.Object'
+
+ def test_unbox_instance(self):
+ class Foo:
+ pass
+ def fn():
+ boxed = box(Foo())
+ return unbox(boxed, Foo)
+ a = RPythonAnnotator()
+ s = a.build_types(fn, [])
+ assert isinstance(s, annmodel.SomeInstance)
+ assert s.classdef.name.endswith('Foo')
+
class TestDotnetRtyping(CliTest):
def _skip_pythonnet(self, msg):
@@ -314,6 +335,29 @@
res = self.interpret(fn, [1])
assert res is None
+ def test_box_unbox_instance(self):
+ class Foo:
+ pass
+ def fn():
+ obj = Foo()
+ b_obj = box(obj)
+ obj2 = unbox(b_obj, Foo)
+ return obj is obj2
+ res = self.interpret(fn, [])
+ assert res is True
+
+ def test_instance_wrapping(self):
+ class Foo:
+ pass
+ def fn():
+ obj = Foo()
+ x = ArrayList()
+ x.Add(box(obj))
+ obj2 = unbox(x.get_Item(0), Foo)
+ return obj is obj2
+ res = self.interpret(fn, [])
+ assert res is True
+
class TestPythonnet(TestDotnetRtyping):
# don't interpreter functions but execute them directly through pythonnet
def interpret(self, f, args):
More information about the Pypy-commit
mailing list