Example #1
0
def cse(expr):
    """ symplify a complicated sympy expression
        into a list of expression using the cse
        sympy function
    """
    ls = list(expr.atoms(Sum))
    if not ls:
        return [expr]
    ls += [expr]
    (ls, _) = sympy_cse(ls)

    (vars_old, stmts) = map(list, zip(*ls))
    vars_new = []
    free_gl = expr.free_symbols
    free_gl.update(expr.atoms(IndexedBase))
    free_gl.update(vars_old)
    stmts.append(expr)

    for i in range(len(stmts) - 1):
        free = stmts[i].free_symbols
        free = free.difference(free_gl)
        free = list(free)
        var = create_variable(stmts[i])
        if len(free) > 0:
            var = IndexedBase(var)[free]
        vars_new.append(var)
    for i in range(len(stmts) - 1):
        stmts[i + 1] = stmts[i + 1].replace(vars_old[i], vars_new[i])
        stmts[-1] = stmts[-1].replace(stmts[i], vars_new[i])

    allocate = []
    for i in range(len(stmts) - 1):
        stmts[i] = Assign(vars_new[i], stmts[i])
        stmts[i] = pyccel_sum(stmts[i])
        if isinstance(vars_new[i], Indexed):
            ind = vars_new[i].indices
            tp = list(stmts[i + 1].atoms(Tuple))
            size = None
            size = [None] * len(ind)
            for (j, k) in enumerate(ind):
                for t in tp:
                    if k == t[0]:
                        size[j] = t[2] - t[1] + 1
                        break
            if not all(size):
                raise ValueError('Unable to find range of index')
            name = str(vars_new[i].base)
            var = Symbol(name)
            stmt = Assign(var, Function('empty')(size[0]))
            allocate.append(stmt)
            stmts[i] = For(ind[0],
                           Function('range')(size[0]), [stmts[i]],
                           strict=False)
    lhs = create_variable(expr)
    stmts[-1] = Assign(lhs, stmts[-1])
    imports = [Import('empty', 'numpy')]
    return imports + allocate + stmts
Example #2
0
    def _body_optional_variable(self,
                                tmp_variable,
                                variable,
                                collect_var,
                                check_type=False):
        """
        Responsible for collecting value and managing error and create the body
        of optional arguments in format
                if (pyobject == Py_None){
                    collect Null
                }else if(Type Check == False){
                    Print TypeError Wrong Type
                    return Null
                }else{
                    assign pyobject value to tmp variable
                    collect the adress of the tmp variable
                }
        Parameters:
        ----------
        tmp_variable : Variable
            The temporary variable  to hold result
        Variable : Variable
            The optional variable
        collect_var : variable
            the pyobject type variable  holder of value
        check_type : Boolean
            True if the type is needed

        Returns
        -------
        body : list
            A list of statements
        """
        body = [(PyccelEq(VariableAddress(collect_var),
                          VariableAddress(Py_None)),
                 [Assign(VariableAddress(variable), Nil())])]
        if check_type:  # Type check
            check = PyccelNot(
                PyccelOr(NumpyType_Check(variable, collect_var),
                         PythonType_Check(variable, collect_var)))
            error = PyErr_SetString(
                'PyExc_TypeError',
                '"{} must be {}"'.format(variable, variable.dtype))
            body += [(check, [error, Return([Nil()])])]
        body += [(LiteralTrue(), [
            self._create_collecting_value_body(variable, collect_var,
                                               tmp_variable),
            Assign(VariableAddress(variable), VariableAddress(tmp_variable))
        ])]
        body = [If(*body)]

        return body
Example #3
0
    def _visit_Assign(self, stmt):

        lhs = self._visit(stmt.targets)
        if len(lhs) == 1:
            lhs = lhs[0]
        else:
            lhs = PythonTuple(*lhs)

        rhs = self._visit(stmt.value)
        expr = Assign(lhs, rhs)

        # we set the fst to keep track of needed information for errors

        expr.set_fst(stmt)
        return expr
Example #4
0
    def doprint(self, expr, assign_to=None):
        """
        Print the expression as code.

        expr : Expression
            The expression to be printed.

        assign_to : Symbol, MatrixSymbol, or string (optional)
            If provided, the printed code will set the expression to a
            variable with name ``assign_to``.
        """

        if isinstance(assign_to, str):
            assign_to = Symbol(assign_to)
        elif not isinstance(assign_to, (Basic, type(None))):
            raise TypeError("{0} cannot assign to object of type {1}".format(
                    type(self).__name__, type(assign_to)))

        if assign_to:
            expr = Assign(assign_to, expr)
        else:
            expr = _sympify(expr)

        # Do the actual printing
        lines = self._print(expr).splitlines(True)

        # Format the output
        return ''.join(self._format_code(lines))
