Beispiel #1
0
def new_variable(dtype, var, tag=None, prefix=None, kind=None):

    # ...
    if prefix is None:
        prefix = ''

    _prefix = '{}'.format(prefix)
    # ...

    # ...
    if dtype == 'int':
        if kind == 'len':
            _prefix = 'n{}'.format(_prefix)

        elif kind == 'multi':
            _prefix = 'im{}'.format(_prefix)

        else:
            _prefix = 'i{}'.format(_prefix)

    elif dtype == 'real':
        _prefix = 'r{}'.format(_prefix)

    else:
        raise NotImplementedError()
    # ...

    # ...
    if tag is None:
        tag = random_string(4)
    # ...

    pattern = '{prefix}{dim}_{tag}'
    _print = lambda d, t: pattern.format(prefix=_prefix, dim=d, tag=t)

    if isinstance(var, Variable):
        assert (var.rank > 0)

        if var.rank == 1:
            name = _print('', tag)
            return Variable(dtype, name)

        else:
            indices = []
            for d in range(0, var.rank):
                name = _print(d, tag)
                indices.append(Variable(dtype, name))

            return Tuple(*indices)

    elif isinstance(var, (list, tuple, Tuple)):
        ls = [
            new_variable(dtype, x, tag=tag, prefix=str(i), kind=kind)
            for i, x in enumerate(var)
        ]
        return Tuple(*ls)

    else:
        raise NotImplementedError('{} not available'.format(type(var)))
Beispiel #2
0
    def get_PyArgParseType(self, used_names, variable):
        """
        Responsible for creating any necessary intermediate variables which are used
        to collect the result of PyArgParse, and collecting the required cast function

        Parameters:
        ----------
        used_names : list of strings
            List of variable and function names to avoid name collisions

        variable : Variable
            The variable which will be passed to the translated function

        Returns
        -------
        collect_var : Variable
            The variable which will be used to collect the argument

        cast_fun : FunctionCall
            call to cast function responsible of the conversion of one data type into another
        """
        cast_function = None
        collect_var = variable

        if variable.rank > 0:
            collect_type = PyccelPyArrayObject()
            collect_var = Variable(dtype=collect_type,
                                   is_pointer=True,
                                   rank=variable.rank,
                                   order=variable.order,
                                   name=self.get_new_name(
                                       used_names, variable.name + "_tmp"))

        elif isinstance(variable, ValuedVariable):
            collect_type = PyccelPyObject()
            collect_var = Variable(dtype=collect_type,
                                   is_pointer=True,
                                   name=self.get_new_name(
                                       used_names, variable.name + "_tmp"))

        elif variable.dtype is NativeBool():
            collect_type = NativeInteger()
            collect_var = Variable(dtype=collect_type,
                                   precision=4,
                                   name=self.get_new_name(
                                       used_names, variable.name + "_tmp"))
            cast_function = self.get_cast_function_call(
                'pyint_to_bool', collect_var)

        elif variable.dtype is NativeComplex():
            collect_type = PyccelPyObject()
            collect_var = Variable(dtype=collect_type,
                                   is_pointer=True,
                                   name=self.get_new_name(
                                       used_names, variable.name + "_tmp"))

        return collect_var, cast_function
Beispiel #3
0
 def _get_static_function(self, used_names, function, collect_dict):
     """
     Create arguments and functioncall for arguments rank > 0 in fortran.
     Format : a is numpy array
     func(a) ==> static_func(a.DIM , a.DATA)
     where a.DATA = buffer holding data
           a.DIM = size of array
     """
     additional_body = []
     if self._target_language == 'fortran':
         static_args = []
         for a in function.arguments:
             if isinstance(a, Variable) and a.rank > 0:
                 # Add shape arguments for static function
                 for i in range(collect_dict[a].rank):
                     var = Variable(dtype=NativeInteger(),
                                    name=self.get_new_name(
                                        used_names, a.name + "_dim"))
                     body = FunctionCall(numpy_get_dim,
                                         [collect_dict[a], i])
                     if a.is_optional:
                         body = IfTernaryOperator(
                             VariableAddress(collect_dict[a]), body,
                             LiteralInteger(0))
                     body = Assign(var, body)
                     additional_body.append(body)
                     static_args.append(var)
             static_args.append(a)
         static_function = as_static_function_call(function,
                                                   self._module_name,
                                                   name=function.name)
     else:
         static_function = function
         static_args = function.arguments
     return static_function, static_args, additional_body
