public static function_node DeduceFunction(function_node func, expressions_list fact, bool alone, location loc, List<SyntaxTree.expression> syntax_nodes_parameters = null) { parameter_list formal = func.parameters; int formal_count = formal.Count; int fact_count = fact.Count; int generic_type_params_count = func.generic_parameters_count; type_node[] deduced = new type_node[generic_type_params_count]; List<int> nils = new List<int>(); int count_params_to_see = fact_count; var lambda_syntax_nodes = new Dictionary<string, function_lambda_definition>(); //lroman Получим список фактических параметров-лямбд текущей вызываемой подпрограммы if (syntax_nodes_parameters != null && syntax_nodes_parameters.Count > 0) //lroman { lambda_syntax_nodes = syntax_nodes_parameters .OfType<function_lambda_definition>() .ToDictionary(f => f.lambda_name, f => f); } var lambda_in_parameters = lambda_syntax_nodes.Count > 0; var saved_lambdas_states = SaveLambdasStates(lambda_syntax_nodes.Select(ld => ld.Value)); // Сохраним типы лямбды перед вычислениями if (fact_count < formal_count) { //Сравниваем количества параметров parameter par = formal[fact_count]; if (par.default_value == null && !par.is_params) { if (alone) throw new NoFunctionWithSameParametresNum(loc, alone, func); return null; } } else { type_node last_params_type = null; bool last_is_params = false; parameter par = null; if (formal_count > 0) { par = formal[formal_count - 1]; last_is_params = par.is_params; } if (last_is_params) { array_internal_interface aii = par.type.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; last_params_type = aii.element_type; } if (fact_count > formal_count) { //Фактических больше, чем формальных. Последний формальный должен быть params... if (last_is_params) { for (int i = formal_count - 1; i < fact_count; ++i) { //Проверяем фактические, попадающие под params... if (!DeduceInstanceTypes(last_params_type, fact[i].type, deduced, nils)) { if (alone) throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); return null; } } count_params_to_see = formal_count - 1; } else { if (alone) throw new NoFunctionWithSameParametresNum(loc, alone, func); return null; } } } bool need_params_work = (count_params_to_see > 0 && formal[count_params_to_see - 1].is_params); if (need_params_work) { count_params_to_see -= 1; } var continue_trying_to_infer_types = true; Dictionary<string, delegate_internal_interface> formal_delegates = null; while (continue_trying_to_infer_types) //Продолжаем пытаться вычислить типы до тех пор пока состояние о выведенных типах не будет отличаться от состояния на предыдущей итерации { var previous_deduce_state = deduced // Текущее состояние выведенных на данный момент типов. Простой список индексов с уже выведенными типами из массива deduced .Select((t, i) => new { Type = t, Index = i }) .Where(t => t.Type != null) .Select(t => t.Index) .ToArray(); for (int i = 0; i < count_params_to_see; ++i) { if (!DeduceInstanceTypes(formal[i].type, fact[i].type, deduced, nils)) { if (alone) throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); RestoreLambdasStates(lambda_syntax_nodes.Values.ToList(), saved_lambdas_states); return null; } } if (lambda_in_parameters) { if (formal_delegates == null) { formal_delegates = new Dictionary<string, delegate_internal_interface>(); for (int i = 0; i < count_params_to_see; ++i) //Выделим из формальных параметров те, которые соотвтествуют фактическим параметрам-лямбдам { var lambda_func = fact[i].type as delegated_methods; if (lambda_func != null && lambda_func.proper_methods.Count == 1 && LambdaHelper.IsLambdaName(lambda_func.proper_methods[0].simple_function_node.name)) { formal_delegates.Add(LambdaHelper.GetLambdaNamePartWithoutGenerics(lambda_func.proper_methods[0].simple_function_node.name), formal[i].type.get_internal_interface( internal_interface_kind.delegate_interface) as delegate_internal_interface); } } } foreach (var formal_delegate in formal_delegates) //Перебираем все полученные формальные параемтры, соотвтетсвующие фактическим лямбдам { var lambda_syntax_node = lambda_syntax_nodes[formal_delegate.Key]; Exception on_lambda_body_compile_exception; // Исключение которое может возникунть в результате компиляции тела лямбды если мы выберем неправильные типы параметров if (!TryToDeduceTypesInLambda(lambda_syntax_node, formal_delegate.Value, deduced, nils, out on_lambda_body_compile_exception)) //Пробуем вычислить типы из лямбд { RestoreLambdasStates(lambda_syntax_nodes.Values.ToList(), saved_lambdas_states); if (on_lambda_body_compile_exception != null) { if (alone) { throw on_lambda_body_compile_exception; } throw new FailedWhileTryingToCompileLambdaBodyWithGivenParametersException( on_lambda_body_compile_exception); } if (alone) { throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); } return null; } } } var current_deduce_state = deduced //текущее состояние выведенных типов .Select((t, ii) => new {Type = t, Index = ii}) .Where(t => t.Type != null) .Select(t => t.Index) .ToArray(); if (previous_deduce_state.SequenceEqual(current_deduce_state)) // Если ничего с прошлой итерации не изменилось, то дальше нет смысла пробовать выводить. Выходим из цикла { continue_trying_to_infer_types = false; } } RestoreLambdasStates(lambda_syntax_nodes.Values.ToList(), saved_lambdas_states); if (need_params_work) { type_node[] tmp_deduced = (type_node[])deduced.Clone(); List<int> tmp_nils = new List<int>(); tmp_nils.AddRange(nils); if (!DeduceInstanceTypes(formal[count_params_to_see].type, fact[count_params_to_see].type, deduced, nils)) { //Второй шанс. Учитываем слово params. deduced = tmp_deduced; nils = tmp_nils; if (!DeduceInstanceTypes(formal[count_params_to_see].type.element_type, fact[count_params_to_see].type, deduced, nils)) { if (alone) throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); return null; } } } //Вывели всё, что могли. Теперь проверяем. for (int i = 0; i < generic_type_params_count; ++i) { if (deduced[i] == null) { if (alone) throw new SimpleSemanticError(loc, "CAN_NOT_DEDUCE_TYPE_PARAMS_FROM_CALL_{0}", func.name); return null; } } foreach (int num in nils) { if (!type_table.is_with_nil_allowed(deduced[num])) { if (alone) throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); return null; } } foreach (type_node tt in deduced) { CompilationErrorWithLocation check_err = generic_parameter_eliminations.check_type_generic_useful(tt, loc); if (check_err != null) { if (alone) throw check_err; return null; } } //Итак, вывели все параметры. Теперь инстанцируем. List<type_node> deduced_list = new List<type_node>(generic_type_params_count); deduced_list.AddRange(deduced); return func.get_instance(deduced_list, alone, loc); }