Example #5
0
def lambdify(expr, args):
    if isinstance(args, Lambda):
        new_expr = args.expr
        new_expr = Return(new_expr)
        new_expr.set_fst(expr)
        f_arguments = args.variables
        func = FunctionDef('lambda', f_arguments, [], [new_expr])
        return func

    code = compile(args.body[0], '', 'single')
    g = {}
    eval(code, g)
    f_name = str(args.name)
    code = g[f_name]
    new_args = args.arguments
    new_expr = code(*new_args)
    f_arguments = list(new_expr.free_symbols)
    stmts = cse(new_expr)
    if isinstance(stmts[-1], (Assign, GC)):
        var = stmts[-1].lhs
    else:
        var = create_variable(expr)
        stmts[-1] = Assign(var, stmts[-1])
    stmts += [Return([var])]
    set_fst(stmts, args.fst)
    func = FunctionDef(f_name, new_args, [], stmts, decorators=args.decorators)
    return func
Example #6
0
 def _print_PythonPrint(self, expr):
     self._additional_imports.add("stdio")
     args_format = []
     args = []
     end = '\n'
     sep = ' '
     for f in expr.expr:
         if isinstance(f, ValuedVariable):
             if f.name == 'sep': sep = str(f.value)
             elif f.name == 'end': end = str(f.value)
         elif isinstance(f, FunctionCall) and isinstance(
                 f.dtype, NativeTuple):
             tmp_list = self.extract_function_call_results(f)
             tmp_arg_format_list = []
             for a in tmp_list:
                 arg_format, arg = self.get_print_format_and_arg(a)
                 tmp_arg_format_list.append(arg_format)
                 args.append(arg)
             args_format.append('({})'.format(
                 ', '.join(tmp_arg_format_list)))
             assign = Assign(tmp_list, f)
             self._additional_code += self._print(assign) + '\n'
         else:
             arg_format, arg = self.get_print_format_and_arg(f)
             args_format.append(arg_format)
             args.append(arg)
     args_format = sep.join(args_format)
     args_format += end
     args_format = self._print(LiteralString(args_format))
     code = ', '.join([args_format, *args])
     return "printf({});".format(code)
Example #7
0
def as_static_function_call(func, mod_name, name=None):

    assert isinstance(func, FunctionDef)
    assert isinstance(mod_name, str)

    # create function alias by prepending 'mod_' to its name
    func_alias = func.clone('mod_' + str(func.name))

    # from module import func as func_alias
    imports = [Import(target=AsName(func.name, func_alias.name), source=mod_name)]

    # function arguments
    args = sanitize_arguments(func.arguments)
    # function body
    call    = FunctionCall(func_alias, args)
    results = func.results
    results = results[0] if len(results) == 1 else results
    stmt    = call if len(func.results) == 0 else Assign(results, call)
    body    = [stmt]

    # new function declaration
    new_func = FunctionDef(func.name, list(args), func.results, body,
                       arguments_inout = func.arguments_inout,
                       functions = func.functions,
                       interfaces = func.interfaces,
                       imports = imports,
                       doc_string = func.doc_string,
                       )

    # make it compatible with c
    static_func = as_static_function(new_func, name)

    return static_func
Example #8
0
    def _create_collecting_value_body(self, variable, collect_var, tmp_variable = None):
        """
        Create If block to differentiate between python and numpy data types when collecting value
        format :
            if (collect_var is numpy_scalar)
                collect_value from numpy type
            else
                collect value from python type
        Parameters:
        ----------
        variable: variable
            the variable needed to collect
        collect_var : variable
            the pyobject variable
        tmp_variable : variable
            temporary variable to hold value default None

        Returns
        -------
        body : If block
        """
        var = tmp_variable if tmp_variable else variable
        python_type_collect_func_call =  self.get_collect_function_call(variable, collect_var)

        numpy_type_collect_func_call = FunctionCall(PyArray_ScalarAsCtype, [collect_var, var])
        check_scalar_type = FunctionCall(PyArray_CheckScalar, [collect_var])

        body = If((check_scalar_type, [numpy_type_collect_func_call]),
                (LiteralTrue() , [Assign(var, python_type_collect_func_call)]))

        return body
