//Первый параметр - выходной. Он содержит выражения с необходимыми преобразованиями типов.
        public function_node select_function(expressions_list parameters, SymbolInfo functions, location loc, List<SyntaxTree.expression> syntax_nodes_parameters = null)
		{
			if (functions==null)
			{
				AddError(new NoFunctionWithThisName(loc));
			}

            function_node_list set_of_possible_functions = new function_node_list();

            bool is_alone_method_defined = (functions.Next == null);
            function_node first_function = functions.sym_info as function_node;
            bool _is_assigment = first_function.name == compiler_string_consts.assign_name;
            basic_function_node _tmp_bfn = functions.sym_info as basic_function_node;

            List<function_node> indefinits = new List<function_node>();

			while(functions!=null)
			{
#if (DEBUG)
				if (functions.sym_info.general_node_type!=general_node_type.function_node && functions.sym_info.general_node_type != general_node_type.property_node)
				{
					throw new CompilerInternalError("Function name is used to define another kind of object.");
				}
#endif
                function_node fn = null;
                if (functions.sym_info.general_node_type == general_node_type.property_node)
                {
                    fn = (functions.sym_info as property_node).get_function;
                }
                else
                fn=(function_node)functions.sym_info;

                if (fn.node_kind == node_kind.indefinite)
                {
                    indefinits.Add(fn);
                }
				else if (fn.node_kind==SemanticTree.node_kind.common)
				{
					common_function_node cfn=(common_function_node)fn;
					if ((parameters.Count>=cfn.parameters.Count-cfn.num_of_default_variables)&&
					    (parameters.Count<=cfn.parameters.Count) || parameters.Count == 0 && cfn.parameters.Count == 1 && cfn.parameters[0].is_params)
					{
						if (is_exist_eq_method_in_list(fn,set_of_possible_functions) != null)
						{
                            //!!!!!!!!!!!!!
                            //DS TODO
                            //Это нужно чтобы была возможность создавать операторы = := ..., т.к. всегда они добавляюся автоматом
                            //Надо сначало просматривать заголовки и добавлять такие операторы только если нужно.
                            if (set_of_possible_functions.Count > 0)
                                if (set_of_possible_functions[0] is basic_function_node)
                                {
                                    set_of_possible_functions.remove(set_of_possible_functions[0]);
                                    set_of_possible_functions.AddElement(fn);
                                }
                            //!!!!!!!!!!!!!
							
                            functions=functions.Next;
							continue;
						}
						set_of_possible_functions.AddElement(fn);
					}
				}
				else
				{
                    //TODO: Здесь нужно поправить, если создавать возможность вызова метода с параметрами по умолчанию из откомпилированной dll.
					if (parameters.Count==fn.parameters.Count)
					{
                        function_node func = null;
                        if ((func=is_exist_eq_method_in_list(fn,set_of_possible_functions)) != null)
						{
                            if (!eq_type_nodes(fn.return_value_type, func.return_value_type))
                            {
                                set_of_possible_functions[set_of_possible_functions.IndexOf(func)] = fn;
                                
                            }
                            functions = functions.Next;
                            continue;
						}
						set_of_possible_functions.AddElement(fn);
					}
				}
                if (parameters.Count > fn.parameters.Count)
                {
                    if (fn.parameters.Count > 0)
                    {
                        if ((fn.parameters[fn.parameters.Count - 1]).is_params)
                        {
                            //+DS ms0105
                            if (is_exist_eq_method_in_list(fn, set_of_possible_functions) != null)
                            {
                                functions = functions.Next;
                                continue;
                            }
                            //-DS
                            set_of_possible_functions.AddElement(fn);
                        }
                    }
                }
                else if ((parameters.Count == 0 && fn.parameters.Count == 1) && fn.parameters[0].is_params && !set_of_possible_functions.Contains(fn))
                    set_of_possible_functions.AddElement(fn);
                else if (fn.num_of_default_parameters != 0 && parameters.Count >= fn.parameters.Count - fn.num_of_default_parameters)
                {
                    if (!set_of_possible_functions.Contains(fn))
                        set_of_possible_functions.AddElement(fn);
                }
                else if (parameters.Count == 1 && fn is common_namespace_function_node && (fn as common_namespace_function_node).ConnectedToType != null && fn.parameters.Count == 2 && fn.parameters[1].is_params)
                    set_of_possible_functions.AddElement(fn);
                functions=functions.Next;
			}

			if (set_of_possible_functions.Count==0 && indefinits.Count == 0)
			{
                AddError(new NoFunctionWithSameParametresNum(loc, is_alone_method_defined, first_function));
			}

            //(ssyy) Инициализируем is_alone_defined
            FailedWhileTryingToCompileLambdaBodyWithGivenParametersException lastFailedWhileTryingToCompileLambdaBodyWithGivenParametersException = null;

            if (set_of_possible_functions.Count == 1 && indefinits.Count == 0)
            {
                is_alone_method_defined = true;
            }

            //(ssyy) Инстанцируем дженерики
            for (int i = set_of_possible_functions.Count - 1; i > -1; --i)
            {
                function_node func = set_of_possible_functions[i];
                if (func.is_generic_function)
                {
                    try
                    {

                        function_node inst = generic_convertions.DeduceFunction(func, parameters,
                                                                                is_alone_method_defined, loc, syntax_nodes_parameters);
                        if (inst == null)
                        {
                            set_of_possible_functions.remove_at(i);
                        }
                        else
                        {
                            set_of_possible_functions[i] = inst;
                        }
                    }
                    catch (FailedWhileTryingToCompileLambdaBodyWithGivenParametersException exc) //lroman Отлавливаем последнее исключение, которое возникло при попытке скомпилировать тело лямбды с заданными типами параметров
                    {
                        set_of_possible_functions.remove_at(i);
                        lastFailedWhileTryingToCompileLambdaBodyWithGivenParametersException = exc;
                    }
                }
            }

            if (lastFailedWhileTryingToCompileLambdaBodyWithGivenParametersException != null
                && set_of_possible_functions.Count == 0
                && indefinits.Count == 0)
            {
                throw lastFailedWhileTryingToCompileLambdaBodyWithGivenParametersException.ExceptionOnCompileBody;  // Если перебрали все, но ничто не подошло, то кидаем последнее исключение
            }

            if (set_of_possible_functions.Count == 0 && indefinits.Count == 0)
            {
                AddError(loc, "CAN_NOT_CALL_ANY_GENERIC_FUNCTION_{0}_WITH_THESE_PARAMETERS", first_function.name);
            }

            possible_type_convertions_list_list tcll = new possible_type_convertions_list_list();

			for(int i=0;i<set_of_possible_functions.Count;i++)
			{
				possible_type_convertions_list tc=get_conversions(parameters,set_of_possible_functions[i].parameters,
					is_alone_method_defined,loc);
				tcll.AddElement(tc);
			}

			int j=0;
			while(j<set_of_possible_functions.Count)
			{
				if (tcll[j]==null && set_of_possible_functions[j].node_kind != node_kind.indefinite)
				{
					tcll.remove_at(j);
					set_of_possible_functions.remove_at(j);
				}
				else
				{
					j++;
				}
			}

			if (set_of_possible_functions.Count==0 && indefinits.Count == 0)
			{
                if (_is_assigment && parameters.Count == 2)
                    AddError(new CanNotConvertTypes(parameters[1], parameters[1].type, parameters[0].type, parameters[1].location));
                if (_tmp_bfn != null && parameters.Count == 2)
                    AddError(new OperatorCanNotBeAppliedToThisTypes(_tmp_bfn.name, parameters[0], parameters[1],loc));
				AddError(new NoFunctionWithSameArguments(loc,is_alone_method_defined));
			}

			bool remove=true;
			
			while(remove)
			{
				if (set_of_possible_functions.Count==1)
				{
					check_single_possible_convertion(loc,tcll[0]);
					convert_function_call_expressions(set_of_possible_functions[0],parameters,tcll[0]);
					return set_of_possible_functions[0];
				}
				remove=false;

                var i = 0;
                while (i < set_of_possible_functions.Count-1)
                {
                    j = i+1;
                    while (j < set_of_possible_functions.Count)
                    {
                        method_compare mc = compare_methods(set_of_possible_functions[i],
                            set_of_possible_functions[j], tcll[i], tcll[j]);
                        if (mc == method_compare.greater_method)
                        {
                            tcll.remove_at(j);
                            set_of_possible_functions.remove_at(j);
                            remove = true;
                        }
                        else if (mc == method_compare.less_method)
                        {
                            tcll[i] = tcll[j];
                            set_of_possible_functions[i] = set_of_possible_functions[j];
                            tcll.remove_at(j);
                            set_of_possible_functions.remove_at(j);
                            remove = true;
                        }
                        else
                        {
                            j++;
                        }
                    }
                    i++;
                }

            }

            // TODO: Исправить этот алгоритм, сделав каждый с каждым - вроде исправил - см. выше
            /*j = 1;
				while(j<set_of_possible_functions.Count)
				{
                    method_compare mc = compare_methods(set_of_possible_functions[0],
                        set_of_possible_functions[j], tcll[0], tcll[j]);
					if (mc==method_compare.greater_method)
					{
						tcll.remove_at(j);
						set_of_possible_functions.remove_at(j);
						remove=true;
					}
					else if (mc==method_compare.less_method)
					{
						tcll[0]=tcll[j];
						set_of_possible_functions[0]=set_of_possible_functions[j];
						tcll.remove_at(j);
						set_of_possible_functions.remove_at(j);
						remove=true;
					}
					else
					{
						j++;
					}
				}
			}*/

            /*remove=true;
            while (remove)
            {
                if (set_of_possible_functions.Count == 1)
                {
                    check_single_possible_convertion(loc, tcll[0]);
                    convert_function_call_expressions(set_of_possible_functions[0], parameters, tcll[0]);
                    return set_of_possible_functions[0];
                }
                remove = false;
                j = 1;
                while (j < set_of_possible_functions.Count)
                {

                }
            }*/
			//Тут некоторое дублирование кода, но сюда программа не должна никогда зайти.
			//Должен быть выполнен if выше.
			//Но пусть пока повисит. Потом нужно разобраться и убрать.
			/*if (set_of_possible_functions.Count==1)
			{
				check_single_possible_conversion(func_call,tcll[0]);
				func_call.function=set_of_possible_functions[0];
				convert_function_call_expressions(func_call,tcll[0]);
				func_call.type=func_call.function.return_value_type;
				return func_call;
			}*/

            //Тупая заглушка для примитивных типов. иначе не работает +=, у нас лишком много неявных приведений
            //в дальнейшем может вызвать странное поведение, это надо проверить
            if (set_of_possible_functions.Count == 2 && indefinits.Count == 0)
                if (set_of_possible_functions[0] is basic_function_node && set_of_possible_functions[1] is basic_function_node)
                    return set_of_possible_functions[0];

            if (indefinits.Count > 0)
            {
                if (indefinits.Count == 1 && set_of_possible_functions.Count == 0)
                {
                    return indefinits[0];
                }
                indefinits.AddRange(set_of_possible_functions);
                return new indefinite_functions_set(indefinits);
            }

            bool exist_indefinite_parameter = false;
            foreach (expression_node par in parameters)
            {
                if (par.type.depended_from_indefinite)
                {
                    exist_indefinite_parameter = true;
                    break;
                }
            }
            if (exist_indefinite_parameter)
            {
                indefinits.AddRange(set_of_possible_functions);
                return new indefinite_functions_set(indefinits);
            }
			
            AddError(new SeveralFunctionsCanBeCalled(loc,set_of_possible_functions));
            return null;
		}