Example #1
0
def generate_cxx(module_name, code, specs=None, optimizations=None):
    '''python + pythran spec -> c++ code
    returns a PythonModule object

    '''
    if sys.version_info[0] == 3:
        raise ValueError(
            "Pythran does not fully support Python3, "
            "it can only be used to compile C++ code "
            "generated with the -E flag with a Python2 version of Pythran. "
            "Sorry about this :-/")

    pm = PassManager(module_name)

    # front end
    ir, renamings, docstrings = frontend.parse(pm, code)

    # middle-end
    optimizations = (optimizations or
                     cfg.get('pythran', 'optimizations').split())
    optimizations = [_parse_optimization(opt) for opt in optimizations]
    refine(pm, ir, optimizations)

    # back-end
    content = pm.dump(Cxx, ir)

    # instanciate the meta program
    if specs is None:

        class Generable(object):
            def __init__(self, content):
                self.content = content

            def __str__(self):
                return str(self.content)

            generate = __str__

        mod = Generable(content)
    else:

        # uniform typing
        for fname, signatures in specs.items():
            if not isinstance(signatures, tuple):
                specs[fname] = (signatures,)

        # verify the pythran export are compatible with the code
        specs = expand_specs(specs)
        check_specs(ir, specs, renamings)
        specs_to_docstrings(specs, docstrings)

        metainfo = {'hash': hashlib.sha256(code).hexdigest(),
                    'version': __version__,
                    'date': datetime.now()}

        mod = PythonModule(module_name, docstrings, metainfo)
        mod.add_to_preamble(Define("BOOST_SIMD_NO_STRICT_ALIASING", "1"))
        mod.add_to_includes(Include("pythonic/core.hpp"),
                            Include("pythonic/python/core.hpp"),
                            # FIXME: only include these when needed
                            Include("pythonic/types/bool.hpp"),
                            Include("pythonic/types/int.hpp"),
                            Line("#ifdef _OPENMP\n#include <omp.h>\n#endif")
                            )
        mod.add_to_includes(*[Include(inc) for inc in
                              _extract_specs_dependencies(specs)])
        mod.add_to_includes(*content.body)

        for function_name, signatures in specs.iteritems():
            internal_func_name = renamings.get(function_name,
                                               function_name)
            # global variables are functions with no signatures :-)
            if not signatures:
                mod.add_global_var(function_name,
                                   "{}()()".format(
                                       pythran_ward + '{0}::{1}'.format(
                                           module_name, internal_func_name)))

            for sigid, signature in enumerate(signatures):
                numbered_function_name = "{0}{1}".format(internal_func_name,
                                                         sigid)
                arguments_types = [pytype_to_ctype(t) for t in signature]
                has_arguments = HasArgument(internal_func_name).visit(ir)
                arguments = ["a{0}".format(i)
                             for i in xrange(len(arguments_types))]
                name_fmt = pythran_ward + "{0}::{1}::type{2}"
                args_list = ", ".join(arguments_types)
                specialized_fname = name_fmt.format(module_name,
                                                    internal_func_name,
                                                    "<{0}>".format(args_list)
                                                    if has_arguments else "")
                result_type = "typename %s::result_type" % specialized_fname
                mod.add_function(
                    FunctionBody(
                        FunctionDeclaration(
                            Value(
                                result_type,
                                numbered_function_name),
                            [Value(t, a)
                             for t, a in zip(arguments_types, arguments)]),
                        Block([Statement("return {0}()({1})".format(
                            pythran_ward + '{0}::{1}'.format(
                                module_name, internal_func_name),
                            ', '.join(arguments)))])
                    ),
                    function_name,
                    arguments_types
                )
    return mod
Example #2
0
def generate_cxx(module_name, code, specs=None, optimizations=None):
    '''python + pythran spec -> c++ code
    returns a PythonModule object

    '''
    if sys.version_info[0] == 3:
        raise ValueError(
            "Pythran does not fully support Python3, "
            "it can only be used to compile C++ code "
            "generated with the -E flag with a Python2 version of Pythran. "
            "Sorry about this :-/")

    pm = PassManager(module_name)

    # front end
    ir, renamings, docstrings = frontend.parse(pm, code)

    # middle-end
    optimizations = (optimizations
                     or cfg.get('pythran', 'optimizations').split())
    optimizations = [_parse_optimization(opt) for opt in optimizations]
    refine(pm, ir, optimizations)

    # back-end
    content = pm.dump(Cxx, ir)

    # instanciate the meta program
    if specs is None:

        class Generable(object):
            def __init__(self, content):
                self.content = content

            def __str__(self):
                return str(self.content)

            generate = __str__

        mod = Generable(content)
    else:

        # uniform typing
        for fname, signatures in specs.items():
            if not isinstance(signatures, tuple):
                specs[fname] = (signatures, )

        # verify the pythran export are compatible with the code
        specs = expand_specs(specs)
        check_specs(ir, specs, renamings)
        specs_to_docstrings(specs, docstrings)

        metainfo = {
            'hash': hashlib.sha256(code).hexdigest(),
            'version': __version__,
            'date': datetime.now()
        }

        mod = PythonModule(module_name, docstrings, metainfo)
        mod.add_to_preamble(Define("BOOST_SIMD_NO_STRICT_ALIASING", "1"))
        mod.add_to_includes(
            Include("pythonic/core.hpp"),
            Include("pythonic/python/core.hpp"),
            # FIXME: only include these when needed
            Include("pythonic/types/bool.hpp"),
            Include("pythonic/types/int.hpp"),
            Line("#ifdef _OPENMP\n#include <omp.h>\n#endif"))
        mod.add_to_includes(
            *[Include(inc) for inc in _extract_specs_dependencies(specs)])
        mod.add_to_includes(*content.body)

        for function_name, signatures in specs.iteritems():
            internal_func_name = renamings.get(function_name, function_name)
            # global variables are functions with no signatures :-)
            if not signatures:
                mod.add_global_var(
                    function_name, "{}()()".format(
                        pythran_ward +
                        '{0}::{1}'.format(module_name, internal_func_name)))

            for sigid, signature in enumerate(signatures):
                numbered_function_name = "{0}{1}".format(
                    internal_func_name, sigid)
                arguments_types = [pytype_to_ctype(t) for t in signature]
                has_arguments = HasArgument(internal_func_name).visit(ir)
                arguments = [
                    "a{0}".format(i) for i in xrange(len(arguments_types))
                ]
                name_fmt = pythran_ward + "{0}::{1}::type{2}"
                args_list = ", ".join(arguments_types)
                specialized_fname = name_fmt.format(
                    module_name, internal_func_name,
                    "<{0}>".format(args_list) if has_arguments else "")
                result_type = "typename %s::result_type" % specialized_fname
                mod.add_function(
                    FunctionBody(
                        FunctionDeclaration(
                            Value(result_type, numbered_function_name), [
                                Value(t, a)
                                for t, a in zip(arguments_types, arguments)
                            ]),
                        Block([
                            Statement("return {0}()({1})".format(
                                pythran_ward + '{0}::{1}'.format(
                                    module_name, internal_func_name),
                                ', '.join(arguments)))
                        ])), function_name, arguments_types)
    return mod