Example #9
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
Example #10
0
    def _create_wrapper_check(self, check_var, parse_args, types_dict, used_names, func_name):
        check_func_body = []
        flags = (len(types_dict) - 1) * 4
        for arg in types_dict:
            var_name = ""
            body = []
            types = []
            arg_type_check_list = list(types_dict[arg])
            arg_type_check_list.sort(key= lambda x : x[0].precision)
            for elem in arg_type_check_list:
                var_name = elem[0].name
                value = elem[2] << flags
                body.append((elem[1], [AugAssign(check_var, '+' ,value)]))
                types.append(elem[0])
            flags -= 4
            error = ' or '.join(['{} bit {}'.format(v.precision * 8 , str_dtype(v.dtype)) if not isinstance(v.dtype, NativeBool)
                            else  str_dtype(v.dtype) for v in types])
            body.append((LiteralTrue(), [PyErr_SetString('PyExc_TypeError', '"{} must be {}"'.format(var_name, error)), Return([LiteralInteger(0)])]))
            check_func_body += [If(*body)]

        check_func_body = [Assign(check_var, LiteralInteger(0))] + check_func_body
        check_func_body.append(Return([check_var]))
        # Creating check function definition
        check_func_name = self.get_new_name(used_names.union(self._global_names), 'type_check')
        self._global_names.add(check_func_name)
        check_func_def = FunctionDef(name = check_func_name,
            arguments = parse_args,
            results = [check_var],
            body = check_func_body,
            local_vars = [])
        return check_func_def
Example #11
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
Example #12
0
 def get_default_assign(self, arg, func_arg):
     if arg.rank > 0 :
         return AliasAssign(arg, Nil())
     elif func_arg.is_optional:
         return AliasAssign(arg, Py_None)
     elif isinstance(arg.dtype, (NativeReal, NativeInteger, NativeBool)):
         return Assign(arg, func_arg.value)
     elif isinstance(arg.dtype, PyccelPyObject):
         return AliasAssign(arg, Py_None)
     else:
         raise NotImplementedError('Default values are not implemented for this datatype : {}'.format(func_arg.dtype))
Example #13
0
    def _visit_GeneratorExp(self, stmt):

        result = self._visit(stmt.elt)

        generators = self._visit(stmt.generators)
        parent = self._scope[-3]
        if not isinstance(parent, ast.Call):
            raise NotImplementedError(
                "GeneratorExp is not the argument of a function call")

        name = str(self._visit(parent.func))

        grandparent = self._scope[-4]
        if isinstance(grandparent, ast.Assign):
            if len(grandparent.targets) != 1:
                raise NotImplementedError(
                    "Cannot unpack function with generator expression argument"
                )
            lhs = self._visit(grandparent.targets[0])
        else:
            lhs = self.get_new_variable()

        body = result
        if name == 'sum':
            body = AugAssign(lhs, '+', body)
        else:
            body = Function(name)(lhs, body)
            body = Assign(lhs, body)

        body.set_fst(parent)
        indices = []
        generators = list(generators)
        while len(generators) > 0:
            indices.append(generators[-1].target)
            generators[-1].insert2body(body)
            body = generators.pop()
        indices = indices[::-1]
        body = [body]
        if name == 'sum':
            expr = FunctionalSum(body, result, lhs, indices, None)
        elif name == 'min':
            expr = FunctionalMin(body, result, lhs, indices, None)
        elif name == 'max':
            expr = FunctionalMax(body, result, lhs, indices, None)
        else:
            errors.report(PYCCEL_RESTRICTION_TODO,
                          symbol=name,
                          bounding_box=(stmt.lineno, stmt.col_offset),
                          severity='fatal')

        expr.set_fst(stmt)
        return expr
Example #14
0
    def __new__(cls, generator):

        # ... define the name for the shape and the statements to be able to
        #     compute it inside the python interface

        if isinstance(generator, VariableGenerator):
            var = generator.length
            stmts = [Assign(var, Len(generator.arguments))]

        elif isinstance(generator, ZipGenerator):
            var = generator.length
            stmts = [Assign(var, Len(generator.arguments[0]))]

        elif isinstance(generator, ProductGenerator):
            arguments = generator.arguments
            length = generator.length

            stmts = [Assign(l, Len(a)) for l, a in zip(length, arguments)]

            if generator.is_list:
                n = 1
                for i in length:
                    n *= i

            else:
                n = length

            var = Dummy()
            stmts += [Assign(var, n)]

        else:
            msg = 'not available for {}'.format(type(generator))
            raise NotImplementedError(msg)

        stmts = Tuple(*stmts)

        return Basic.__new__(cls, var, stmts)
