Commits

Antonio Cuni committed 88bbbab

kill carbonpython

Comments (0)

Files changed (6)

pypy/bin/carbonpython.py

-#! /usr/bin/env python
-import autopath, sys
-from pypy.translator.cli.carbonpython import main
-
-main(sys.argv)

pypy/doc/carbonpython.rst

-==================================================
-CarbonPython, aka C# considered harmful
-==================================================
-
-CarbonPython overview
-=====================
-
-CarbonPython is an experimental RPython to .NET compiler. Its main
-focus is to produce DLLs to be used by other .NET programs, not
-standalone executables; if you want to compile an RPython standalone
-program, have a look to `translate.py`_.
-
-Compiled RPython programs are much faster (up to 250x) than
-interpreted IronPython programs, hence it might be a convenient
-replacement for C# when more speed is needed. RPython programs can be
-as fast as C# programs.
-
-RPython is a restrict subset of Python, static enough to be analyzed
-and compiled efficiently to lower level languages.  To read more about
-the RPython limitations read the `RPython description`_.
-
-**Disclaimer**: RPython is a much less convenient language than Python
-to program with. If you do not need speed, there is no reason to look
-at RPython.
-
-**Big disclaimer**: CarbonPython is still in a pre-alpha stage: it's
-not meant to be used for production code, and the API might change in
-the future. Despite this, it might be useful in some situations and
-you are encouraged to try it by yourself. Suggestions, bug-reports and
-even better patches are welcome.
-
-.. _`RPython description`: coding-guide.html#restricted-python
-.. _`translate.py`: faq.html#how-do-i-compile-my-own-interpreters
-
-
-Quick start
-===========
-
-Suppose you want to write a little DLL in RPython and call its
-function from C#.
-
-Here is the file mylibrary.py::
-
-    from pypy.translator.cli.carbonpython import export
-
-    @export(int, int)
-    def add(x, y):
-        return x+y
-
-    @export(int, int)
-    def sub(x, y):
-        return x-y
-
-
-And here the C# program main.cs::
-
-    using System;
-    public class CarbonPythonTest
-    {
-        public static void Main()
-        {
-            Console.WriteLine(mylibrary.add(40, 2));
-            Console.WriteLine(mylibrary.sub(44, 2));
-        }
-    }
-
-Once the files have been created, you can compile ``mylibrary.py``
-with CarbonPython to get the corresponding DLL::
-
-    $ python carbonpython.py mylibrary.py
-    ... lot of stuff
-
-Then, we compile main.cs into an executable, being sure to add a
-reference to the newly created ``mylibrary.dll``::
-
-    # with mono on linux
-    $ gmcs /r:mylibrary.dll main.cs
-
-    # with Microsoft CLR on windows
-    c:\> csc /r:mylibrary main.cs
-
-Now we can run the executable to see whether the answers are right::
-
-    $ mono main.exe
-    42
-    42
-
-
-Multiple entry-points
-=====================
-
-In RPython, the type of each variable is inferred by the `Annotator`_:
-the annotator analyzed the whole program top-down starting from an
-entry-point, i.e. a function whose we specified the types of the
-parameters.
-
-This approach works for a standalone executables, but not for a
-library that by definition is composed by more than one
-entry-point. Thus, you need to explicitly specify which functions you
-want to include in your DLL, together with the expected input types.
-
-To mark a function as an entry-point, you use the ``@export``
-decorator, which is defined in ``pypy.translator.cli.carbonpython``,
-as shown by the previous example.  Note that you do not need to
-specify the return type, because it is automatically inferenced by the
-annotator.
-
-.. _`Annotator`: translation.html#annotator
-
-
-Namespaces
-==========
-
-Since `CLS`_ (Common Language Specification) does not support module
-level static methods, RPython functions marked as entry-points are
-compiled to static methods of a class, in order to be accessible by
-every CLS-compliant language such as C# or VB.NET.
-
-The class which each function is placed in depends on its
-**namespace**; for example, if the namespace of a function ``foo`` is
-``A.B.C``, the function will be rendered as a static method of the
-``C`` class inside the ``A.B`` namespace. This allows C# and
-IronPython code to call the function using the intuitive ``A.B.C.foo``
-syntax.
-
-By default, the default namespace for exported function is the same as
-the name of the module. Thus in the previous example the default
-namespace is ``mylibrary`` and the functions are placed inside the
-corresponding class in the global namespace.
-
-You can change the default namespace by setting the ``_namespace_``
-variable in the module you are compiling::
-
-    _namespace_ = 'Foo.Bar'
-
-    @export(int, int)
-    def f(x, y):
-        pass
-
-Finally, you can also set a specific namespace on a per-function
-basis, using the appropriate keyword argument of the ``@export``
-decorator::
-
-    @export(int, int, namespace='Foo.Bar')
-    def f(x, y):
-        pass
-
-
-.. _`CLS`: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf
-
-
-Exporting classes
-=================
-
-RPython libraries can also export classes: to export a class, add the
-``@export`` decorator to its ``__init__`` method; similarly, you can
-also export any methods of the class::
-
-    class MyClass:
-
-        @export(int)
-        def __init__(self, x):
-            self.x = x
-
-        @export
-        def getx(self):
-            return self.x
-
-
-Note that the type of ``self`` must not be specified: it will
-automatically assumed to be ``MyClass``.
-
-The ``__init__`` method is not automatically mapped to the .NET
-constructor; to properly initialize an RPython object from C# or
-IronPython code you need to explicitly call ``__init__``; for example,
-in C#::
-
-    MyClass obj = new MyClass();
-    obj.__init__(x);
-
-Note that this is needed only when calling RPython code from 
-outside; the RPython compiler automatically calls ``__init__``
-whenever an RPython class is instantiated.
-
-In the future this discrepancy will be fixed and the ``__init__``
-method will be automatically mapped to the constructor.
-
-
-Accessing .NET libraries
-========================
-
-**Warning**: the API for accessing .NET classes from RPython is highly
-experimental and will probably change in the future.
-
-In RPython you can access native .NET classes through the ``CLR``
-object defined in ``translator.cli.dotnet``: from there, you can
-navigate through namespaces using the usual dot notation; for example,
-``CLR.System.Collections.ArrayList`` refers to the ``ArrayList`` class
-in the ``System.Collections`` namespace.
-
-To instantiate a .NET class, simply call it::
-
-    ArrayList = CLR.System.Collections.ArrayList
-    def foo():
-        obj = ArrayList()
-        obj.Add(42)
-        return obj
-
-At the moment there is no special syntax support for indexers and
-properties: for example, you can't access ArrayList's elements using
-the square bracket notation, but you have to call the call the
-``get_Item`` and ``set_Item`` methods; similarly, to access a property
-``XXX`` you need to call ``get_XXX`` and ``set_XXX``::
-
-    def foo():
-        obj = ArrayList()
-        obj.Add(42)
-        print obj.get_Item(0)
-        print obj.get_Count()
-
-Static methods and are also supported, as well as overloadings::
-
-    Math = CLR.System.Math
-    def foo():
-        print Math.Abs(-42)
-        print Math.Abs(-42.0)
-
-
-At the moment, it is not possible to reference assemblies other than
-mscorlib. This will be fixed soon.