Beispiel #4
0
    def _body_management(self,
                         used_names,
                         variable,
                         collect_var,
                         cast_function,
                         check_type=False):
        """
        Responsible for calling functions that take care of body creation
        """
        tmp_variable = None
        body = []

        if variable.rank > 0:
            body = self._body_array(variable, collect_var, check_type)

        elif variable.is_optional:
            tmp_variable = Variable(dtype=variable.dtype,
                                    name=self.get_new_name(
                                        used_names, variable.name + "_tmp"))
            body = self._body_optional_variable(tmp_variable, variable,
                                                collect_var, check_type)

        elif isinstance(variable, ValuedVariable):
            body = self._body_valued_variable(variable, collect_var,
                                              check_type)

        elif isinstance(collect_var.dtype, PyccelPyObject):
            body = [self._create_collecting_value_body(variable, collect_var)]

        elif cast_function is not None:
            body = [Assign(variable, cast_function)]

        return body, tmp_variable
Beispiel #5
0
    def get_PyBuildValue(self, used_names, variable):
        """
        Responsible for collecting the variable required to build the result
        and the necessary cast function

        Parameters:
        ----------
        used_names : list of strings
            List of variable and function names to avoid name collisions

        variable : Variable
            The variable returned by the translated function

        Returns
        -------
        collect_var : Variable
            The variable which will be provided to PyBuild

        cast_func_stmts : functionCall
            call to cast function responsible of the conversion of one data type into another
        """
        collect_var = variable
        cast_function = None

        if variable.dtype is NativeBool():
            collect_type = PyccelPyObject()
            collect_var = Variable(dtype=collect_type,
                                   is_pointer=True,
                                   name=self.get_new_name(
                                       used_names, variable.name + "_tmp"))
            cast_function = self.get_cast_function_call(
                'bool_to_pyobj', variable)

        if variable.dtype is NativeComplex():
            collect_type = PyccelPyObject()
            collect_var = Variable(dtype=collect_type,
                                   is_pointer=True,
                                   name=self.get_new_name(
                                       used_names, variable.name + "_tmp"))
            cast_function = self.get_cast_function_call(
                'complex_to_pycomplex', variable)
            self._to_free_PyObject_list.append(collect_var)

        return collect_var, cast_function
Beispiel #6
0
    def _visit_TypeVariable(self, stmt):
        t_var = stmt

        d_var = _attributs_default()
        d_var = _attributs_from_type(t_var, d_var)

        dtype = d_var.pop('dtype')
        name = 'dummy_{}'.format(stmt.tag)
        var = Variable(dtype, name, **d_var)

        return var
Beispiel #7
0
    def _visit_TypeList(self, stmt):
        t_var = stmt

        rank = len(stmt)
        var = self._visit(stmt.types)

        if isinstance(var, Tuple):
            ls = []
            for e, v in enumerate(var):
                d_var = _attributs_default()
                d_var = _attributs_from_type(v, d_var)
                d_var['rank'] += rank

                dtype = d_var.pop('dtype')
                name = 'dummy_{}_{}'.format(e, stmt.tag)
                var = Variable(dtype, name, **d_var)

                ls.append(var)

            return Tuple(*ls)

        elif isinstance(var, Variable):
            d_var = _attributs_default()
            d_var = _attributs_from_type(var, d_var)
            d_var['rank'] += rank

            dtype = d_var.pop('dtype')
            name = 'dummy_{}'.format(stmt.tag)
            var = Variable(dtype, name, **d_var)

            return var

        else:
            msg = 'Expecting a Tuple or Variable, but {} was given'
            msg = msg.format(type(var))
            raise TypeError(msg)