Example #15
0
    def _visit_ListComp(self, stmt):

        result = self._visit(stmt.elt)
        generators = list(self._visit(stmt.generators))

        if not isinstance(self._scope[-2], ast.Assign):
            errors.report(PYCCEL_RESTRICTION_LIST_COMPREHENSION_ASSIGN,
                          symbol=stmt,
                          severity='error')
            lhs = self.get_new_variable()
        else:
            lhs = self._visit(self._scope[-2].targets)
            if len(lhs) == 1:
                lhs = lhs[0]
            else:
                raise NotImplementedError(
                    "A list comprehension cannot be unpacked")

        index = self.get_new_variable()

        args = [index]
        target = IndexedBase(lhs)[args]
        target = Assign(target, result)
        assign1 = Assign(index, LiteralInteger(0))
        assign1.set_fst(stmt)
        target.set_fst(stmt)
        generators[-1].insert2body(target)
        assign2 = Assign(index, PyccelAdd(index, LiteralInteger(1)))
        assign2.set_fst(stmt)
        generators[-1].insert2body(assign2)

        indices = [generators[-1].target]
        while len(generators) > 1:
            F = generators.pop()
            generators[-1].insert2body(F)
            indices.append(generators[-1].target)
        indices = indices[::-1]
        return FunctionalFor([assign1, generators[-1]], target.rhs, target.lhs,
                             indices, index)
Example #16
0
    def _print_FunctionCall(self, expr):
        func = expr.funcdef
        # Ensure the correct syntax is used for pointers
        args = []
        for a, f in zip(expr.arguments, func.arguments):
            if isinstance(a, Variable) and self.stored_in_c_pointer(f):
                args.append(VariableAddress(a))
            elif f.is_optional and not isinstance(a, Nil):
                tmp_var = self.create_tmp_var(f)
                assign = Assign(tmp_var, a)
                self._additional_code += self._print(assign) + '\n'
                args.append(VariableAddress(tmp_var))

            else:
                args.append(a)

        args += self._temporary_args
        self._temporary_args = []
        args = ', '.join(['{}'.format(self._print(a)) for a in args])
        if not func.results:
            return '{}({});'.format(func.name, args)
        return '{}({})'.format(func.name, args)
Example #17
0
    def __new__(cls, block, reduction, lhs, **kwargs):

        # ...
        settings = kwargs.copy()

        accelerator = settings.pop('accelerator')
        # ...

        assert (isinstance(reduction, Reduction))

        # ...
        if isinstance(lhs, (list, tuple, Tuple)):
            raise NotImplementedError()
        # ...

        # ...
        generator = block.generator
        decs = block.decs
        body = block.body
        private_vars = generator.private
        # ...

        # ...
        lhs_name = lhs.name

        assign_stmts = list(block.body.atoms(Assign))
        # ...

        # ...
        ls = [i for i in assign_stmts if _get_name(i.lhs) == lhs_name]
        if len(ls) > 1:
            raise NotImplementedError()

        assign_iterable = ls[0]
        rhs = assign_iterable.rhs
        new_stmt = AugAssign(lhs, reduction.op, rhs)

        body = block.body.subs(assign_iterable, new_stmt)

        decs = block.decs
        # ...

        # ... add initial values for reduced variables
        _reduction_init = lambda i: _get_default_value(i, op=reduction.op)
        reduction_stmts = [
            Assign(r, _reduction_init(r)) for r in reduction.arguments
        ]

        # update declarations
        decs = list(decs) + reduction_stmts
        decs = Tuple(*decs)
        # ...

        # ... define private variables of the current block
        # TODO add private vars from internal blocks
        private_vars = Tuple(*private_vars)
        # ...

        # ... add parallel loop
        if accelerator:
            if not (accelerator == 'omp'):
                raise NotImplementedError('Only OpenMP is available')

            # ...
            omp_fors = list(body.atoms(OMP_For))
            omp_for = [i for i in body if isinstance(i, OMP_For)]
            assert (len(omp_for) == 1)
            omp_for = omp_for[0]

            loop = omp_for.loop
            clauses = list(omp_for.clauses)
            nowait = omp_for.nowait

            # ...
            reduction_args = [reduction.op] + list(reduction.arguments)
            clauses += [OMP_Reduction(*reduction_args)]
            clauses = Tuple(*clauses)
            # ...

            new = OMP_For(loop, clauses, nowait)
            body = body.subs(omp_for, new)
        # ...

        decs = Tuple(*decs)
        body = Tuple(*body)

        return Basic.__new__(cls, generator, decs, body, private_vars)
