diff --git a/TreeConverter/TreeRealization/generics.cs b/TreeConverter/TreeRealization/generics.cs index 19e60c234..8341dbb72 100644 --- a/TreeConverter/TreeRealization/generics.cs +++ b/TreeConverter/TreeRealization/generics.cs @@ -922,13 +922,12 @@ namespace PascalABCCompiler.TreeRealization if (isTypeclassRestricted) { - //func.wh foreach (var tc in typeclasses) { var instances = context.typeclassInstances.Where(ti => (ti.ImplementingInterfaces[0] as common_generic_instance_type_node).original_generic == (tc.ImplementingInterfaces[0] as common_generic_instance_type_node).original_generic); - + var appropriateInstances = instances.Where(ti => (ti.ImplementingInterfaces[0] as common_generic_instance_type_node).instance_params.SequenceEqual( (tc.ImplementingInterfaces[0] as common_generic_instance_type_node).instance_params.Select(ip => deduced[ip.generic_param_index]))); @@ -936,14 +935,19 @@ namespace PascalABCCompiler.TreeRealization if (appropriateInstances.Count() == 1) { var foundInstance = appropriateInstances.First() as common_type_node; - if (foundInstance.generic_params.Count > 0) + if (foundInstance.generic_params?.Count > 0 is true) { - throw new NotImplementedException("Can't deduce type for typeclass inheritance"); + type_node[] deducedInstances = new type_node[foundInstance.generic_params.Count]; + DeduceTypeclassInstances(context, deducedInstances, foundInstance.generic_params.OfType()); + + deduced[tc.generic_param_index] = foundInstance.get_instance(deducedInstances.ToList()); + } + else + { + deduced[tc.generic_param_index] = appropriateInstances.First(); } - deduced[tc.generic_param_index] = appropriateInstances.First(); } } - //context.typeclassInstances.Where(ti => ti.ImplementingInterfaces[0].) } var current_deduce_state = deduced //текущее состояние выведенных типов @@ -1013,6 +1017,34 @@ namespace PascalABCCompiler.TreeRealization return func.get_instance(deduced_list, alone, loc); } + private static void DeduceTypeclassInstances(compilation_context context, type_node[] deduced, IEnumerable typeclasses) + { + foreach (var tc in typeclasses) + { + var instances = context.typeclassInstances.Where(ti => + (ti.ImplementingInterfaces[0] as common_generic_instance_type_node).original_generic == + (tc.ImplementingInterfaces[0] as common_generic_instance_type_node).original_generic); + + var appropriateInstances = instances.Where(ti => + (ti.ImplementingInterfaces[0] as common_generic_instance_type_node).instance_params.SequenceEqual( + (tc.ImplementingInterfaces[0] as common_generic_instance_type_node).instance_params)); + + if (appropriateInstances.Count() == 1) + { + var foundInstance = appropriateInstances.First() as common_type_node; + if (foundInstance.generic_params?.Count > 0 is true) + { + List instanceTypes = null; + deduced[tc.generic_param_index] = foundInstance.get_instance(instanceTypes); + } + else + { + deduced[tc.generic_param_index] = appropriateInstances.First(); + } + } + } + } + //Выведение типов public static bool DeduceInstanceTypes(type_node formal_type, type_node fact_type, type_node[] deduced, List nils) {