private base_function_call_list create_possible_delegates_list(expression_node obj, SymbolInfo si, location loc, bool is_static)
        {
            if (si == null)
            {
                return new base_function_call_list();
            }
            function_node_list fnl = new function_node_list();
            while (si != null)
            {
                function_node fn = si.sym_info as function_node;
                if (si.sym_info is compiled_property_node)
                {
                    fn = (si.sym_info as compiled_property_node).get_function; 
                }
                else if (si.sym_info is common_property_node)
                {
                    fn = (si.sym_info as common_property_node).get_function;
                }
                if (convertion_data_and_alghoritms.find_eq_method_in_list(fn, fnl) == null)
                {
                    if (!(obj != null && fn.polymorphic_state == SemanticTree.polymorphic_state.ps_static && !fn.is_extension_method))
                    {
                        if (fn.is_extension_method)
                        {
                            if (obj != null && (fn.parameters[0].type == obj.type || type_table.compare_types(fn.parameters[0].type, obj.type) == type_compare.greater_type))
                                fnl.AddElementFirst(fn);
                            else
                                fnl.AddElement(fn);
                        }
                        else
                            fnl.AddElement(fn);
                    }
                }
                else
                {

                }
                si = si.Next;
            }
            return convert_functions_to_calls(obj, fnl, loc, is_static);
        }
 private base_function_call_list create_possible_delegates_list(expression_node obj, function_node func, location loc, bool is_static)
 {
     function_node_list fnl = new function_node_list();
     fnl.AddElement(func);
     return convert_functions_to_calls(obj, fnl, loc, is_static);
 }
        public expression_node find_operator(string name, expression_node left, expression_node right, location loc)
        {
            //if (!CheckExpressionType(left))
            //    return SystemLibrary.SystemLibrary.get_empty_method_call(left.location);
            //if (!CheckExpressionType(right))
            //    return SystemLibrary.SystemLibrary.get_empty_method_call(right.location);
            //string name=name_reflector.get_name(ot);
#if (DEBUG)
            if (name == null)
            {
                throw new CompilerInternalError("Invalid operator name");
            }
#endif

            if (right.semantic_node_type == semantic_node_type.null_const_node)
            {
            	if ( !type_table.is_with_nil_allowed(left.type) && !left.type.IsPointer)
                    AddError(right.location, "NIL_WITH_VALUE_TYPES_NOT_ALLOWED");
            	right = null_const_node.get_const_node_with_type(left.type, (null_const_node)right);
            }

            type_node left_type = left.type;
            type_node right_type = right.type;
			
            /*if (left.type == SystemLibrary.SystemLibrary.uint64_type || right.type == SystemLibrary.SystemLibrary.uint64_type)
            	if (name == compiler_string_consts.plus_name || name == compiler_string_consts.minus_name || name == compiler_string_consts.mul_name || name == compiler_string_consts.idiv_name || name == compiler_string_consts.mod_name)
            	{
                    expression_node expr = right.type != SystemLibrary.SystemLibrary.uint64_type ? right : left;
                    if (!(expr is constant_node))
                    {
                        type_node tn = expr.type;
                        if (tn == SystemLibrary.SystemLibrary.short_type || tn == SystemLibrary.SystemLibrary.sbyte_type || tn == SystemLibrary.SystemLibrary.integer_type || tn == SystemLibrary.SystemLibrary.int64_type)
                            throw new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc);
                    }
            	}
            */

            if (left_type.semantic_node_type == semantic_node_type.delegated_method)
            {
                delegated_methods dm1 = (delegated_methods)left_type;
                if (dm1.empty_param_method != null)
                {
                    if (dm1.empty_param_method.simple_function_node.return_value_type != null)
                    {
                        left_type = dm1.empty_param_method.simple_function_node.return_value_type;
                    }
                }
            }

            if (right_type.semantic_node_type == semantic_node_type.delegated_method && name != compiler_string_consts.plusassign_name && name != compiler_string_consts.minusassign_name)
            {
                delegated_methods dm2 = (delegated_methods)right_type;
                if (dm2.empty_param_method != null)
                {
                    if (dm2.empty_param_method.simple_function_node.return_value_type != null)
                    {
                        right_type = dm2.empty_param_method.simple_function_node.return_value_type;
                    }
                }
            }
			
            //zdes ne vse verno. += odnostoronnjaa operacija, a += b pochemu esli tipy ne ravny, += ishetsja v tipe b???
            //TODO: Посмотреть.
            //TODO: Не find а find_in_type.
            //SymbolInfo si=left_type.find(name, context.CurrentScope);
            SymbolInfo si = left_type.find_in_type(name, left_type.Scope);
            SymbolInfo added_symbols = null;
            SymbolInfo si2 = null;
            if (left_type != right_type && !one_way_operation(name))
            {
                //SymbolInfo si2 = right_type.find(name, context.CurrentScope);
                if (si != null)
                    si = si.copy();
                si2 = right_type.find_in_type(name, right_type.Scope);
                if ((si != null) && (si2 != null))
                {
                    //Важная проверка. Возможно один и тот же оператор с одними и теми же типами определен в двух разных классах.
                    //Возможно она занимает много времени, но, наверное, от нее нельзя отказаться.
                    function_node_list funcs = new function_node_list();
                    SymbolInfo sic = si;
                    SymbolInfo sic_last = null;
                    while (sic != null)
                    {
                        if (sic.sym_info.general_node_type != general_node_type.function_node)
                        {
                            BasePCUReader.RestoreSymbols(sic, name);
                        }
#if (DEBUG)
                        if (sic.sym_info.general_node_type != general_node_type.function_node)
                        {
                            throw new CompilerInternalError("Expected operator.");
                        }
#endif
                        
                        function_node fn = ((function_node)(sic.sym_info));
                        if (convertion_data_and_alghoritms.is_exist_eq_method_in_list(fn, funcs) != null)
                        {
                            break;
                        }
                        funcs.AddElement(fn);
                        sic_last = sic;
                        sic = sic.Next;
                    }
                    sic = si2;
                    //TODO: Разобраться с зацикливанием.
                    function_node_list fnl = new function_node_list();
                    while (sic != null)
                    {
                        if (sic.sym_info.general_node_type != general_node_type.function_node)
                        {
                            BasePCUReader.RestoreSymbols(sic, name);
                        }
#if (DEBUG)
                        if (sic.sym_info.general_node_type != general_node_type.function_node)
                        {
                            throw new CompilerInternalError("Expected operator.");
                        }
#endif
                        fnl.AddElement(((function_node)(sic.sym_info)));
                        sic = sic.Next;
                    }
                    added_symbols = sic_last;
                    foreach (function_node fnode in fnl)
                    {
                        function_node eq_func = convertion_data_and_alghoritms.find_eq_method_in_list(fnode, funcs);
                        if (eq_func != null)
                        {
                            //TODO: Проверить правильно ли это будет работать.
                            if (eq_func != fnode)
                            {
                                basic_function_node bbfn1 = fnode as basic_function_node;
                                basic_function_node bbfn2 = eq_func as basic_function_node;
                                if ((bbfn1 != null) && (bbfn2 != null))
                                {
                                    if (bbfn1.basic_function_type != bbfn2.basic_function_type)
                                    {
                                        AddError(new TwoOperatorsCanBeCalled(eq_func, fnode, left, right));
                                    }
                                    //sic = sic.Next;
                                    continue;
                                }
                                else
                                {
                                	if (left.type.type_special_kind == SemanticTree.type_special_kind.set_type && right.type.type_special_kind == SemanticTree.type_special_kind.set_type
                                	   || left.type.type_special_kind == SemanticTree.type_special_kind.set_type &&  right.type.type_special_kind == SemanticTree.type_special_kind.base_set_type
                                	  || left.type.type_special_kind == SemanticTree.type_special_kind.base_set_type &&  right.type.type_special_kind == SemanticTree.type_special_kind.set_type
                                	 || left.type.type_special_kind == SemanticTree.type_special_kind.base_set_type &&  right.type.type_special_kind == SemanticTree.type_special_kind.base_set_type
                                	|| left.type == SystemLibrary.SystemLibrary.string_type && right.type.type_special_kind == SemanticTree.type_special_kind.short_string
                               		 || right.type == SystemLibrary.SystemLibrary.string_type && left.type.type_special_kind == SemanticTree.type_special_kind.short_string
                               		|| left.type.type_special_kind == SemanticTree.type_special_kind.short_string && right.type.type_special_kind == SemanticTree.type_special_kind.short_string)
                                	{
                                		//if (left.type.find_in_type(name) !=null)
                                	}
                                	else
                                	AddError(new TwoOperatorsCanBeCalled(eq_func, fnode, left, right));
                                }
                            }
                        }
                        sic_last.Next = new SymbolInfo(fnode);
                        sic_last = sic_last.Next;
                    }
                    /*while (sic!=null)
                    {
#if (DEBUG)
                        if (sic.sym_info.general_node_type!=general_node_type.function_node)
                        {
                            throw new CompilerInternalError("Expected operator.");
                        }
#endif
                        function_node fn=((function_node)(sic.sym_info));
                        function_node eq_func=convertion_data_and_alghoritms.find_eq_method_in_list(fn,funcs);
                        if (eq_func!=null)
                        {
                            basic_function_node bbfn1=fn as basic_function_node;
                            basic_function_node bbfn2=eq_func as basic_function_node;
                            if ((bbfn1!=null)&&(bbfn2!=null))
                            {
                                if (bbfn1.basic_function_type!=bbfn2.basic_function_type)
                                {
                                    throw new TwoOperatorsCanBeCalled(eq_func,fn,left,right);
                                }
                                sic=sic.Next;
                                continue;
                            }
                            else
                            {
                                throw new TwoOperatorsCanBeCalled(eq_func,fn,left,right);
                            }
                        }
                        //TODO: Разобраться с зацикливанием.
                        sic_last.Next = sic;
                        sic_last = sic;
                        sic=sic.Next;
                    }*/
                    //sic_last.Next=si2;
                }
                else
                {
                    if ((si == null) && (si2 != null))
                    {
                        si = si2;
                    }
                }
            }
            //if (si == null)
            {
                if (/*si2 == null && */left_type.semantic_node_type == semantic_node_type.delegated_method && right_type.semantic_node_type == semantic_node_type.delegated_method)
                {
                    SymbolInfo saved_si = si;
                    SymbolInfo saved_si2 = si2;
                    base_function_call bfc = ((left as typed_expression).type as delegated_methods).proper_methods[0];
                    left = convertion_data_and_alghoritms.explicit_convert_type(left, CreateDelegate(bfc.simple_function_node));
                    si = left.type.find_in_type(name);
                    bfc = ((right as typed_expression).type as delegated_methods).proper_methods[0];
                    right = convertion_data_and_alghoritms.explicit_convert_type(right, CreateDelegate(bfc.simple_function_node));
                    si2 = right.type.find_in_type(name);
                    if (saved_si != null)
                        si.Next = saved_si;
                    else
                        saved_si = si;
                    if (saved_si2 != null)
                        si2.Next = saved_si2;
                    else
                        saved_si2 = si2;
                    if (saved_si == null)
                        AddError(new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc));
                }
                else if (si == null)
                    AddError(new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc));
            }

            expressions_list pars = null;
            function_node fnsel = null;
            SymbolInfo tmp_si = si;
            while (tmp_si != null)
            {
                if (tmp_si.sym_info is wrapped_definition_node)
                    BasePCUReader.RestoreSymbols(tmp_si, name);
                tmp_si = tmp_si.Next;
            }
            pars = new expressions_list();
            pars.AddElement(left);
            pars.AddElement(right);

            fnsel = convertion_data_and_alghoritms.select_function(pars, si, loc);
            //function_node fnsel=convertion_data_and_alghoritms.select_function(pars,si,loc);
            CheckSpecialFunctionCall(si, pars,loc);
            //TODO: А это зачем? Можно передать в create_simple_function_call pars.
            left = pars[0];
            right = pars[1];
            if (fnsel == null)
            {
                AddError(new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc));
            }
            if (added_symbols != null)
                added_symbols.Next = null;
            
            if (SystemUnitAssigned && in_check_range_region() && name == compiler_string_consts.assign_name && is_range_checkable(left.type) && is_range_checkable(right.type))
            {
            	ordinal_type_interface oti = left.type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
            	if (left.type != SystemLibrary.SystemLibrary.char_type && left.type != SystemLibrary.SystemLibrary.uint64_type && !(oti.lower_value is ulong_const_node))
            	if(!(oti.lower_value is enum_const_node) && !(oti.lower_value is char_const_node))
            		right = convertion_data_and_alghoritms.convert_type(convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CheckRangeFunction.sym_info as common_namespace_function_node, null, convertion_data_and_alghoritms.convert_type(right,SystemLibrary.SystemLibrary.int64_type), convertion_data_and_alghoritms.convert_type(oti.lower_value,SystemLibrary.SystemLibrary.int64_type),convertion_data_and_alghoritms.convert_type(oti.upper_value,SystemLibrary.SystemLibrary.int64_type)),right.type);
            	else if (oti.lower_value is enum_const_node)
            	{
            		right = convertion_data_and_alghoritms.explicit_convert_type(convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CheckRangeFunction.sym_info as common_namespace_function_node, null, convertion_data_and_alghoritms.explicit_convert_type(right,SystemLibrary.SystemLibrary.int64_type),
            		                                                                                                               convertion_data_and_alghoritms.explicit_convert_type(oti.lower_value,SystemLibrary.SystemLibrary.int64_type),convertion_data_and_alghoritms.explicit_convert_type(oti.upper_value,SystemLibrary.SystemLibrary.int64_type)),right.type);
            	}
            	else if (oti.lower_value is char_const_node)
            	right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CheckCharRangeFunction.sym_info as common_namespace_function_node, null, right, oti.lower_value,oti.upper_value);	
            }
            expression_node exp_node = convertion_data_and_alghoritms.create_simple_function_call(fnsel, loc, left, right);
            return exp_node;
        }
        private base_function_call_list convert_functions_to_calls(expression_node obj, function_node_list fnl, location loc, bool is_static)
        {
            base_function_call_list ret = new base_function_call_list();
            foreach (function_node fnode in fnl)
            {
                base_function_call bfc = null;
                switch (fnode.semantic_node_type)
                {
                    case semantic_node_type.common_namespace_function_node:
                        {
                            common_namespace_function_node cmfn = fnode as common_namespace_function_node;
                            common_namespace_function_call cnfc = new common_namespace_function_call(cmfn, loc);
                            if (cmfn.ConnectedToType != null)
                                cnfc.parameters.AddElement(obj);
                            if (cmfn.is_generic_function && !cmfn.is_generic_function_instance && cmfn.ConnectedToType != null && cmfn.parameters.Count == 1)
                            {
                                expressions_list parameters = new expressions_list();
                                parameters.AddElement(obj);
                                function_node inst = null;
                                try
                                {
                                    inst = generic_convertions.DeduceFunction(cmfn, parameters, true, loc);
                                }
                                catch
                                {
                                    continue;
                                }
                                cnfc = new common_namespace_function_call((common_namespace_function_node)inst, loc);
                                if (cmfn.ConnectedToType != null)
                                    cnfc.parameters.AddElement(obj);
                            }
                            /*if (cmfn.parameters.Count >= 1 && cmfn.parameters[cmfn.parameters.Count - 1].is_params)
                            {
                                convertion_data_and_alghoritms.select_function(cnfc.parameters, new SymbolInfo(cmfn), loc);
                                
                            }*/
                            bfc = cnfc;
                            break;
                        }
                    case semantic_node_type.basic_function_node:
                        {
                            //Может здесь стоит и выругаться, но я не буду пока этого делать.
                            break;
                        }
                    case semantic_node_type.common_in_function_function_node:
                        {
                            common_in_function_function_node ciffn = fnode as common_in_function_function_node;
                            int depth = convertion_data_and_alghoritms.symbol_table.GetRelativeScopeDepth(ciffn.scope,
                                context.top_function.scope);
                            common_in_function_function_call ciffc = new common_in_function_function_call(ciffn, depth, loc);
                            bfc = ciffc;
                            break;
                        }
                    case semantic_node_type.common_method_node:
                        {
                            common_method_node cmn = fnode as common_method_node;
                            //Если cmn конструктор - то плохо, но его не должно сюда попасть.
                            if (cmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
                            {
                                if (!is_static)
                                {
                                    if (obj == null)
                                        obj = GetCurrentObjectReference(cmn.cont_type.Scope, cmn, loc);//new this_node(context.converted_type, loc);
                                    common_method_call cmc = new common_method_call(cmn, obj, loc);
                                    cmc.virtual_call = !inherited_ident_processing;
                                    bfc = cmc;
                                }
                                //ssyy!!! Мне сложно понять предназначение данного кода, но, по-видимому,
                                //следует его переписать так.
                                else if (cmn.is_constructor)
                                {
                                    if (cmn.parameters.Count == 0)
                                    {
                                    	if (cmn.cont_type.IsAbstract)
                                            AddError(loc, "ABSTRACT_CONSTRUCTOR_{0}_CALL", cmn.cont_type.name);
                                    	ret.clear();
                                        ret.AddElement(new common_constructor_call(cmn, loc));
                                        return ret;
                                    }
                                }
                            }
                            else
                            {
                                if (is_static)
                                {
                                    common_static_method_call csmc = new common_static_method_call(cmn, loc);
                                    bfc = csmc;
                                }
                            }
                            break;
                        }
                    case semantic_node_type.compiled_function_node:
                        {
                            compiled_function_node cfn = fnode as compiled_function_node;
                            if (cfn.cont_type.Scope == null && cfn is compiled_function_node)
                        	(cfn.cont_type as compiled_type_node).init_scope();
                            
                            if (cfn.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
                            {
                                //ispravleno ibond
                            	//if (is_static)
                                {

                                    if (cfn.is_generic_function && !cfn.is_generic_function_instance && cfn.ConnectedToType != null && cfn.parameters.Count == 1)
                                    {
                                        expressions_list parameters = new expressions_list();
                                        parameters.AddElement(obj);
                                        function_node inst = null;
                                        try
                                        {
                                            inst = generic_convertions.DeduceFunction(cfn, parameters, true, loc);
                                        }
                                        catch
                                        {
                                            continue;
                                        }
                                        if (inst is common_namespace_function_node)
                                            bfc = new common_namespace_function_call((common_namespace_function_node)inst, loc);
                                        else if (inst is compiled_function_node)
                                            bfc = new compiled_static_method_call((compiled_function_node)inst, loc);
                                        else
                                            bfc = new compiled_static_method_call(cfn, loc);
                                    }
                                    else
                                    {
                                        compiled_static_method_call csmc = new compiled_static_method_call(cfn, loc);
                                        bfc = csmc;
                                        
                                    }
                                    if (cfn.ConnectedToType != null)
                                        bfc.parameters.AddElement(obj);
                                }
                            }
                            else
                            {
                                if (!is_static)
                                {
                                    if (obj == null)
                                        obj = GetCurrentObjectReference(cfn.cont_type.Scope, cfn, loc);//new this_node(context.converted_type, loc);
                                    compiled_function_call cfc = new compiled_function_call(cfn, obj, loc);
                                    cfc.virtual_call = !inherited_ident_processing;
                                    bfc = cfc;
                                }
                            }
                            break;
                        }
                    case semantic_node_type.compiled_constructor_node:
                        {
                            //Этот код мы вроде не должны вызывать, но если он все-же вызовется.
                            compiled_constructor_node ccn = fnode as compiled_constructor_node;
                            compiled_constructor_call ccc = new compiled_constructor_call(ccn, loc);
                            bfc = ccc;
                            break;
                        }
                    default:
                        {
                            throw new CompilerInternalError("Undefined method type.");
                        }
                }
                if (bfc != null)
                {
                    ret.AddElement(bfc);
                }
            }
            return ret;
        }
 private function_node is_exist_eq_return_value_method(function_node fn, function_node_list funcs)
 {
     fn = find_eq_return_value_method_in_list(fn, funcs);
     return fn;
     /*if (fn == null)
     {
         return false;
     }
     return true;*/
 }
		//Первый параметр - выходной. Он содержит выражения с необходимыми преобразованиями типов.
        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;
		}
		public function_node is_exist_eq_method_in_list(function_node fn,function_node_list funcs)
		{
			return find_eq_method_in_list(fn,funcs);
			/*if (fn==null)
			{
				return false;
			}
			return true;*/
		}
		public function_node find_eq_method_in_list(function_node fn,function_node_list funcs)
		{
			foreach(function_node f in funcs)
			{
				//Проверка добавлена 14.07.2006 в 14.28. Нужно с ней прогнать тесты, хотя вроде вреда от нее не должно быть.
				if (f==fn)
				{
					return f;
				}
				if (function_eq_params(fn,f))
				{
                    if (fn.original_function == f.original_function)
                    {
                        return f;
                    }
				}
			}
			return null;
		}
Esempio n. 9
0
 public SeveralFunctionsCanBeCalled(ILocation loc, function_node_list set_of_possible_functions)
 {
     _loc = loc;
     _possible_functions = set_of_possible_functions;
 }