Example #18
0
    def _visit_ProductMap(self, stmt):
        func = stmt.func
        args = stmt.target

        # ...
        if isinstance(func, BasicMap):
            raise TypeError("'map' object is not callable")
        # ...

        # ... get the codomain type
        type_codomain = self.main_type
        type_domain = self.d_domain_types[type_codomain]
        # ...

        # ... construct the generator
        target = [self._visit(i) for i in args]

        generator = ProductGenerator(*target)
        # ...

        # ... construct the results
        results = self._visit(type_codomain)

        # compute depth of the type list
        # TODO do we still need this?
        depth_out = len(list(type_codomain.atoms(TypeList)))
        # ...

        # ...
        index = generator.index
        iterator = generator.iterator
        # ...

        # ... list of all statements
        stmts = []
        # ...

        # ... use a multi index in the case of zip
        length = generator.length
        multi_index = generator.multi_index
        generator.set_as_list()

        # TODO check formula
        value = index[0]
        for ix, nx in zip(index[1:], length[::-1][:-1]):
            value = nx * value + ix

        stmts += [Assign(multi_index, value)]

        # update index to use multi index
        index = multi_index
        # ...

        # ... we set the generator after we treat map/tmap
        self.set_generator(results, generator)
        # ...

        # ... apply the function to arguments
        rhs = Call(func, iterator)
        # ...

        # ... create lhs
        lhs = generator.iterator
        # TODO check this
        if isinstance(lhs, Tuple) and len(lhs) == 1:
            lhs = lhs[0]
        # ...

        # ... create lhs for storing the result
        if isinstance(results, Variable):
            results = [results]

        else:
            msg = '{} not available'.format(type(results))
            raise NotImplementedError(msg)

        if not isinstance(index, Tuple):
            index = [index]

        else:
            index = list([i for i in index])

        lhs = []
        for r in results:
            m = r.rank - depth_out
            ind = index + [Slice(None, None)] * m
            if len(ind) == 1:
                ind = ind[0]

            lhs.append(IndexedBase(r.name)[ind])

        lhs = Tuple(*lhs)
        if len(lhs) == 1:
            lhs = lhs[0]
        # ...

        # ... create core statement
        stmts += [Assign(lhs, rhs)]
        # ...

        # TODO USE THIS
        #                expr = self.get_expr_from_type()

        # return the associated for loops
        return GeneratorBlock(generator,
                              stmts,
                              accelerator=self.accelerator,
                              nowait=self.nowait,
                              schedule=self.schedule,
                              chunk=self.chunk)
Example #19
0
    def __new__(cls, func, import_lambda):

        # ...
        m_results = func.m_results

        name = 'interface_{}'.format(func.name)
        args = [i for i in func.arguments if not i in m_results]
        s_results = func.results

        results = list(s_results) + list(m_results)
        # ...

        # ...
        imports = [import_lambda]
        stmts = []
        # ...

        # ... out argument
        if len(results) == 1:
            outs = [Symbol('out')]

        else:
            outs = [Symbol('out_{}'.format(i)) for i in range(0, len(results))]
        # ...

        # ...
        generators = func.generators
        d_shapes = {}
        for i in m_results:
            d_shapes[i] = compute_shape(i, generators)
        # ...

        # ... TODO build statements
        if_cond = Is(Symbol('out'), Nil())

        if_body = []

        # TODO add imports from numpy
        if_body += [Import('zeros', 'numpy')]
        if_body += [Import('float64', 'numpy')]

        for i, var in enumerate(results):
            if var in m_results:
                shaping = d_shapes[var]

                if_body += shaping.stmts
                if_body += [Assign(outs[i], Zeros(shaping.var, var.dtype))]

        # update statements
        stmts = [If((if_cond, if_body))]
        # ...

        # ... add call to the python or pyccelized function
        stmts += [FunctionCall(func, args + outs)]
        # ...

        # ... add return out
        if len(outs) == 1:
            stmts += [Return(outs[0])]

        else:
            stmts += [Return(outs)]
        # ...

        # ...
        body = imports + stmts
        # ...

        # update arguments with optional
        args += [Assign(Symbol('out'), Nil())]

        return FunctionDef(name, args, results, body)