Beispiel #8
0
    def _visit_TypeTuple(self, stmt):
        ls = []
        for e, t_var in enumerate(stmt.types):
            d_var = _attributs_default()
            d_var = _attributs_from_type(t_var, d_var)

            dtype = d_var.pop('dtype')
            name = 'dummy_{}_{}'.format(e, stmt.tag)
            var = Variable(dtype, name, **d_var)

            ls.append(var)

        var = Tuple(*ls)
        if len(var) == 1:
            return var[0]

        else:
            return var
Beispiel #9
0
def sanitize_arguments(args):
    _args = []
    for a in args:
        if isinstance(a, (Variable, FunctionAddress)):
            _args.append(a)

        elif isinstance(a, IndexedVariable):
            a_new = Variable(a.dtype,
                             str(a.name),
                             shape=a.shape,
                             rank=a.rank,
                             order=a.order,
                             precision=a.precision)

            _args.append(a_new)

        else:
            raise NotImplementedError('TODO for {}'.format(type(a)))

    return _args
Beispiel #10
0
 def create_tmp_var(self, match_var):
     tmp_var_name = self._parser.get_new_name('tmp')
     tmp_var = Variable(name=tmp_var_name, dtype=match_var.dtype)
     self._additional_declare.append(tmp_var)
     return tmp_var