pypy/doc/dot-net.rst

 
    cli-backend.rst
    clr-module.rst
-   carbonpython.rst

pypy/translator/cli/carbonpython.py

-#! /usr/bin/env python
-"""
-Usage:  carbonpython.py <module-name> [dll-name]
-
-Compiles an RPython module into a .NET dll.
-"""
-
-import sys
-import new
-import types
-import os.path
-import inspect
-
-from pypy.translator.driver import TranslationDriver
-from pypy.translator.cli.entrypoint import DllEntryPoint
-
-class DllDef:
-    def __init__(self, name, namespace, functions=[], dontmangle=True, isnetmodule=False):
-        self.name = name
-        self.namespace = namespace
-        self.functions = functions # [(function, annotation), ...]
-        self.isnetmodule = isnetmodule
-        self.driver = TranslationDriver()
-        if dontmangle:
-            self.driver.config.translation.ootype.mangle = False
-        self.driver.setup_library(self)
-
-    def add_function(self, func, inputtypes):
-        self.functions.append((func, inputtypes))
-
-    def get_entrypoint(self, bk):
-        graphs = [bk.getdesc(f).cachedgraph(None) for f, _ in self.functions]
-        return DllEntryPoint(self.name, graphs, self.isnetmodule)
-
-    def compile(self):
-        # add all functions to the appropriate namespace
-        if self.namespace:
-            for func, _ in self.functions:
-                if not hasattr(func, '_namespace_'):
-                    func._namespace_ = self.namespace
-        self.driver.proceed(['compile_cli'])
-
-class export(object):
-    def __new__(self, *args, **kwds):
-        if len(args) == 1 and isinstance(args[0], types.FunctionType):
-            func = args[0]
-            func._inputtypes_ = ()
-            return func
-        return object.__new__(self, *args, **kwds)
-    
-    def __init__(self, *args, **kwds):
-        self.inputtypes = args
-        self.namespace = kwds.pop('namespace', None)
-        if len(kwds) > 0:
-            raise TypeError, "unexpected keyword argument: '%s'" % kwds.keys()[0]
-
-    def __call__(self, func):
-        func._inputtypes_ = self.inputtypes
-        if self.namespace is not None:
-            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 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, dllname=None, copy_dll=True):
-    dirname, name = os.path.split(filename)
-    if dllname is None:
-        dllname, _ = os.path.splitext(name)
-    elif dllname.endswith('.dll'):
-        dllname, _ = os.path.splitext(dllname)
-    module = new.module(dllname)
-    namespace = module.__dict__.get('_namespace_', dllname)
-    sys.path.insert(0, dirname)
-    execfile(filename, module.__dict__)
-    sys.path.pop(0)
-
-    dll = DllDef(dllname, namespace)
-    dll.functions = collect_entrypoints(module.__dict__)
-    dll.compile()
-    if copy_dll:
-        dll.driver.copy_cli_dll()
-
-def main(argv):
-    if len(argv) == 2:
-        filename = argv[1]
-        dllname = None
-    elif len(argv) == 3:
-        filename = argv[1]
-        dllname = argv[2]
-    else:
-        print >> sys.stderr, __doc__
-        sys.exit(2)
-
-    if not filename.endswith('.py'):
-        filename += '.py'
-    if not os.path.exists(filename):
-        print >> sys.stderr, "Cannot find file %s" % filename
-        sys.exit(1)
-    compile_dll(filename, dllname)
-
-if __name__ == '__main__':
-    main(sys.argv)
-