Example #20
0
    def _print_FunctionDef(self, expr):
        # Save all used names
        used_names = set([a.name for a in expr.arguments] +
                         [r.name for r in expr.results] + [expr.name.name])

        # Find a name for the wrapper function
        wrapper_name = self._get_wrapper_name(used_names, expr)
        used_names.add(wrapper_name)
        # Collect local variables
        wrapper_vars = {a.name: a for a in expr.arguments}
        wrapper_vars.update({r.name: r for r in expr.results})
        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 arguments and results
        wrapper_args = [
            python_func_selfarg, python_func_args, python_func_kwargs
        ]
        wrapper_results = [self.get_new_PyObject("result", used_names)]

        if expr.is_private:
            wrapper_func = FunctionDef(
                name=wrapper_name,
                arguments=wrapper_args,
                results=wrapper_results,
                body=[
                    PyErr_SetString(
                        'PyExc_NotImplementedError',
                        '"Private functions are not accessible from python"'),
                    AliasAssign(wrapper_results[0], Nil()),
                    Return(wrapper_results)
                ])
            return CCodePrinter._print_FunctionDef(self, wrapper_func)
        if any(isinstance(arg, FunctionAddress) for arg in expr.arguments):
            wrapper_func = FunctionDef(
                name=wrapper_name,
                arguments=wrapper_args,
                results=wrapper_results,
                body=[
                    PyErr_SetString('PyExc_NotImplementedError',
                                    '"Cannot pass a function as an argument"'),
                    AliasAssign(wrapper_results[0], Nil()),
                    Return(wrapper_results)
                ])
            return CCodePrinter._print_FunctionDef(self, wrapper_func)

        # Collect argument names for PyArgParse
        arg_names = [a.name for a in expr.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 = []

        parse_args = []
        collect_vars = {}
        for arg in expr.arguments:
            collect_var, cast_func = self.get_PyArgParseType(used_names, arg)
            collect_vars[arg] = collect_var

            body, tmp_variable = self._body_management(used_names, arg,
                                                       collect_var, cast_func,
                                                       True)
            if tmp_variable:
                wrapper_vars[tmp_variable.name] = tmp_variable

            # If the variable cannot be collected from PyArgParse directly
            wrapper_vars[collect_var.name] = collect_var

            # Save cast to argument variable
            wrapper_body_translations.extend(body)

            parse_args.append(collect_var)

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

        # Parse arguments
        parse_node = PyArg_ParseTupleNode(python_func_args, python_func_kwargs,
                                          expr.arguments, parse_args,
                                          keyword_list)
        wrapper_body.append(If((PyccelNot(parse_node), [Return([Nil()])])))
        wrapper_body.extend(wrapper_body_translations)

        # Call function
        static_function, static_args, additional_body = self._get_static_function(
            used_names, expr, collect_vars)
        wrapper_body.extend(additional_body)
        for var in static_args:
            wrapper_vars[var.name] = var

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

        wrapper_body.append(func_call)

        # Loop over results to carry out necessary casts and collect Py_BuildValue type string
        res_args = []
        for a in expr.results:
            collect_var, cast_func = self.get_PyBuildValue(used_names, a)
            if cast_func is not None:
                wrapper_vars[collect_var.name] = collect_var
                wrapper_body.append(AliasAssign(collect_var, cast_func))

            res_args.append(
                VariableAddress(collect_var) if collect_var.
                is_pointer else collect_var)

        # Call PyBuildNode
        wrapper_body.append(
            AliasAssign(wrapper_results[0], PyBuildValueNode(res_args)))

        # Call free function for python type
        wrapper_body += [
            FunctionCall(Py_DECREF, [i]) for i in self._to_free_PyObject_list
        ]
        self._to_free_PyObject_list.clear()
        #Return
        wrapper_body.append(Return(wrapper_results))
        # Create FunctionDef and write using classic method
        wrapper_func = FunctionDef(name=wrapper_name,
                                   arguments=wrapper_args,
                                   results=wrapper_results,
                                   body=wrapper_body,
                                   local_vars=wrapper_vars.values())
        return CCodePrinter._print_FunctionDef(self, wrapper_func)
Example #21
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)
Example #22
0
def mpify(stmt, **options):
    """
    Converts some statements to MPI statments.

    stmt: stmt, list
        statement or a list of statements
    """
    if isinstance(stmt, (list, tuple, Tuple)):
        return [mpify(i, **options) for i in stmt]

    if isinstance(stmt, MPI):
        return stmt

    if isinstance(stmt, Tensor):
        options['label'] = stmt.name
        return stmt

    if isinstance(stmt, ForIterator):
        iterable = mpify(stmt.iterable, **options)
        target = stmt.target
        body = mpify(stmt.body, **options)
        return ForIterator(target, iterable, body, strict=False)

    if isinstance(stmt, For):
        iterable = mpify(stmt.iterable, **options)
        target = stmt.target
        body = mpify(stmt.body, **options)
        return For(target, iterable, body, strict=False)

    if isinstance(stmt, list):
        return [mpify(a, **options) for a in stmt]

    if isinstance(stmt, While):
        test = mpify(stmt.test, **options)
        body = mpify(stmt.body, **options)
        return While(test, body)

    if isinstance(stmt, If):
        args = []
        for block in stmt.args:
            test = block[0]
            stmts = block[1]
            t = mpify(test, **options)
            s = mpify(stmts, **options)
            args.append((t, s))
        return If(*args)

    if isinstance(stmt, FunctionDef):
        return stmt
        # TODO uncomment this