Beispiel #11
0
    def _print_Interface(self, expr):

        # Collecting all functions
        funcs = expr.functions
        # Save all used names
        used_names = set(n.name for n in funcs)

        # Find a name for the wrapper function
        wrapper_name = self._get_wrapper_name(used_names, expr)
        self._global_names.add(wrapper_name)

        # Collect local variables
        python_func_args = self.get_new_PyObject("args", used_names)
        python_func_kwargs = self.get_new_PyObject("kwargs", used_names)
        python_func_selfarg = self.get_new_PyObject("self", used_names)

        # Collect wrapper arguments and results
        wrapper_args = [
            python_func_selfarg, python_func_args, python_func_kwargs
        ]
        wrapper_results = [self.get_new_PyObject("result", used_names)]

        # Collect parser arguments
        wrapper_vars = {}

        # Collect argument names for PyArgParse
        arg_names = [a.name for a in funcs[0].arguments]
        keyword_list_name = self.get_new_name(used_names, 'kwlist')
        keyword_list = PyArgKeywords(keyword_list_name, arg_names)
        wrapper_body = [keyword_list]

        wrapper_body_translations = []
        body_tmp = []

        # To store the mini function responsible of collecting value and calling interfaces functions and return the builded value
        funcs_def = []
        default_value = {
        }  # dict to collect all initialisation needed in the wrapper
        check_var = Variable(dtype=NativeInteger(),
                             name=self.get_new_name(used_names, "check"))
        wrapper_vars[check_var.name] = check_var
        types_dict = OrderedDict(
            (a, set()) for a in funcs[0].arguments
        )  #dict to collect each variable possible type and the corresponding flags
        # collect parse arg
        parse_args = [
            Variable(dtype=PyccelPyArrayObject(),
                     is_pointer=True,
                     rank=a.rank,
                     order=a.order,
                     name=self.get_new_name(used_names, a.name +
                                            "_tmp")) if a.rank > 0 else
            Variable(dtype=PyccelPyObject(),
                     name=self.get_new_name(used_names, a.name + "_tmp"),
                     is_pointer=True) for a in funcs[0].arguments
        ]
        # Managing the body of wrapper
        for func in funcs:
            mini_wrapper_func_body = []
            res_args = []
            mini_wrapper_func_vars = {a.name: a for a in func.arguments}
            flags = 0
            collect_vars = {}

            # Loop for all args in every functions and create the corresponding condition and body
            for p_arg, f_arg in zip(parse_args, func.arguments):
                collect_vars[f_arg] = p_arg
                body, tmp_variable = self._body_management(
                    used_names, f_arg, p_arg, None)
                if tmp_variable:
                    mini_wrapper_func_vars[tmp_variable.name] = tmp_variable

                # get check type function
                check = self._get_check_type_statement(f_arg, p_arg)
                # If the variable cannot be collected from PyArgParse directly
                wrapper_vars[p_arg.name] = p_arg

                # Save the body
                wrapper_body_translations.extend(body)

                # Write default values
                if isinstance(f_arg, ValuedVariable):
                    wrapper_body.append(
                        self.get_default_assign(parse_args[-1], f_arg))

                flag_value = flags_registry[(f_arg.dtype, f_arg.precision)]
                flags = (flags << 4) + flag_value  # shift by 4 to the left
                types_dict[f_arg].add(
                    (f_arg, check,
                     flag_value))  # collect variable type for each arguments
                mini_wrapper_func_body += body

            # create the corresponding function call
            static_function, static_args, additional_body = self._get_static_function(
                used_names, func, collect_vars)
            mini_wrapper_func_body.extend(additional_body)

            for var in static_args:
                mini_wrapper_func_vars[var.name] = var

            if len(func.results) == 0:
                func_call = FunctionCall(static_function, static_args)
            else:
                results = func.results if len(
                    func.results) > 1 else func.results[0]
                func_call = Assign(results,
                                   FunctionCall(static_function, static_args))

            mini_wrapper_func_body.append(func_call)

            # Loop for all res in every functions and create the corresponding body and cast
            for r in func.results:
                collect_var, cast_func = self.get_PyBuildValue(used_names, r)
                mini_wrapper_func_vars[collect_var.name] = collect_var
                if cast_func is not None:
                    mini_wrapper_func_vars[r.name] = r
                    mini_wrapper_func_body.append(
                        AliasAssign(collect_var, cast_func))
                res_args.append(
                    VariableAddress(collect_var) if collect_var.
                    is_pointer else collect_var)

            # Building PybuildValue and freeing the allocated variable after.
            mini_wrapper_func_body.append(
                AliasAssign(wrapper_results[0], PyBuildValueNode(res_args)))
            mini_wrapper_func_body += [
                FunctionCall(Py_DECREF, [i])
                for i in self._to_free_PyObject_list
            ]
            mini_wrapper_func_body.append(Return(wrapper_results))
            self._to_free_PyObject_list.clear()
            # Building Mini wrapper function
            mini_wrapper_func_name = self.get_new_name(
                used_names.union(self._global_names),
                func.name.name + '_mini_wrapper')
            self._global_names.add(mini_wrapper_func_name)

            mini_wrapper_func_def = FunctionDef(
                name=mini_wrapper_func_name,
                arguments=parse_args,
                results=wrapper_results,
                body=mini_wrapper_func_body,
                local_vars=mini_wrapper_func_vars.values())
            funcs_def.append(mini_wrapper_func_def)

            # append check condition to the functioncall
            body_tmp.append((PyccelEq(check_var, LiteralInteger(flags)), [
                AliasAssign(wrapper_results[0],
                            FunctionCall(mini_wrapper_func_def, parse_args))
            ]))

        # Errors / Types management
        # Creating check_type function
        check_func_def = self._create_wrapper_check(check_var, parse_args,
                                                    types_dict, used_names,
                                                    funcs[0].name.name)
        funcs_def.append(check_func_def)

        # Create the wrapper body with collected informations
        body_tmp = [((PyccelNot(check_var), [Return([Nil()])]))] + body_tmp
        body_tmp.append((LiteralTrue(), [
            PyErr_SetString('PyExc_TypeError',
                            '"Arguments combinations don\'t exist"'),
            Return([Nil()])
        ]))
        wrapper_body_translations = [If(*body_tmp)]

        # Parsing Arguments
        parse_node = PyArg_ParseTupleNode(python_func_args, python_func_kwargs,
                                          funcs[0].arguments, parse_args,
                                          keyword_list, True)
        wrapper_body += list(default_value.values())
        wrapper_body.append(If((PyccelNot(parse_node), [Return([Nil()])])))

        #finishing the wrapper body
        wrapper_body.append(
            Assign(check_var, FunctionCall(check_func_def, parse_args)))
        wrapper_body.extend(wrapper_body_translations)
        wrapper_body.append(Return(wrapper_results))  # Return

        # Create FunctionDef
        funcs_def.append(
            FunctionDef(name=wrapper_name,
                        arguments=wrapper_args,
                        results=wrapper_results,
                        body=wrapper_body,
                        local_vars=wrapper_vars.values()))

        sep = self._print(SeparatorComment(40))

        return sep + '\n'.join(
            CCodePrinter._print_FunctionDef(self, f) for f in funcs_def)