Example #3
0
def generate_cxx(module_name, code, specs=None, optimizations=None):
    '''python + pythran spec -> c++ code
    returns a PythonModule object

    '''

    pm = PassManager(module_name)

    # front end
    ir, renamings, docstrings = frontend.parse(pm, code)

    # middle-end
    optimizations = (optimizations or
                     cfg.get('pythran', 'optimizations').split())
    optimizations = [_parse_optimization(opt) for opt in optimizations]
    refine(pm, ir, optimizations)

    # type check
    types = tog.typecheck(ir)

    # back-end
    content = pm.dump(Cxx, ir)

    # instantiate the meta program
    if specs is None:

        class Generable(object):
            def __init__(self, content):
                self.content = content

            def __str__(self):
                return str(self.content)

            generate = __str__

        mod = Generable(content)
    else:

        # uniform typing
        for fname, signatures in list(specs.items()):
            if not isinstance(signatures, tuple):
                specs[fname] = (signatures,)

        # verify the pythran export are compatible with the code
        specs = expand_specs(specs)
        check_specs(ir, specs, renamings, types)
        specs_to_docstrings(specs, docstrings)

        if isinstance(code, bytes):
            code_bytes = code
        else:
            code_bytes = code.encode('ascii', 'ignore')
        metainfo = {'hash': hashlib.sha256(code_bytes).hexdigest(),
                    'version': __version__,
                    'date': datetime.now()}

        mod = PythonModule(module_name, docstrings, metainfo)
        mod.add_to_preamble(Define("BOOST_SIMD_NO_STRICT_ALIASING", "1"))
        mod.add_to_includes(
            Include("pythonic/core.hpp"),
            Include("pythonic/python/core.hpp"),
            # FIXME: only include these when needed
            Include("pythonic/types/bool.hpp"),
            Include("pythonic/types/int.hpp"),
            Line("#ifdef _OPENMP\n#include <omp.h>\n#endif")
        )
        mod.add_to_includes(*[Include(inc) for inc in
                              _extract_specs_dependencies(specs)])
        mod.add_to_includes(*content.body)
        mod.add_to_includes(
            Include("pythonic/python/exception_handler.hpp"),
        )

        for function_name, signatures in specs.items():
            internal_func_name = renamings.get(function_name,
                                               function_name)
            # global variables are functions with no signatures :-)
            if not signatures:
                mod.add_global_var(function_name,
                                   "{}()()".format(
                                       pythran_ward + '{0}::{1}'.format(
                                           module_name, internal_func_name)))

            for sigid, signature in enumerate(signatures):
                numbered_function_name = "{0}{1}".format(internal_func_name,
                                                         sigid)
                arguments_types = [pytype_to_ctype(t) for t in signature]
                has_arguments = HasArgument(internal_func_name).visit(ir)
                arguments = ["a{0}".format(i)
                             for i in range(len(arguments_types))]
                name_fmt = pythran_ward + "{0}::{1}::type{2}"
                args_list = ", ".join(arguments_types)
                specialized_fname = name_fmt.format(module_name,
                                                    internal_func_name,
                                                    "<{0}>".format(args_list)
                                                    if has_arguments else "")
                result_type = "typename %s::result_type" % specialized_fname
                mod.add_function(
                    FunctionBody(
                        FunctionDeclaration(
                            Value(
                                result_type,
                                numbered_function_name),
                            [Value(t, a)
                             for t, a in zip(arguments_types, arguments)]),
                        Block([Statement("""
                            PyThreadState *_save = PyEval_SaveThread();
                            try {{
                                auto res = {0}()({1});
                                PyEval_RestoreThread(_save);
                                return res;
                            }}
                            catch(...) {{
                                PyEval_RestoreThread(_save);
                                throw;
                            }}
                            """.format(
                            pythran_ward + '{0}::{1}'.format(
                                module_name, internal_func_name),
                            ', '.join(arguments)))])
                    ),
                    function_name,
                    arguments_types
                )
    return mod