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()); }
//(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; }