Beispiel #12
0
def as_static_function(func):
    assert (isinstance(func, FunctionDef))

    args = func.arguments
    results = func.results
    body = func.body
    arguments_inout = func.arguments_inout
    functions = func.functions
    _results = []
    if results:
        if len(results) == 1:
            result = results[0]
            if result.rank > 0:
                # updates args
                args = list(args) + [result]
                arguments_inout += [False]
            else:
                _results = results

        else:
            raise NotImplementedError('when len(results) > 1')

    name = 'f2py_{}'.format(func.name).lower()

    # ...
    results_names = [i.name for i in results]
    _args = []
    _arguments_inout = []
    for i_a, a in enumerate(args):
        if not isinstance(a, Variable):
            raise TypeError('Expecting a Variable type for {}'.format(a))

        rank = a.rank
        if rank > 0:
            # ...
            additional_args = []
            for i in range(0, rank):
                n_name = 'n{i}_{name}'.format(name=str(a.name), i=i)
                n_arg = Variable('int', n_name)

                additional_args += [n_arg]

            shape_new = Tuple(*additional_args, sympify=False)
            # ...

            _args += additional_args
            for j in additional_args:
                _arguments_inout += [False]

            a_new = Variable(a.dtype,
                             a.name,
                             allocatable=a.allocatable,
                             is_pointer=a.is_pointer,
                             is_target=a.is_target,
                             is_optional=a.is_optional,
                             shape=shape_new,
                             rank=a.rank,
                             order=a.order,
                             precision=a.precision)

            if not (a.name in results_names):
                _args += [a_new]

            else:
                _results += [a_new]

        else:
            _args += [a]

        intent = arguments_inout[i_a]
        _arguments_inout += [intent]

    args = _args
    results = _results
    arguments_inout = _arguments_inout
    # ...

    return FunctionDef(name,
                       list(args),
                       results,
                       body,
                       local_vars=func.local_vars,
                       is_static=True,
                       arguments_inout=arguments_inout,
                       functions=functions)
