private method_compare compare_methods(function_node left_func, function_node right_func,
            possible_type_convertions_list left,possible_type_convertions_list right)
		{
            function_compare fc = function_node.compare_functions(left_func, right_func);
            if (fc == function_compare.less)
            {
                return method_compare.less_method;
            }
            if (fc == function_compare.greater)
            {
                return method_compare.greater_method;
            }

			bool left_greater=false;
			bool right_greater=false;

			for(int i=0;i<left.Count;i++)
			{
				type_conversion_compare tcc=compare_type_conversions(left[i],right[i]);
				if (tcc==type_conversion_compare.less_type_conversion)
				{
					right_greater=true;
				}
				if (tcc==type_conversion_compare.greater_type_conversion)
				{
					left_greater=true;
				}
				if ((left_greater)&&(right_greater))
				{
					return method_compare.not_comparable_methods;
				}
			}
			if ((left_greater)&&(!right_greater))
			{
				return method_compare.greater_method;
			}
			if ((!left_greater)&&(right_greater))
			{
				return method_compare.less_method;
			}
            if ((left_greater) && (right_greater))
            {
                return method_compare.not_comparable_methods;
            }

            if ((left.snl != null) && (right.snl == null))
            {
                return method_compare.less_method;
            }
            if ((left.snl == null) && (right.snl != null))
            {
                return method_compare.greater_method;
            }
            if (!left_func.is_generic_function_instance && right_func.is_generic_function_instance)
            {
                return method_compare.greater_method;
            }
            if (left_func.is_generic_function_instance && !right_func.is_generic_function_instance)
            {
                return method_compare.less_method;
            }
            if (left_func.is_generic_function_instance && right_func.is_generic_function_instance)
            {
            	if (left_func.generic_parameters_count > right_func.generic_parameters_count)
            		return method_compare.greater_method;
            	else if (left_func.generic_parameters_count < right_func.generic_parameters_count)
            		return method_compare.less_method;
                else // SSM 8/8/15 Два метода одинаковы по всем параметрам, но у одного - больше instance_params, т.е. он менее специализирован
                if (left_func.parameters.Count == right_func.parameters.Count)
                {
                    bool eq = true;
                    for (var i=0; i<left_func.parameters.Count; i++)
                        if (left_func.parameters[i].type != right_func.parameters[i].type)
                        {
                            eq = false;
                            break;
                        }
                    if (eq)
                    {
                        var lc = left_func.get_generic_params_list().Count;
                        var rc = right_func.get_generic_params_list().Count;
                        if (lc < rc)
                            return method_compare.greater_method;
                        if (lc > rc)
                            return method_compare.less_method;
                        // Тут совпадать они не могут, но если совпадают - пусть уж будут несравнимыми
                    }
                }
            }
            return method_compare.not_comparable_methods;
		}
 private void WriteGenericMethodReference(function_node meth)
 {
     common_method_node cnode = meth.original_function as common_method_node;
     if (cnode != null)
     {
         bw.Write((byte)PCUConsts.common_method_generic);
         WriteMethodReference(cnode);
     }
     else
     {
         compiled_function_node comp = meth.original_function as compiled_function_node;
         bw.Write((byte)PCUConsts.compiled_method_generic);
         WriteCompiledMethod(comp);
     }
     WriteTypeList(meth.get_generic_params_list());
 }
示例#3
0
 //(ssyy) Создаёт метод псевдо-инстанции generic-типа.
 protected common_method_node make_method(function_node orig_fn, location loc)
 {
     if (orig_fn == null)
     {
         return null;
     }
     List<type_node> meth_inst_pars = null;
     SemanticTree.IClassMemberNode orig_member = orig_fn as SemanticTree.IClassMemberNode;
     common_method_node cmn = new common_method_node(
         orig_fn.name,
         //generic_convertions.determine_type(orig_fn.return_value_type, _instance_params, false),
         null,
         loc, this, orig_member.polymorphic_state, orig_member.field_access_level,
         null);
     if (orig_fn.is_generic_function)
     {
         List<type_node> orig_tpars = orig_fn.get_generic_params_list();
         int type_count = orig_tpars.Count;
         cmn.generic_params = new List<PascalABCCompiler.SemanticTree.ICommonTypeNode>(orig_tpars.Count);
         foreach (type_node t in orig_tpars)
         {
             common_type_node par = new common_type_node(t.name, PascalABCCompiler.SemanticTree.type_access_level.tal_public,
                 null, SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.symbol_table.CreateInterfaceScope(null, SystemLibrary.SystemLibrary.object_type.Scope, null), null);
             SystemLibrary.SystemLibrary.init_reference_type(par);
             par.SetBaseType(SystemLibrary.SystemLibrary.object_type);
             cmn.generic_params.Add(par);
             par.generic_function_container = cmn;
         }
         meth_inst_pars = cmn.get_generic_params_list();
         List<generic_parameter_eliminations> gpes = orig_fn.parameters_eliminations;
         for (int i = 0; i < type_count; ++i)
         {
             common_type_node p = (common_type_node)(meth_inst_pars[i]);
             generic_parameter_eliminations gpe = gpes[i];
             p.SetBaseType(generic_convertions.determine_type(
                 generic_convertions.determine_type(gpe.base_class, _instance_params, false),
                 meth_inst_pars, true));
             p.is_class = gpe.is_class;
             p.internal_is_value = gpe.is_value;
             foreach (type_node interf in gpe.implementing_interfaces)
             {
                 type_table.AddInterface(p, generic_convertions.determine_type(
                     generic_convertions.determine_type(interf, _instance_params, false),
                     meth_inst_pars, true), null);
             }
             if (gpe.has_default_ctor)
             {
                 generic_parameter_eliminations.add_default_ctor(p);
             }
         }
     }
     cmn.parameters.AddRange(make_parameters(orig_fn.parameters, cmn));
     if (orig_fn.is_generic_function)
     {
         foreach (common_parameter cp in cmn.parameters)
         {
             cp.type = generic_convertions.determine_type(cp.type, meth_inst_pars, true);
         }
     }
     common_method_node common_orig = orig_fn as common_method_node;
     if (common_orig != null)
     {
         cmn.num_of_default_variables = common_orig.num_of_default_variables;
     }
     compiled_constructor_node compiled_orig = orig_fn as compiled_constructor_node;
     cmn.is_constructor = (compiled_orig != null ||
         (common_orig != null && common_orig.is_constructor));
     cmn.return_value_type = generic_convertions.determine_type(orig_fn.return_value_type, _instance_params, false);
     if (orig_fn.is_generic_function)
     {
         cmn.return_value_type = generic_convertions.determine_type(cmn.return_value_type, meth_inst_pars, true);
     }
     return cmn;
 }