#        name        = mpify(stmt.name,        **options)
#        arguments   = mpify(stmt.arguments,   **options)
#        results     = mpify(stmt.results,     **options)
#        body        = mpify(stmt.body,        **options)
#        local_vars  = mpify(stmt.local_vars,  **options)
#        global_vars = mpify(stmt.global_vars, **options)
#
#        return FunctionDef(name, arguments, results, \
#                           body, local_vars, global_vars)

    if isinstance(stmt, ClassDef):
        name = mpify(stmt.name, **options)
        attributs = mpify(stmt.attributs, **options)
        methods = mpify(stmt.methods, **options)
        options = mpify(stmt.options, **options)

        return ClassDef(name, attributs, methods, options)

    if isinstance(stmt, Assign):
        if isinstance(stmt.rhs, Tensor):
            lhs = stmt.lhs
            options['label'] = lhs.name
            rhs = mpify(stmt.rhs, **options)

            return Assign(lhs, rhs, \
                          strict=stmt.strict, \
                          status=stmt.status, \
                          like=stmt.like)

    if isinstance(stmt, Del):
        variables = [mpify(a, **options) for a in stmt.variables]
        return Del(variables)

    if isinstance(stmt, Ones):
        if stmt.grid:
            lhs = stmt.lhs
            shape = stmt.shape
            grid = mpify(stmt.grid, **options)
            return Ones(lhs, grid=grid)

    if isinstance(stmt, Zeros):
        if stmt.grid:
            lhs = stmt.lhs
            shape = stmt.shape
            grid = mpify(stmt.grid, **options)
            return Zeros(lhs, grid=grid)

    if isinstance(stmt, Module):
        name = mpify(stmt.name, **options)
        variables = mpify(stmt.variables, **options)
        funcs = mpify(stmt.funcs, **options)
        classes = mpify(stmt.classes, **options)
        imports = mpify(stmt.imports, **options)
        imports += [Import('mpi')]
        # TODO add stdlib_parallel_mpi module

        return Module(name, variables, funcs, classes, imports=imports)

    if isinstance(stmt, Program):
        name = mpify(stmt.name, **options)
        variables = mpify(stmt.variables, **options)
        funcs = mpify(stmt.funcs, **options)
        classes = mpify(stmt.classes, **options)
        imports = mpify(stmt.imports, **options)
        body = mpify(stmt.body, **options)
        modules = mpify(stmt.modules, **options)
        imports += [Import('mpi')]
        # TODO improve this import, without writing 'mod_...'
        #      maybe we should create a new class for this import
        imports += [Import('mod_pyccel_stdlib_parallel_mpi')]

        return Program(name,
                       variables,
                       funcs,
                       classes,
                       body,
                       imports=imports,
                       modules=modules)

    return stmt
Example #23
0
def _build_block(generator, stmts):

    # ...
    decs = []
    body = []
    # ...

    # TODO USE stmts

    # ...
    iterable = generator.arguments
    index = generator.index
    iterator = generator.iterator
    length = generator.length

    if not isinstance(iterable, (list, tuple, Tuple)):
        iterable = [iterable]

    if not isinstance(index, (list, tuple, Tuple)):
        index = [index]

    if not isinstance(iterator, (list, tuple, Tuple)):
        iterator = [iterator]

    if not isinstance(length, (list, tuple, Tuple)):
        length = [length]
    # ...

#    print('------------- BEFORE')
#    print(' iterable = ', iterable)
#    print(' index    = ', index   )
#    print(' iterator = ', iterator)
#    print(' length   = ', length  )

# ... TODO  use shape_stmts
    for n, xs in zip(length, iterable):
        decs += [Assign(n, Len(xs))]
    # ...

    # ... append the same length for product
    if isinstance(generator, ProductGenerator):
        length = length * len(generator)
    # ...

#    print('------------- AFTER')
#    print(' iterable = ', iterable)
#    print(' index    = ', index   )
#    print(' iterator = ', iterator)
#    print(' length   = ', length  )

# ...
    body += list(stmts)
    # ...

    # ...
    if isinstance(generator, ZipGenerator):
        for i, n in zip(index, length):
            for x, xs in zip(iterator, iterable):

                if not isinstance(xs, (list, tuple, Tuple)):
                    body = [Assign(x, IndexedBase(xs.name)[i])] + body

                else:
                    for v in xs:
                        body = [Assign(x, IndexedBase(v.name)[i])] + body

            body = [For(i, Range(0, n), Tuple(*body), strict=False)]

    else:
        for i, n, x, xs in zip(index, length, iterator, iterable):

            if not isinstance(xs, (list, tuple, Tuple)):
                body = [Assign(x, IndexedBase(xs.name)[i])] + body

            else:
                for v in xs:
                    body = [Assign(x, IndexedBase(v.name)[i])] + body

            body = [For(i, Range(0, n), Tuple(*body), strict=False)]
    # ...

    return decs, body