Beispiel #13
0
    def __init__(self, expr, **kwargs):
        assert (isinstance(expr, Lambda))

        self._expr = LampyLambda(expr)

        # ...
        self._d_types = {}
        self._d_domain_types = {
        }  # for each codomain we store its associated domain type
        self._d_expr = {}
        self._tag = random_string(8)

        # TODO to be removed later?
        self._d_functions = {}

        # to store current typed expr
        # this must not be a private variable,
        # in order to modify it on the fly
        self.main = self.expr
        self.main_type = None
        # ...

        # ... add types for arguments and results
        #     TODO use domain and codomain optional args for functions
        self._typed_functions = kwargs.pop('typed_functions', {})
        for f in self.typed_functions.values():
            type_domain = assign_type(f.arguments)
            type_codomain = assign_type(f.results)

            self._set_type(f, value=type_domain, domain=True)
            self._set_type(f, value=type_codomain, codomain=True)
            self._set_domain_type(type_domain, type_codomain)
            self._insert_function(f, type_domain, type_codomain)
        # ...

        # ... default Type
        prefix = kwargs.pop('prefix', 'd')  # doubles as default
        dtype = None
        precision = None
        if prefix == 'i':
            dtype = Int
            precision = 4

        elif prefix == 's':
            dtype = Real
            precision = 4

        elif prefix == 'd':
            dtype = Real
            precision = 8

        elif prefix == 'c':
            dtype = Complex
            precision = 8

        elif prefix == 'z':
            dtype = Complex
            precision = 16

        else:
            raise ValueError('Wrong prefix. Available: i, s, d, c, z')

        var = Variable(dtype, 'dummy_' + self.tag, precision=precision)
        self._default_type = TypeVariable(var)
        # ...

        # ... get all functions
        functions = list(expr.atoms(FunctionSymbol))

        for f in functions:
            if f.name in _elemental_math_functions:
                type_domain = self.default_type
                type_codomain = self.default_type

                self._set_type(f, value=type_domain, domain=True)
                self._set_type(f, value=type_codomain, codomain=True)
                self._set_domain_type(type_domain, type_codomain)
                self._insert_function(str(f), type_domain, type_codomain)

            elif not str(f) in list(_internal_applications) + list(
                    self.typed_functions.keys()):
                raise NotImplementedError('{} not available'.format(str(f)))
Beispiel #14
0
 def get_new_PyObject(self, name, used_names):
     return Variable(dtype=PyccelPyObject(),
                     name=self.get_new_name(used_names, name),
                     is_pointer=True)
Beispiel #15
0
def as_static_function(func, name=None):

    assert(isinstance(func, FunctionDef))

    args    = list(func.arguments)
    results = list(func.results)
    body    = func.body
    arguments_inout = func.arguments_inout
    functions = func.functions
    _results = []
    interfaces = func.interfaces

    # Convert array results to inout arguments
    for r in results:
        if r.rank > 0 and r not in args:
            args += [r]
            arguments_inout += [False]
        elif r.rank == 0:
            _results += [r]

    if name is None:
        name = 'bind_c_{}'.format(func.name).lower()

    # ...
    results_names = [i.name for i in _results]
    _args = []
    _arguments_inout = []

    for i_a, a in enumerate(args):
        if not isinstance(a, (Variable, FunctionAddress)):
            raise TypeError('Expecting a Variable or FunctionAddress type for {}'.format(a))
        if not isinstance(a, FunctionAddress) and a.rank > 0:
            # ...
            additional_args = []
            for i in range(a.rank):
                n_name = 'n{i}_{name}'.format(name=str(a.name), i=i)
                n_arg  = Variable('int', n_name, precision=4)

                additional_args += [n_arg]

            shape_new = Tuple(*additional_args, sympify=False)
            # ...

            _args += additional_args
            _arguments_inout += [False] * len(additional_args)

            a_new = Variable( a.dtype, a.name,
                              allocatable = a.allocatable,
                              is_pointer  = a.is_pointer,
                              is_target   = a.is_target,
                              is_optional = a.is_optional,
                              shape       = shape_new,
                              rank        = a.rank,
                              order       = a.order,
                              precision   = a.precision)

            if not( a.name in results_names ):
                _args += [a_new]

            else:
                _results += [a_new]

        else:
            _args += [a]

        intent = arguments_inout[i_a]
        _arguments_inout += [intent]
    args = _args
    results = _results
    arguments_inout = _arguments_inout
    # ...
    return BindCFunctionDef( name, list(args), results, body,
                        local_vars = func.local_vars,
                        is_static = True,
                        arguments_inout = arguments_inout,
                        functions = functions,
                        interfaces = interfaces,
                        imports = func.imports,
                        original_function = func,
                        doc_string = func.doc_string,
                        )
Beispiel #16
0
    def expr(self):
        name = str(self.name)
        dtype = _construct_dtype(self.dtype)

        # TODO must return a TypedFunction
        return Variable(dtype, name)
Beispiel #17
0
 def expr(self):
     name = str(self.name)
     dtype = datatype(str(self.dtype))
     return Variable(dtype, name)