コード例 #1
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
コード例 #2
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
コード例 #3
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)
コード例 #4
0
 def get_new_PyObject(self, name, used_names):
     return Variable(dtype=PyccelPyObject(),
                     name=self.get_new_name(used_names, name),
                     is_pointer=True)