Example #24
0
    def _visit_Map(self, stmt):
        func = stmt.func
        args = stmt.target

        # ...
        if isinstance(func, BasicMap):
            raise TypeError("'map' object is not callable")
        # ...

        # ... get the codomain type
        type_codomain = self.main_type
        type_domain = self.d_domain_types[type_codomain]
        # ...

        # ... construct the generator
        target = [self._visit(i) for i in args]

        if len(target) == 1:
            target = target[0]
            assert (isinstance(target, Variable))

            generator = VariableGenerator(target)

        else:
            generator = ZipGenerator(*target)
        # ...

        # ... construct the results
        results = self._visit(type_codomain)

        # compute depth of the type list
        # TODO do we still need this?
        depth_out = len(list(type_codomain.atoms(TypeList)))
        # ...

        # ...
        index = generator.index
        iterator = generator.iterator
        # ...

        # ... list of all statements
        stmts = []
        # ...

        # ... we set the generator after we treat map/tmap
        self.set_generator(results, generator)
        # ...

        # ... apply the function to arguments
        rhs = Call(func, iterator)
        # ...

        #        print('PAR ICI')
        #        print(func)
        #        print(func.name)
        ##        import sys; sys.exit(0)

        # ... create lhs
        lhs = generator.iterator
        # TODO check this
        if isinstance(lhs, Tuple) and len(lhs) == 1:
            lhs = lhs[0]
        # ...

        # ... create lhs for storing the result
        if isinstance(results, Variable):
            results = [results]

        else:
            msg = '{} not available'.format(type(results))
            raise NotImplementedError(msg)

        if not isinstance(index, Tuple):
            index = [index]

        else:
            index = list([i for i in index])

        lhs = []
        for r in results:
            m = r.rank - depth_out
            ind = index + [Slice(None, None)] * m
            if len(ind) == 1:
                ind = ind[0]

            lhs.append(IndexedBase(r.name)[ind])

        lhs = Tuple(*lhs)
        if len(lhs) == 1:
            lhs = lhs[0]
        # ...

        # ... create core statement
        stmts += [Assign(lhs, rhs)]
        # ...

        # TODO USE THIS
        #                expr = self.get_expr_from_type()

        # return the associated for loops
        return GeneratorBlock(generator,
                              stmts,
                              accelerator=self.accelerator,
                              nowait=self.nowait,
                              schedule=self.schedule,
                              chunk=self.chunk)
Example #25
0
    def _body_array(self, variable, collect_var, check_type=False):
        """
        Responsible for collecting value and managing error and create the body
        of arguments with rank greater than 0 in format
                if (rank check == False){
                    print TypeError Wrong rank
                    return Null
                }else if(Type Check == False){
                    Print TypeError Wrong type
                    return Null
                }else if (order check == False){ #check for order for rank > 1
                    Print NotImplementedError Wrong Order
                    return Null
                }
                collect the value from PyArrayObject

        Parameters:
        ----------
        Variable : Variable
            The optional variable
        collect_var : variable
            the pyobject type variable  holder of value
        check_type : Boolean
            True if the type is needed

        Returns
        -------
        body : list
            A list of statements
        """
        body = []
        #TODO create and extern rank and order check function
        #check optional :
        if variable.is_optional:
            check = PyccelNot(VariableAddress(collect_var))
            body += [(check, [Assign(VariableAddress(variable), Nil())])]

        #rank check :
        check = PyccelNe(FunctionCall(numpy_get_ndims, [collect_var]),
                         LiteralInteger(collect_var.rank))
        error = PyErr_SetString(
            'PyExc_TypeError',
            '"{} must have rank {}"'.format(collect_var,
                                            str(collect_var.rank)))
        body += [(check, [error, Return([Nil()])])]
        if check_type:  #Type check
            numpy_dtype = self.find_in_numpy_dtype_registry(variable)
            arg_dtype = self.find_in_dtype_registry(
                self._print(variable.dtype), variable.precision)
            check = PyccelNe(FunctionCall(numpy_get_type, [collect_var]),
                             numpy_dtype)
            info_dump = PythonPrint(
                [FunctionCall(numpy_get_type, [collect_var]), numpy_dtype])
            error = PyErr_SetString(
                'PyExc_TypeError',
                '"{} must be {}"'.format(variable, arg_dtype))
            body += [(check, [info_dump, error, Return([Nil()])])]

        if collect_var.rank > 1 and self._target_language == 'fortran':  #Order check
            if collect_var.order == 'F':
                check = FunctionCall(numpy_check_flag,
                                     [collect_var, numpy_flag_f_contig])
            else:
                check = FunctionCall(numpy_check_flag,
                                     [collect_var, numpy_flag_c_contig])
                error = PyErr_SetString(
                    'PyExc_NotImplementedError',
                    '"Argument does not have the expected ordering ({})"'.
                    format(collect_var.order))
                body += [(PyccelNot(check), [error, Return([Nil()])])]
        body += [(LiteralTrue(), [
            Assign(VariableAddress(variable),
                   self.get_collect_function_call(variable, collect_var))
        ])]
        body = [If(*body)]

        return body