[pypy-svn] r44557 - in pypy/dist/pypy/translator/cli: . test
antocuni at codespeak.net
antocuni at codespeak.net
Wed Jun 27 14:48:42 CEST 2007
Author: antocuni
Date: Wed Jun 27 14:48:41 2007
New Revision: 44557
Modified:
pypy/dist/pypy/translator/cli/silverpython.py
pypy/dist/pypy/translator/cli/test/test_silverpython.py
Log:
add the possibility to export classes.
A class is exported is its __init__ is marked with @export. Individual
methods can also be @exported, useful for methods that can't be
reached by one of the entrypoints.
To force the annotator to analyze a given method, we generates a dummy
function which call that method. Better approached are welcome.
Modified: pypy/dist/pypy/translator/cli/silverpython.py
==============================================================================
--- pypy/dist/pypy/translator/cli/silverpython.py (original)
+++ pypy/dist/pypy/translator/cli/silverpython.py Wed Jun 27 14:48:41 2007
@@ -9,6 +9,7 @@
import new
import types
import os.path
+import inspect
from pypy.translator.driver import TranslationDriver
from pypy.translator.cli.entrypoint import DllEntryPoint
@@ -18,6 +19,9 @@
self.name = name
self.namespace = namespace
self.functions = functions # [(function, annotation), ...]
+ self.driver = TranslationDriver()
+ self.driver.config.translation.ootype.mangle = False
+ self.driver.setup_library(self)
def add_function(self, func, inputtypes):
self.functions.append((func, inputtypes))
@@ -31,11 +35,7 @@
for func, _ in self.functions:
if not hasattr(func, '_namespace_'):
func._namespace_ = self.namespace
- driver = TranslationDriver()
- driver.config.translation.ootype.mangle = False
- driver.setup_library(self)
- driver.proceed(['compile_cli'])
- return driver
+ self.driver.proceed(['compile_cli'])
class export(object):
def __new__(self, *args, **kwds):
@@ -57,25 +57,76 @@
func._namespace_ = self.namespace
return func
+def is_exported(obj):
+ return isinstance(obj, (types.FunctionType, types.UnboundMethodType)) \
+ and hasattr(obj, '_inputtypes_')
+
def collect_entrypoints(dic):
entrypoints = []
for item in dic.itervalues():
- if isinstance(item, types.FunctionType) and hasattr(item, '_inputtypes_'):
+ if is_exported(item):
entrypoints.append((item, item._inputtypes_))
+ elif isinstance(item, types.ClassType) or isinstance(item, type):
+ entrypoints += collect_class_entrypoints(item)
+ return entrypoints
+
+def collect_class_entrypoints(cls):
+ try:
+ __init__ = cls.__init__
+ if not is_exported(__init__):
+ return []
+ except AttributeError:
+ return []
+
+ entrypoints = [(wrap_init(cls, __init__), __init__._inputtypes_)]
+ for item in cls.__dict__.itervalues():
+ if item is not __init__.im_func and is_exported(item):
+ inputtypes = (cls,) + item._inputtypes_
+ entrypoints.append((wrap_method(item), inputtypes))
return entrypoints
+def getarglist(meth):
+ arglist, starargs, kwargs, defaults = inspect.getargspec(meth)
+ assert starargs is None, '*args not supported yet'
+ assert kwargs is None, '**kwds not supported yet'
+ assert defaults is None, 'default values not supported yet'
+ return arglist
+
+def wrap_init(cls, meth):
+ arglist = getarglist(meth)[1:] # discard self
+ args = ', '.join(arglist)
+ source = 'def __internal__ctor(%s): return %s(%s)' % (
+ args, cls.__name__, args)
+ mydict = {cls.__name__: cls}
+ print source
+ exec source in mydict
+ return mydict['__internal__ctor']
+
+def wrap_method(meth, is_init=False):
+ arglist = getarglist(meth)
+ name = '__internal__%s' % meth.func_name
+ selfvar = arglist[0]
+ args = ', '.join(arglist)
+ params = ', '.join(arglist[1:])
+ source = 'def %s(%s): return %s.%s(%s)' % (
+ name, args, selfvar, meth.func_name, params)
+ mydict = {}
+ print source
+ exec source in mydict
+ return mydict[name]
+
+
def compile_dll(filename):
_, name = os.path.split(filename)
dllname, _ = os.path.splitext(name)
-
module = new.module(dllname)
- execfile(filename, module.__dict__)
- entrypoints = collect_entrypoints(module.__dict__)
namespace = module.__dict__.get('_namespace_', dllname)
-
- dll = DllDef(dllname, namespace, entrypoints)
- driver = dll.compile()
- driver.copy_cli_dll()
+ execfile(filename, module.__dict__)
+
+ dll = DllDef(dllname, namespace)
+ dll.functions = collect_entrypoints(module.__dict__)
+ dll.compile()
+ dll.driver.copy_cli_dll()
def main(argv):
if len(argv) != 2:
Modified: pypy/dist/pypy/translator/cli/test/test_silverpython.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/test_silverpython.py (original)
+++ pypy/dist/pypy/translator/cli/test/test_silverpython.py Wed Jun 27 14:48:41 2007
@@ -1,6 +1,7 @@
from pypy.tool import udir
from pypy.translator.cli.rte import Target
-from pypy.translator.cli.silverpython import DllDef, export, collect_entrypoints
+from pypy.translator.cli.silverpython import DllDef, export, collect_entrypoints,\
+ collect_class_entrypoints
from pypy.translator.cli.test.runtest import CliFunctionWrapper, CliTest
TEMPLATE = """
@@ -82,3 +83,42 @@
mydict = dict(foo=foo, bar=bar, x=42)
entrypoints = collect_entrypoints(mydict)
assert entrypoints == [(foo, (int, float))]
+
+ def test_collect_class_entrypoints(self):
+ class NotExported:
+ def __init__(self):
+ pass
+
+ class MyClass:
+ @export
+ def __init__(self):
+ pass
+ @export(int)
+ def foo(self, x):
+ return x
+
+ assert collect_class_entrypoints(NotExported) == []
+ entrypoints = collect_class_entrypoints(MyClass)
+ assert len(entrypoints) == 2
+ assert entrypoints[0][1] == () # __init__ inputtypes
+ assert entrypoints[1][1] == (MyClass, int) # foo inputtypes
+
+ def test_compile_class(self):
+ class MyClass:
+ @export(int)
+ def __init__(self, x):
+ self.x = x
+ @export(int, int)
+ def add(self, y, z):
+ return self.x + y + z
+ MyClass.__module__ = 'Test' # put the class in the Test namespace
+
+ entrypoints = collect_entrypoints({'MyClass': MyClass})
+ dll = DllDef('test', 'Test', entrypoints)
+ dll.compile()
+ res = self._csharp('test', """
+ Test.MyClass obj = new Test.MyClass();
+ obj.__init___variant0(39);
+ Console.WriteLine(obj.add_variant0(1, 2));
+ """)
+ assert res == 42
More information about the Pypy-commit
mailing list