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))
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)
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)