Example #1
0
def test_macro():
    print (parse(stmts='#$ header macro _f(x) := f(x, x.shape)'))
    print (parse(stmts='#$ header macro _g(x) := g(x, x.shape[0], x.shape[1])'))
    print (parse(stmts='#$ header macro (a, b), _f(x) := f(x.shape, x, a, b)'))
    print (parse(stmts='#$ header macro _dswap(x, incx) := dswap(x.shape, x, incx)'))
    print (parse(stmts="#$ header macro _dswap(x, incx=1) := dswap(x.shape, x, incx)"))
    print (parse(stmts='#$ header macro _dswap(x, y, incx=1, incy=1) := dswap(x.shape, x, incx, y, incy)'))
Example #2
0
def epyccel_old(func,
                inputs=None,
                verbose=False,
                modules=[],
                libs=[],
                libdirs=[],
                name=None,
                compiler=None,
                mpi=False,
                static=None,
                only=None,
                openmp=False):
    """Pyccelize a python function and wrap it using f2py.

    func: function, str
        a Python function or source code defining the function

    inputs: str, list, tuple, dict
        inputs can be the function header as a string, or a list/tuple of
        strings or the globals() dictionary

    verbose: bool
        talk more

    modules: list, tuple
        list of dependencies

    libs: list, tuple
        list of libraries

    libdirs: list, tuple
        list of paths for libraries

    name: str
        name of the function, if it is given as a string

    static: list/tuple
        a list of 'static' functions as strings

    only: list/tuple
        a list of what should be exposed by f2py as strings

    openmp: bool
        True if openmp is used. Note that in this case, one need to use nogil
        from cython

    Examples

    The following example shows how to use Pyccel within an IPython session

    >>> #$ header procedure static f_static(int [:]) results(int)
    >>> def f_static(x):
    >>>     y = x[0] - 1
    >>>     return y

    >>> from test_epyccel import epyccel
    >>> f = epyccel(f_static, globals()) # appending IPython history

    >>> header = '#$ header procedure static f_static(int [:]) results(int)'
    >>> f = epyccel(f_static, header) # giving the header explicitly

    Now, **f** is a Fortran function that has been wrapped. It is compatible
    with numpy and you can call it

    >>> import numpy as np
    >>> x = np.array([3, 4, 5, 6], dtype=int)
    >>> y = f(x)

    You can also call it with a list instead of numpy arrays

    >>> f([3, 4, 5])
    2
    """
    if compiler is None:
        compiler = 'gfortran'

    is_module = False
    is_function = False

    if isinstance(func, ModuleType):
        is_module = True

    if callable(func):
        is_function = True

    assert (callable(func) or isinstance(func, str)
            or isinstance(func, ModuleType))

    # ...
    if callable(func) or isinstance(func, ModuleType):
        name = func.__name__

    elif name is None:
        # case of func as a string
        raise ValueError(
            'function name must be provided, in the case of func string')
    # ...

    output_folder = name.rsplit('.', 1)[0] if '.' in name else ''

    # fortran module name
    modname = 'epyccel__' + name

    # ...
    if is_module:
        mod = func
        is_sharedlib = isinstance(getattr(mod, '__loader__', None),
                                  ExtensionFileLoader)

        if is_sharedlib:
            module_filename = inspect.getfile(mod)

            # clean
            cmd = 'rm -f {}'.format(module_filename)
            output = subprocess.check_output(cmd, shell=True)

            # then re-run again
            mod = importlib.import_module(name)
            # we must reload the module, otherwise it is still the .so one
            importlib.reload(mod)
            epyccel_old(mod,
                        inputs=inputs,
                        verbose=verbose,
                        modules=modules,
                        libs=libs,
                        name=name,
                        compiler=compiler,
                        mpi=mpi,
                        static=static,
                        only=only,
                        openmp=openmp)
    # ...

    # ...
    ignored_funcs = None
    if not static:
        if isinstance(func, ModuleType):
            mod = func
            funcs = [
                i for i in dir(mod)
                if isinstance(getattr(mod, i), FunctionType)
            ]

            # remove pyccel.decorators
            ignored_funcs = [
                i for i in funcs
                if getattr(mod, i).__module__ == 'pyccel.decorators'
            ]
            static = [i for i in funcs if not (i in ignored_funcs)]

        else:
            static = [name]
    # ...

    # ...
    headers = None
    if inputs:
        if isinstance(inputs, str):
            headers = inputs

        elif isinstance(inputs, (tuple, list)):
            # find all possible headers
            lines = [
                str(i) for i in inputs
                if (isinstance(i, str) and i.lstrip().startswith('#$ header'))
            ]
            # TODO take the last occurence for f => use zip
            headers = "\n".join([str(i) for i in lines])

        elif isinstance(inputs, dict):
            # case of globals() history from ipython
            if not 'In' in inputs.keys():
                raise ValueError('Expecting `In` key in the inputs dictionary')

            inputs = inputs['In']

            # TODO shall we reverse the list

            # find all possible headers
            lines = [
                str(i) for i in inputs if i.lstrip().startswith('#$ header')
            ]
            # TODO take the last occurence for f => use zip
            headers = "\n".join([str(i) for i in lines])

    # we parse all headers then convert them to static function
    d_headers = {}
    if headers:
        hdr = parse(stmts=headers)
        if isinstance(hdr, FunctionHeader):
            header = hdr.to_static()
            d_headers = {str(name): header}

        elif isinstance(hdr, (tuple, list)):
            hs = [h.to_static() for h in hdr]
            hs = [h for h in hs if hs.func == name]
            # TODO improve
            header = hs[0]
            raise NotImplementedError('TODO')

        else:
            raise NotImplementedError('TODO')
    # ...

    # ...
    if not static:
        raise NotImplementedError('TODO')
    # ...

    # ... get the function source code
    if callable(func):
        code = get_source_function(func)

    elif isinstance(func, ModuleType):
        lines = inspect.getsourcelines(func)[0]
        code = ''.join(lines)

    else:
        code = func
    # ...

    if verbose:
        print('------')
        print(code)
        print('------')

    extra_args = ''
    include_args = ''

    if libdirs:
        libdirs = ['-L{}'.format(i) for i in libdirs]
        extra_args += ' '.join(i for i in libdirs)

    try:
        # ...
        pyccel = Parser(code,
                        headers=d_headers,
                        static=static,
                        output_folder=output_folder)
        ast = pyccel.parse()

        settings = {}
        ast = pyccel.annotate(**settings)

        codegen = Codegen(ast, modname)
        code = codegen.doprint()
        # ...

        # reset Errors singleton
        errors = Errors()
        errors.reset()

    except:
        # reset Errors singleton
        errors = Errors()
        errors.reset()

        raise PyccelError('Could not convert to Fortran')

    # Change module name to avoid name clashes: Python cannot import two modules with the same name
    if is_module:
        head, sep, tail = name.rpartition('.')
        name = sep.join([head, '__epyccel__' + tail])
    else:
        name = '__epyccel__' + name

    # Find directory where Fortran extension module should be created
    if is_module:
        dirname = os.path.dirname(os.path.abspath(mod.__file__))
    else:
        dirname = os.path.dirname(
            os.path.abspath(sys.modules[func.__module__].__file__))

    # Move into working directory, create extension module, then move back to original directory
    origin = os.path.abspath(os.curdir)
    os.chdir(dirname)
    output, cmd = compile_fortran(code,
                                  name,
                                  extra_args=extra_args,
                                  libs=libs,
                                  compiler=compiler,
                                  mpi=mpi,
                                  openmp=openmp,
                                  includes=include_args,
                                  only=only)
    os.chdir(origin)

    if verbose:
        print(cmd)

    if verbose:
        print(code)
    # ...

    # ...
    try:
        if PY_VERSION == (3, 7):
            dirname = os.path.relpath(dirname).replace('/', '.')
            package = dirname + '.' + name
            package = importlib.import_module('..' + name, package=package)
            clean_extension_module(package, modname)
        else:
            os.chdir(dirname)
            package = importlib.import_module(name)
            clean_extension_module(package, modname)
            os.chdir(origin)

    except:
        raise ImportError('could not import {0}'.format(name))
    # ...

    if is_module:
        return package
    else:
        return getattr(package, func.__name__.lower())
Example #3
0
def test_function():
    print (parse(stmts='#$ header function f(float [:], int [:]) results(int)'))
Example #4
0
def test_variable():
    print (parse(stmts='#$ header variable x :: int'))
    print (parse(stmts='#$ header variable x float [:, :]'))
Example #5
0
def test_metavar():
    print (parse(stmts="#$ header metavar module_name='mpi'"))
Example #6
0
def test_method():
    print (parse(stmts='#$ header method translate(Point, double, double)'))
Example #7
0
def test_class():
    print (parse(stmts='#$ header class Square(public)'))