pypy/translator/cli/test/mylib.py

-from pypy.translator.cli.carbonpython import export
-
-@export(int, int)
-def sum(a, b):
-    return a+b

pypy/translator/cli/test/test_carbonpython.py

-import py
-py.test.skip("it passes usually, but fails on buildbot, no clue why")
-
-import os
-import os.path
-from pypy.tool import udir
-from pypy.translator.cli.rte import Target
-from pypy.translator.cli.carbonpython import DllDef, export, collect_entrypoints,\
-     collect_class_entrypoints, compile_dll
-from pypy.translator.cli.test.runtest import CliFunctionWrapper, CliTest
-
-TEMPLATE = """
-using System;
-using System.Collections;
-class CarbonPytonTest {
-    public static void Main() {
-        %s
-    }
-}
-"""
-
-class TestCarbonPython(CliTest):
-    
-    def _csharp(self, source, references=[], netmodules=[]):
-        tmpfile = udir.udir.join('tmp.cs')
-        tmpfile.write(TEMPLATE % source)
-        flags = ['/r:%s' % ref for ref in references]
-        flags += ['/addmodule:%s' % mod for mod in netmodules]
-        
-        class MyTarget(Target):
-            SOURCES = [str(tmpfile)]
-            FLAGS = flags
-            OUTPUT = 'tmp.exe'
-            SRC_DIR = str(udir.udir)
-
-        func = CliFunctionWrapper(MyTarget.get())
-        return func()
-
-    def test_compilation(self):
-        res = self._csharp('Console.WriteLine(42);')
-        assert res == 42
-
-    def test_func_namespace(self):
-        def foo(x):
-            return x+1
-        def bar(x):
-            return foo(x)
-        foo._namespace_ = 'MyNamespace.MyClass'
-        bar._namespace_ = 'MyClass'
-        res = self.interpret(bar, [41], backendopt=False)
-        assert res == 42
-
-    def test_simple_functions(self):
-        def foo(x):
-            return x+1
-        def bar(x):
-            return x*2
-        dll = DllDef('test', 'Test', [(foo, [int]),
-                                      (bar, [int])])
-        dll.compile()
-        res = self._csharp('Console.WriteLine("{0}, {1}", Test.foo(42), Test.bar(42));', ['test'])
-        assert res == (43, 84)
-
-    def test_export(self):
-        @export(int, float)
-        def foo(x, y):
-            pass
-        @export(int, float, namespace='test')
-        def bar(x, y):
-            pass
-        @export
-        def baz():
-            pass
-
-        assert foo._inputtypes_ == (int, float)
-        assert not hasattr(foo, '_namespace_')
-        assert bar._inputtypes_ == (int, float)
-        assert bar._namespace_ == 'test'
-        assert baz._inputtypes_ == ()
-
-    def test_collect_entrypoints(self):
-        @export(int, float)
-        def foo(x, y):
-            pass
-        def bar(x, y):
-            pass
-        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):
-        py.test.skip('This test fails every other day. No clue why :-(')
-        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.MyClass obj = new Test.MyClass();
-            obj.__init__(39);
-            Console.WriteLine(obj.add(1, 2));
-        """, ['test'])
-        assert res == 42
-
-    def test_export_cliclass(self):
-        py.test.skip('it fails every other day on builbot, no clue why')
-        from pypy.translator.cli.dotnet import CLR
-        
-        @export(CLR.System.Collections.ArrayList, int)
-        def getitem(obj, i):
-            return obj.get_Item(i)
-
-        entrypoints = collect_entrypoints({'getitem': getitem})
-        dll = DllDef('test', 'Test', entrypoints)
-        dll.compile()
-        res = self._csharp("""
-            ArrayList obj = new ArrayList();
-            obj.Add(42);
-            Console.WriteLine(Test.getitem(obj, 0));
-        """, ['test'])
-        assert res == 42
-
-    def test_compile_dll(self):
-        py.test.skip('This test fails every other day. No clue why :-(')
-        cwd, _ = os.path.split(__file__)
-        mylib_py = os.path.join(cwd, 'mylib.py')
-        compile_dll(mylib_py, copy_dll=False)
-        res = self._csharp("""
-            Console.WriteLine(mylib.sum(20, 22));
-        """, ['mylib'])
-        assert res == 42
-
-    def test_compile_dll_alternative_name(self):
-        cwd, _ = os.path.split(__file__)
-        mylib_py = os.path.join(cwd, 'mylib.py')
-        compile_dll(mylib_py, 'mylibxxx.dll', copy_dll=False)
-        res = self._csharp("""
-            Console.WriteLine(mylibxxx.sum(20, 22));
-        """, ['mylibxxx'])
-        assert res == 42
-
-    def test_compile_netmodule(self):
-        def foo(x):
-            return x+1
-        dll = DllDef('mymodule', 'Test', [(foo, [int])], isnetmodule=True)
-        dll.compile()
-        res = self._csharp('Console.WriteLine("{0}", Test.foo(41));',
-                           netmodules = ['mymodule'])
-