// Copyright (c) Ivan Bondarev, Stanislav Mihalkovich (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) //Здесь описана реализация generic-типов //Файлом владеет ssyy. using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using PascalABCCompiler.SyntaxTree; using PascalABCCompiler.TreeConverter; namespace PascalABCCompiler.TreeRealization { //Вспомогательный класс для реализации generic-типов public class generic_type_instance_info { public List param_types; public generic_instance_type_node pseudo_instance; public generic_type_instance_info(List _param_types, generic_instance_type_node _pseudo_instance) { param_types = _param_types; pseudo_instance = _pseudo_instance; } } public class generic_function_instance_info { public List param_types; public function_node pseudo_instance; public generic_function_instance_info(List _param_types, function_node _pseudo_instance) { param_types = _param_types; pseudo_instance = _pseudo_instance; } } public class generic_parameter_eliminations { public bool is_class = false; public bool is_value = false; public bool has_default_ctor = false; public type_node base_class = null; public List implementing_interfaces = null; public static void add_default_ctor(common_type_node param) { common_method_node cnode = new common_method_node( compiler_string_consts.default_constructor_name, param, null, param, SemanticTree.polymorphic_state.ps_common, SemanticTree.field_access_level.fal_public, null); cnode.is_constructor = true; param.methods.AddElement(cnode); param.add_name(compiler_string_consts.default_constructor_name, new SymbolInfo(cnode)); param.has_default_constructor = true; } public static List make_eliminations_common(List generic_params) { List _parameters_eliminations = new List(); foreach (type_node t in generic_params) { generic_parameter_eliminations gpe = new generic_parameter_eliminations(); gpe.has_default_ctor = generic_convertions.type_has_default_ctor(t, false); gpe.is_class = t.is_class; gpe.is_value = t.is_value; gpe.base_class = t.base_type; gpe.implementing_interfaces = new List(t.ImplementingInterfaces.Count); foreach (type_node interf in t.ImplementingInterfaces) { gpe.implementing_interfaces.Add(interf); } _parameters_eliminations.Add(gpe); } return _parameters_eliminations; } public static List make_eliminations_compiled(Type[] pars) { List _parameters_eliminations = new List(); foreach (Type t in pars) { generic_parameter_eliminations gpe = new generic_parameter_eliminations(); gpe.has_default_ctor = ((t.GenericParameterAttributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0); gpe.is_class = ((t.GenericParameterAttributes & GenericParameterAttributes.ReferenceTypeConstraint) != 0); gpe.is_value = ((t.GenericParameterAttributes & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0); gpe.base_class = compiled_type_node.get_type_node(t.BaseType); Type[] net_interf = t.GetInterfaces(); gpe.implementing_interfaces = new List(net_interf.Length); foreach (Type net_t in net_interf) { gpe.implementing_interfaces.Add(compiled_type_node.get_type_node(net_t)); } _parameters_eliminations.Add(gpe); } return _parameters_eliminations; } public static CompilationErrorWithLocation check_type_generic_useful(type_node tn, location loc) { if (tn == null) { return new SimpleSemanticError(loc, "TYPE_NAME_EXPECTED"); } if (tn.IsPointer) { return new SimpleSemanticError(loc, "CANNOT_USE_POINTER_AS_GENERIC_ARGUMENT"); } switch (tn.type_special_kind) { case PascalABCCompiler.SemanticTree.type_special_kind.diap_type: return new SimpleSemanticError(loc, "CANNOT_USE_DIAPASON_AS_GENERIC_ARGUMENT"); case PascalABCCompiler.SemanticTree.type_special_kind.typed_file: return new SimpleSemanticError(loc, "CANNOT_USE_TYPED_FILE_AS_GENERIC_ARGUMENT"); case PascalABCCompiler.SemanticTree.type_special_kind.short_string: return new SimpleSemanticError(loc, "CANNOT_USE_SHORT_STRING_AS_GENERIC_ARGUMENT"); } /*if (tn == SystemLibrary.SystemLibrary.void_type) { return new VoidNotValid(loc); }*/ SystemLibrary.SystemLibrary.syn_visitor.check_for_type_allowed(tn,loc); internal_interface ii = tn.get_internal_interface(internal_interface_kind.bounded_array_interface); if (ii != null) { return new SimpleSemanticError(loc, "CANNOT_USE_BOUNDED_ARRAY_AS_GENERIC_ARGUMENT"); } return null; } public static CompilationErrorWithLocation check_type_list(List tparams, List gpe_list, bool method_param_types, out int i) { int count = tparams.Count; for (i = 0; i < count; i++) { generic_parameter_eliminations gpe = gpe_list[i]; type_node tn = tparams[i]; if (gpe.is_class && !tn.is_class) { return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_BE_REFERENCE_TYPE", tn.PrintableName); } if (gpe.is_value && !tn.is_value) { return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_BE_VALUE_TYPE", tn.PrintableName); } if (gpe.base_class != null && gpe.base_class != SystemLibrary.SystemLibrary.object_type) { type_node base_type = generic_convertions.determine_type(gpe.base_class, tparams, method_param_types); if (base_type != tn && !type_table.is_derived(base_type, tn)) { return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_BE_DERIVED_FROM_{1}", tn.PrintableName, base_type.name); } } foreach (type_node interf in gpe.implementing_interfaces) { type_node di = generic_convertions.determine_type(interf, tparams, method_param_types); if (di != tn && (tn.ImplementingInterfaces == null || !type_table.is_derived(di, tn))) { return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_IMPLEMENT_INTERFACE_{1}", tn.PrintableName, di.name); } } if (gpe.has_default_ctor) { if (tn.IsAbstract || !tn.is_value && !generic_convertions.type_has_default_ctor(tn, false)) { return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_HAVE_DEFAULT_CONSTRUCTOR", tn.PrintableName); } } } return null; } } public class type_instance_and_location { public generic_instance_type_node instance; public location loc; public type_instance_and_location(generic_instance_type_node _instance, location _loc) { instance = _instance; loc = _loc; } } //Вспомогательный класс для создания псевдо-инстанций generic-типов. public static class generic_convertions { //Список, хранящий все псевдо-инстанции generic-типов, нужен для NetGenerator. public static List all_type_instances = new List(); public static List all_function_instances = new List(); public static Hashtable generic_instances = new Hashtable(); public static List get_type_instances(type_node original_generic_type) { List instances = generic_instances[original_generic_type] as List; if (instances == null) { instances = new List(); generic_instances.Add(original_generic_type, instances); } return instances; } public static List get_function_instances(function_node original_generic_function) { List instances = generic_instances[original_generic_function] as List; if (instances == null) { instances = new List(); generic_instances.Add(original_generic_function, instances); } return instances; } public static type_node find_type_instance(List _generic_instances, List param_types) { int count = param_types.Count; foreach (generic_type_instance_info gii in _generic_instances) { bool equals = true; for (int i = 0; equals && i < count; ++i) { equals = (param_types[i] == gii.param_types[i]); } if (equals) { //Такая инстанция уже есть return gii.pseudo_instance; } } return null; } public static void check_instances_are_correct(List insts) { int num; foreach (type_instance_and_location tia in insts) { List gpes = tia.instance.original_generic.parameters_eliminations; CompilationErrorWithLocation err = generic_parameter_eliminations.check_type_list(tia.instance.instance_params, gpes, false, out num); if (err != null) { err.loc = tia.loc; throw err; } } } public static function_node find_function_instance(List _generic_instances, List param_types) { int count = param_types.Count; foreach (generic_function_instance_info gii in _generic_instances) { bool equals = true; for (int i = 0; equals && i < count; ++i) { equals = (param_types[i] == gii.param_types[i]); } if (equals) { //Такая инстанция уже есть return gii.pseudo_instance; } } return null; } public static void init_generic_instance(type_node original, generic_instance_type_node instance, /*SymbolTable.ClassScope instance_scope,*/ List param_types) { instance.IsInterface = original.IsInterface; instance.is_class = original.is_class; instance.internal_is_value = original.is_value; instance.SetIsSealed(original.IsSealed); instance.IsDelegate = original.IsDelegate; instance.type_special_kind = original.type_special_kind; //Определяем базовый тип type_node btype = determine_type( original.base_type, param_types, false); instance.SetBaseTypeIgnoringScope(btype); //instance._scope = new SymbolTable.GenericTypeInstanceScope(instance, instance.original_generic.Scope, btype.Scope); foreach (type_node interf in original.ImplementingInterfaces) { instance.ImplementingInterfaces.Add( determine_type(interf, param_types, false) ); } SystemLibrary.SystemLibrary.init_reference_type(instance); instance.conform_basic_functions(); //(ssyy) Нужно, чтобы добавились конструкторы //ctnode.find_in_type(compiler_string_consts.default_constructor_name); instance.instance_params = param_types; property_node orig_pn = original.default_property_node; if (orig_pn != null) { if (orig_pn.comprehensive_type == original) { //Свойство по умолчанию описано в оригинальном коде generic-a; //конвертируем его instance.default_property = instance.ConvertMember(orig_pn) as common_property_node; } else { //Свойство по умолчанию описано в каком-то предке оригинального generic-a if (orig_pn.comprehensive_type.is_generic_type_definition) { instance.default_property = instance.find_instance_type_from(orig_pn.comprehensive_type).default_property; } } } var shouldAddToAllTypeInstances = true; if (LambdaHelper.processingLambdaParametersForTypeInference != 0) { foreach (var par in instance.generic_parameters) { if (par is lambda_any_type_node) { shouldAddToAllTypeInstances = false; break; } } } if (shouldAddToAllTypeInstances) //lroman// Если зашли сюда при выведении типов параметров лямбды, то тип инстанцироваться может с типом lambda_any_type_node. Поэтому, если выводим типы. То данную инстанцию не добавляем { if (instance.instance_params[0] is ienumerable_auto_type) // SSM 10.07.16 (yields) в эту таблицу не включаются типы IEnumerable, т.к. потом они всё равно автовыводятся { //instance = instance; } else { generic_convertions.all_type_instances.Add(instance); } } internal_interface ii = original.get_internal_interface(internal_interface_kind.delegate_interface); if (ii != null) { delegate_internal_interface dii = ii as delegate_internal_interface; common_method_node inv = instance.ConvertMember(dii.invoke_method) as common_method_node; common_method_node constr = instance.ConvertMember(dii.constructor) as common_method_node; constr.function_code = new runtime_statement(SemanticTree.runtime_statement_type.ctor_delegate, null); delegate_internal_interface converted_dii = new delegate_internal_interface(inv.return_value_type, inv, constr); converted_dii.parameters.AddRange(inv.parameters); instance.add_internal_interface(converted_dii); } } public static void reset_generics() { generic_instances.Clear(); all_type_instances.Clear(); all_function_instances.Clear(); } //Определяет, как должен выглядеть тип в семантическом дереве. //Возвращает этот тип. public static type_node determine_type(Type t, List param_types, bool method_param_types) { if (t == null) return null; if (t.IsGenericParameter) { //Если мы определяем тип-параметры метода, нет необходимости рассматривать //тип-параметры типа, и наоборот. Это для поддержки generic-методов в //generic-типе. if (method_param_types == (t.DeclaringMethod != null)) { return param_types[t.GenericParameterPosition]; } else { return compiled_type_node.get_type_node(t); } } if (t.IsGenericType) { //Формируем список типов-параметров Type[] args = t.GetGenericArguments(); List semantic_args = new List(); foreach (Type arg in args) { semantic_args.Add(determine_type(arg, param_types, method_param_types)); } //Получаем описание generic-класса Type def = t.GetGenericTypeDefinition(); compiled_type_node ct_def = compiled_type_node.get_type_node(def); //Создаём псевдо-инстанцию return ct_def.get_instance(semantic_args); } //Для типов, не имеющих отношения к generic-типам. return compiled_type_node.get_type_node(t); } public static type_node determine_type(type_node tn, List param_types, bool method_param_types) { if (tn == null) return null; ref_type_node rtn = tn as ref_type_node; if (rtn != null) { type_node ptype = generic_convertions.determine_type(rtn.pointed_type, param_types, method_param_types); if (ptype == rtn.pointed_type) return tn; ref_type_node rez_ref = ptype.ref_type; rez_ref.loc = rtn.loc; return rez_ref; } array_internal_interface ii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; if (ii != null) { type_node elem_tp = determine_type(ii.element_type, param_types, method_param_types); if (elem_tp != ii.element_type) { return SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.type_constructor.create_unsized_array(elem_tp, null, ii.rank, null); } return tn; } common_type_node comm_type = tn as common_type_node; if (comm_type != null) { if (comm_type.is_generic_parameter) { if (method_param_types && comm_type.generic_function_container != null) { return param_types[comm_type.generic_param_index]; } else if (!method_param_types && comm_type.generic_type_container != null) { return param_types[comm_type.generic_param_index]; } return tn; } generic_instance_type_node gitn = tn as generic_instance_type_node; if (gitn != null) { List semantic_args = new List(); List gitn_inst_parameters = gitn.instance_params; foreach (type_node arg in gitn_inst_parameters) { semantic_args.Add(determine_type(arg, param_types, method_param_types)); } return gitn.original_generic.get_instance(semantic_args); } if (comm_type.is_generic_type_definition) { return comm_type.get_instance(param_types); } if (comm_type.type_special_kind == SemanticTree.type_special_kind.array_kind) { type_node elem_tp = determine_type(comm_type.element_type, param_types, method_param_types); if (elem_tp != comm_type.element_type) { return SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.type_constructor.create_unsized_array(elem_tp, null, 1, comm_type.loc); } return tn; } if (comm_type.type_special_kind == SemanticTree.type_special_kind.set_type) { type_node elem_tp = determine_type(comm_type.element_type, param_types, method_param_types); if (elem_tp != comm_type.element_type) { return SystemLibrary.SystemLibrary.syn_visitor.context.create_set_type(elem_tp, comm_type.loc); } return tn; } if (comm_type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.typed_file) { type_node elem_tp = determine_type(comm_type.element_type, param_types, method_param_types); if (elem_tp != comm_type.element_type) { return SystemLibrary.SystemLibrary.syn_visitor.context.create_typed_file_type(elem_tp, comm_type.loc); } return tn; } return tn; } compiled_type_node ctn = tn as compiled_type_node; if (ctn == null || (!ctn.compiled_type.IsGenericType && !ctn.compiled_type.IsGenericParameter)) { return tn; } return determine_type(ctn.compiled_type, param_types, method_param_types); } private static bool CheckIfTypeDependsOnUndeducedGenericParameters(type_node formalType, type_node[] deduced) //lroman { if (formalType.generic_function_container != null) { var par_num = formalType.generic_param_index; return deduced[par_num] == null; } var formalRef = formalType as ref_type_node; if (formalRef != null) { return CheckIfTypeDependsOnUndeducedGenericParameters(formalRef.pointed_type, deduced); } var formalIi = formalType.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; if (formalIi != null) { return CheckIfTypeDependsOnUndeducedGenericParameters(formalIi.element_type, deduced); } if (formalType.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.set_type) { return CheckIfTypeDependsOnUndeducedGenericParameters(formalType.element_type, deduced); } if (formalType.IsDelegate) { var dii = formalType.get_internal_interface(internal_interface_kind.delegate_interface) as delegate_internal_interface; var paramCount = dii.parameters.Count; for (var i = 0; i < paramCount; i++) { if (!CheckIfTypeDependsOnUndeducedGenericParameters(dii.parameters[i].type, deduced)) { return false; } } return CheckIfTypeDependsOnUndeducedGenericParameters(dii.return_value_type, deduced); } if (formalType.is_generic_type_instance) { var pcount = formalType.instance_params.Count; for (var k = 0; k < pcount; ++k) { if (!CheckIfTypeDependsOnUndeducedGenericParameters(formalType.instance_params[k], deduced)) { return false; } } return true; } return false; } //Сохранить типы параметров и тип возвращаемого значения лямбд перед попыткой вычисления реального типа возвращаемого знаяения лямбд private static Dictionary, type_node>> SaveLambdasStates(IEnumerable lambdaParametersList) { var savedLambdasStates = new Dictionary, type_node>>(); foreach (var lambda in lambdaParametersList) { var parsTypes = new List(); if (lambda.formal_parameters != null && lambda.formal_parameters.params_list != null && lambda.formal_parameters.params_list.Count > 0) { parsTypes.AddRange(lambda .formal_parameters .params_list .Select(t => { var lambdaNode = t.vars_type as lambda_inferred_type; if (lambdaNode == null) { return null; } return lambdaNode.real_type is lambda_any_type_node ? (lambda_any_type_node) lambdaNode.real_type : null; })); } type_node retType; var lambdaResNode = lambda.return_type as lambda_inferred_type; if (lambdaResNode == null) { retType = null; } else { retType = lambdaResNode.real_type is lambda_any_type_node ? (lambda_any_type_node)lambdaResNode.real_type : null; } savedLambdasStates.Add(lambda.lambda_name, new Tuple, type_node>(parsTypes, retType)); } return savedLambdasStates; } //Восстановление типов в исходное состояние на случай подстановки других типов private static void RestoreLambdasStates(List lambdaParametersList, Dictionary, type_node>> savedLambdasStates) { for (var i = 0; i < lambdaParametersList.Count; i++) { var state = savedLambdasStates[lambdaParametersList[i].lambda_name]; var lambdaPar = lambdaParametersList[i]; for (var k = 0; k < state.Item1.Count; k++) { var lambdaNode = lambdaPar.formal_parameters.params_list[k].vars_type as lambda_inferred_type; if (lambdaNode != null && state.Item1[k] != null) { lambdaNode.real_type = state.Item1[k]; } } var resLambdaNode = lambdaPar.return_type as lambda_inferred_type; if (resLambdaNode != null && state.Item2 != null) { resLambdaNode.real_type = state.Item2; } } } //Попытка вычислить типы после подстановки типов формальных параметров public static bool TryToDeduceTypesInLambda(function_lambda_definition lambda_syntax_node, delegate_internal_interface formal_delegate, type_node[] deduced, List nils, out Exception exception_on_body_compilation) { var there_are_undeduced_params = false; var param_counter = 0; var visitor = SystemLibrary.SystemLibrary.syn_visitor; var result = true; exception_on_body_compilation = null; if (lambda_syntax_node.formal_parameters == null || lambda_syntax_node.formal_parameters.params_list == null || lambda_syntax_node.formal_parameters.params_list.Count == 0) { return false; } foreach (var t in lambda_syntax_node.formal_parameters.params_list) { var lambdaInfType = t.vars_type as lambda_inferred_type; if (lambdaInfType != null && lambdaInfType.real_type is lambda_any_type_node) { if (formal_delegate == null) // SSM 5.12.15 { return false; } if (!CheckIfTypeDependsOnUndeducedGenericParameters(formal_delegate.parameters[param_counter].type, deduced)) //Если тип параметра не зависит от невыведенных дженерик-параметров, то можем вычислить этот тип явно { lambdaInfType.real_type = generic_convertions.determine_type(formal_delegate.parameters[param_counter].type, deduced.ToList(), true); //инстанцируем и записываем вычесленный тип } else { there_are_undeduced_params = true; //иначе мы не сможем вывести тип возвращаемого значения break; } } param_counter += t.idents.idents.Count; } if (!there_are_undeduced_params && lambda_syntax_node.return_type is lambda_inferred_type && ((lambda_inferred_type)lambda_syntax_node.return_type).real_type is lambda_any_type_node) { var lambdaName = lambda_syntax_node.lambda_name; var fl = lambda_syntax_node.lambda_visit_mode; lambda_syntax_node.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; var aux_name = LambdaHelper.GetAuxiliaryLambdaName(lambda_syntax_node.lambda_name); lambda_syntax_node.lambda_name = aux_name; try { visitor.visit(lambda_syntax_node); //пробуем скомпилировать тело лямбды, вычислим тип возвращаемого значения } catch (Exception exc) { exception_on_body_compilation = exc; // Если произошло исключение то запишем его в выходной параметр, оно потом будет обработано вызывающим методом result = false; } finally { var context = visitor.context; //Далее надо удалить ненужный узел из списка функций LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, lambda_syntax_node); lambda_syntax_node.lambda_name = lambdaName; lambda_syntax_node.lambda_visit_mode = fl; if (result) { if (formal_delegate == null) // SSM 5.12.15 { result = false; } else { if (formal_delegate.return_value_type==null) // SSM 19/04/16 - эта проверка в связи с падением при передаче функции вместо процедуры в качестве функционального параметра: a.Foreach(x->1) { result = false; } else if (!DeduceInstanceTypes(formal_delegate.return_value_type, (type_node)((lambda_inferred_type)lambda_syntax_node.return_type).real_type, deduced, nils)) //Выводим дженерик-параметры после того как вычислили тип возвращаемого значения { result = false; } } } } } return result; } public static function_node DeduceFunction(function_node func, expressions_list fact, bool alone, location loc, List 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 nils = new List(); int count_params_to_see = fact_count; var lambda_syntax_nodes = new Dictionary(); //lroman Получим список фактических параметров-лямбд текущей вызываемой подпрограммы if (syntax_nodes_parameters != null && syntax_nodes_parameters.Count > 0) //lroman { lambda_syntax_nodes = syntax_nodes_parameters .OfType() .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; } } else if (last_is_params) { for (int i = formal_count - 1; i < fact_count; ++i) { //Проверяем фактические, попадающие под params... type_node tn = fact[i].type; if (tn.element_type != null && tn.type_special_kind != SemanticTree.type_special_kind.array_wrapper) tn = tn.element_type; if (!DeduceInstanceTypes(last_params_type, tn, 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; } } 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 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 (alone && fact[i].type is delegated_methods && (fact[i].type as delegated_methods).empty_param_method != null && DeduceInstanceTypes(formal[i].type, (fact[i].type as delegated_methods).empty_param_method.type, deduced, nils)) continue; else if (!DeduceInstanceTypes(formal[i].type, fact[i].type, deduced, nils)) { if (alone && fact[i].type is delegated_methods && (fact[i].type as delegated_methods).empty_param_method != null) { if (DeduceInstanceTypes(formal[i].type, (fact[i].type as delegated_methods).empty_param_method.type, deduced, nils)) continue; } 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(); 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 tmp_nils = new List(); 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 deduced_list = new List(generic_type_params_count); deduced_list.AddRange(deduced); return func.get_instance(deduced_list, alone, loc); } //Выведение типов public static bool DeduceInstanceTypes(type_node formal_type, type_node fact_type, type_node[] deduced, List nils) { if (fact_type == null)//issue #347 return false; if (formal_type.generic_function_container == null && fact_type.generic_function_container != null) { //swap type_node tmp = formal_type; formal_type = fact_type; fact_type = tmp; } //Формальный тип - generic-параметр функции. Выводим. if (formal_type.generic_function_container != null) { int par_num = formal_type.generic_param_index; if (fact_type.semantic_node_type == semantic_node_type.null_type_node) { nils.Add(par_num); return true; } if (deduced[par_num] == null) { //Этот тип-параметр ещё не был выведен. if (fact_type is delegated_methods && (fact_type as delegated_methods).empty_param_method != null && (fact_type as delegated_methods).empty_param_method.ret_type != null) fact_type = (fact_type as delegated_methods).empty_param_method.ret_type; deduced[par_num] = fact_type; return true; } //Этот тип-параметр уже был выведен. Сравниваем с выведенным. if (!convertion_data_and_alghoritms.eq_type_nodes(fact_type, deduced[par_num], true)) { return false; } return true; } //Указатели ref_type_node formal_ref = formal_type as ref_type_node; if (formal_ref != null) { ref_type_node fact_ref = fact_type as ref_type_node; if (fact_ref == null) { goto eq_cmp; } return DeduceInstanceTypes(formal_ref.pointed_type, fact_ref.pointed_type, deduced, nils); } //безразмерные массивы array_internal_interface formal_ii = formal_type.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; if (formal_ii != null) { array_internal_interface fact_ii = fact_type.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; if (fact_ii == null) { goto eq_cmp; } return DeduceInstanceTypes(formal_ii.element_type, fact_ii.element_type, deduced, nils); } //множества if (formal_type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.set_type) { if (fact_type.type_special_kind != PascalABCCompiler.SemanticTree.type_special_kind.set_type) { goto eq_cmp; } return DeduceInstanceTypes(formal_type.element_type, fact_type.element_type, deduced, nils); } //множества if (formal_type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.typed_file) { if (fact_type.type_special_kind != PascalABCCompiler.SemanticTree.type_special_kind.typed_file) { goto eq_cmp; } return DeduceInstanceTypes(formal_type.element_type, fact_type.element_type, deduced, nils); } //Делегаты if (formal_type.IsDelegate) { //Если текущий параметр - лямбда, то просто выводим дженерик-параметры из типов, которые уже известны. Не трогаем lambda_any_type_node. Остальное выведется в цикле выше var lambda_func = fact_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)) { var dii = formal_type.get_internal_interface(internal_interface_kind.delegate_interface) as delegate_internal_interface; var fact_func = lambda_func.proper_methods[0].simple_function_node; if (fact_func.parameters.Count != dii.parameters.Count) { goto eq_cmp; } var param_count = fact_func.parameters.Count; for (var i = 0; i < param_count; i++) { if (fact_func.parameters[i].parameter_type != dii.parameters[i].parameter_type || fact_func.parameters[i].is_params != dii.parameters[i].is_params) goto eq_cmp; } for (var i = 0; i < param_count; i++) { if (fact_func.parameters[i].type is lambda_any_type_node) { continue; } // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка if (!DeduceInstanceTypes(dii.parameters[i].type, fact_func.parameters[i].type, deduced, nils)) //if (!DeduceInstanceTypes(fact_func.parameters[i].type, dii.parameters[i].type, deduced, nils)) { goto eq_cmp; } } if (fact_func.return_value_type == null && dii.return_value_type == null) { //ok } else if (fact_func.return_value_type is lambda_any_type_node) //lroman// { if (dii.return_value_type == null) { goto eq_cmp; } return true; } // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка else if (fact_func.return_value_type == null || !DeduceInstanceTypes(dii.return_value_type, fact_func.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable // else if (fact_func.return_value_type == null || !DeduceInstanceTypes(fact_func.return_value_type, dii.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable { goto eq_cmp; } return true; } if (!convertion_data_and_alghoritms.eq_type_nodes(formal_type, fact_type, true)) { delegate_internal_interface dii = formal_type.get_internal_interface(internal_interface_kind.delegate_interface) as delegate_internal_interface; delegated_methods dm = fact_type as delegated_methods; if (dm != null && dm.proper_methods.Count == 1) { function_node fact_func = dm.proper_methods[0].simple_function_node; if (fact_func.parameters.Count != dii.parameters.Count) { goto eq_cmp; } int param_count = fact_func.parameters.Count; for (int i = 0; i < param_count; i++) { if (fact_func.parameters[i].parameter_type != dii.parameters[i].parameter_type || fact_func.parameters[i].is_params != dii.parameters[i].is_params) goto eq_cmp; } for (int i = 0; i < param_count; i++) { if (!DeduceInstanceTypes(dii.parameters[i].type, fact_func.parameters[i].type, deduced, nils)) // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка //if (!DeduceInstanceTypes(fact_func.parameters[i].type, dii.parameters[i].type, deduced, nils)) { goto eq_cmp; } } if (fact_func.return_value_type == null && dii.return_value_type == null) { //ok } else if (fact_func.return_value_type is lambda_any_type_node && dii.return_value_type == null) //lroman// { goto eq_cmp; } // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка else if (fact_func.return_value_type == null || !DeduceInstanceTypes(dii.return_value_type, fact_func.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable // else if (fact_func.return_value_type == null || !DeduceInstanceTypes(fact_func.return_value_type, dii.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable { goto eq_cmp; } return true; } } if (fact_type.IsDelegate && fact_type.semantic_node_type == semantic_node_type.delegated_method) return true; //goto eq_cmp; } //Инстанции дженериков if (formal_type.is_generic_type_instance) { //if () goto eq_cmp; type_node fact_type_converted; //Сюда будет записан фактический тип или интерфейс, к которому он приводится if (!fact_type.is_generic_type_instance || formal_type.original_generic != fact_type.original_generic) { if (!formal_type.IsInterface) goto eq_cmp; fact_type_converted = null; if (fact_type.ImplementingInterfaces != null) foreach (type_node ti in fact_type.ImplementingInterfaces) { if (ti.original_generic == formal_type.original_generic) { fact_type_converted = ti; break; } } if (fact_type_converted == null) goto eq_cmp; } else { fact_type_converted = fact_type; } int pcount = formal_type.instance_params.Count; for (int k = 0; k < pcount; ++k) { if (!DeduceInstanceTypes(formal_type.instance_params[k], fact_type_converted.instance_params[k], deduced, nils)) { goto eq_cmp; } } return true; } //Если совпадают - всё хорошо. eq_cmp: if (convertion_data_and_alghoritms.eq_type_nodes(formal_type, fact_type, true)) { return true; } possible_type_convertions ptc = type_table.get_convertions(fact_type, formal_type); if (ptc.first != null) { return true; } return false; } public static string MakePseudoInstanceName(string name, List param_types, bool type_name) { string rez; if (type_name) { int last = name.LastIndexOf(compiler_string_consts.generic_params_infix); if (last < 0) { rez = name; } else { rez = name.Substring(0, last); } } else { rez = name; } bool first = true; foreach (type_node tnode in param_types) { rez += ((first) ? "<" : ",") + tnode.PrintableName; first = false; } rez += ">"; return rez; } public static bool type_has_default_ctor(type_node tn, bool find_protected_ctors) { SymbolInfo si = tn.find_in_type(compiler_string_consts.default_constructor_name, tn.Scope); while (si != null) { function_node fn = si.sym_info as function_node; if (find_protected_ctors || fn.field_access_level == PascalABCCompiler.SemanticTree.field_access_level.fal_public) { compiled_constructor_node pconstr = fn as compiled_constructor_node; common_method_node mconstr = fn as common_method_node; if ((pconstr != null || mconstr != null && mconstr.is_constructor) && (fn.parameters.Count == 0 || fn.parameters[0].default_value != null) ) { //Нашли конструктор по умолчанию у предка return true; } } si = si.Next; } return false; } public static function_node get_function_instance(function_node orig, List param_types) { List _generic_instances = get_function_instances(orig); function_node founded_inst = find_function_instance(_generic_instances, param_types); if (founded_inst != null) return founded_inst; for (int i=0; i _generic_parameters = null; protected List _instance_params; public generic_instance_type_node(type_node original_generic_type, List param_types, type_node base_type, string name, SemanticTree.type_access_level type_access_level, common_namespace_node comprehensive_namespace, location loc) : base(base_type, name, type_access_level, comprehensive_namespace, null, loc) { _original_generic = original_generic_type; _instance_params = param_types; } public List generic_parameters { get { if (_generic_parameters == null) { _generic_parameters = new List(_instance_params.Count); foreach (type_node tn in _instance_params) { _generic_parameters.Add(tn); } } return _generic_parameters; } } private List temp_names = new List(3); public override void add_name(string name, SymbolInfo si) { temp_names.Add(si); } protected void AddMember(object original, object converted) { _members.Add(original, converted); _member_definitions.Add(converted, original); } protected parameter_list make_parameters(parameter_list orig_pl, common_function_node fn) { parameter_list pl = new parameter_list(); //TODO: разобраться с concrete_parameter_type foreach (parameter p in orig_pl) { common_parameter cp = new common_parameter( p.name, generic_convertions.determine_type(p.type, _instance_params, false), p.parameter_type, fn, concrete_parameter_type.cpt_none, p.inital_value, null); cp.intrenal_is_params = p.is_params; cp.is_special_name = p.is_special_name; cp.is_ret_value = p.is_ret_value; cp.default_value = p.default_value; pl.AddElement(cp); } return pl; } //(ssyy) Создаёт метод псевдо-инстанции generic-типа. protected common_method_node make_method(function_node orig_fn, location loc) { if (orig_fn == null) { return null; } List 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 orig_tpars = orig_fn.get_generic_params_list(); int type_count = orig_tpars.Count; cmn.generic_params = new List(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 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; } public override List instance_params { get { return _instance_params; } set { _instance_params = value; } } public override bool is_generic_type_instance { get { return true; } } protected void AddPropertyAccessors(property_node pn) { if (pn.get_function != null) { if (_members[pn.get_function] == null) { ConvertMember(pn.get_function); } } if (pn.set_function != null) { if (_members[pn.set_function] == null) { ConvertMember(pn.set_function); } } } protected common_property_node make_property(property_node orig_pn, location loc) { AddPropertyAccessors(orig_pn); common_property_node cpn = new common_property_node( orig_pn.name, this, generic_convertions.determine_type( orig_pn.property_type, _instance_params, false), (orig_pn.get_function == null) ? null : _members[orig_pn.get_function] as common_method_node, (orig_pn.set_function == null) ? null : _members[orig_pn.set_function] as common_method_node, loc, orig_pn.field_access_level, orig_pn.polymorphic_state); cpn.parameters.AddRange(make_parameters(orig_pn.parameters, null)); return cpn; } public definition_node get_member_definition(definition_node instance_member) { return _member_definitions[instance_member] as definition_node; } public generic_instance_type_node find_instance_type_from(type_node orig_type) { generic_instance_type_node bt = null;//this; /*while (bt != null) { if (bt._original_generic == orig_type) { return bt; } bt = bt.base_type as generic_instance_type_node; }*/ type_node curt = this; while (curt != null) { bt = curt as generic_instance_type_node; if (bt != null && bt.original_generic == orig_type) { return bt; } curt = curt.base_type; } foreach (type_node tn in ImplementingInterfaces) { bt = tn as generic_instance_type_node; if (bt != null && bt._original_generic == orig_type) { return bt; } } return null; } public definition_node ConvertMember(definition_node orig_node) { definition_node rez_node = _members[orig_node] as definition_node; if (rez_node == null) { //Преобразуем найденный член класса. SemanticTree.IClassMemberNode orig_member = orig_node as SemanticTree.IClassMemberNode; if (orig_member == null) { //Для basic_function generic_instance_type_node gitn = base_type as generic_instance_type_node; if (gitn == null) return orig_node; else return gitn.ConvertMember(orig_node); } type_node tn = orig_member.comperehensive_type as type_node; if (orig_member.comperehensive_type.is_generic_type_instance) tn = tn.original_generic; if (tn != _original_generic) { if (orig_member.comperehensive_type.is_generic_type_definition) { generic_instance_type_node compr_type = find_instance_type_from(orig_member.comperehensive_type as type_node); if (compr_type == null) { compiled_function_node cfn = orig_node as compiled_function_node; if (cfn == null) { return orig_node; } compiled_type_node cct = orig_member.comperehensive_type as compiled_type_node; type_node inst_type = this; do { inst_type = inst_type.base_type; } while (inst_type.semantic_node_type != semantic_node_type.compiled_type_node || (inst_type != cct && inst_type.original_generic != cct)); MethodInfo[] meths = cct._compiled_type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); int num = System.Array.IndexOf(meths, cfn.method_info); MethodInfo mi = ((compiled_type_node)inst_type)._compiled_type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)[num]; return compiled_function_node.get_compiled_method(mi); } else return compr_type.ConvertMember(orig_node); } else if (orig_member.comperehensive_type.is_generic_type_instance) { generic_instance_type_node compr_type = find_instance_type_from(tn); if (compr_type == null) { compiled_function_node cfn = orig_node as compiled_function_node; if (cfn == null) { return orig_node; } compiled_type_node cct = tn as compiled_type_node; type_node inst_type = this; do { inst_type = inst_type.base_type; } while (inst_type.semantic_node_type != semantic_node_type.compiled_type_node || (inst_type != cct && inst_type.original_generic != cct)); MethodInfo[] meths = cct._compiled_type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); int num = System.Array.IndexOf(meths, cfn.method_info); MethodInfo mi = ((compiled_type_node)inst_type)._compiled_type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)[num]; return compiled_function_node.get_compiled_method(mi); } else return compr_type.ConvertMember(orig_node); // } else return orig_node; } SemanticTree.ILocated orig_loc = orig_node as SemanticTree.ILocated; location loc = (orig_loc == null) ? null : (orig_loc.Location as location); switch (orig_node.general_node_type) { case general_node_type.constant_definition: constant_definition_node orig_cdn = orig_node as constant_definition_node; rez_node = new class_constant_definition( orig_cdn.name, orig_cdn.const_value, loc, this, orig_member.field_access_level); break; case general_node_type.variable_node: var_definition_node orig_cf = (var_definition_node)(orig_node); rez_node = new class_field(orig_cf.name, generic_convertions.determine_type(orig_cf.type, _instance_params, false), this, orig_member.polymorphic_state, orig_member.field_access_level, loc); break; case general_node_type.property_node: property_node orig_pn = (property_node)(orig_node); rez_node = make_property(orig_pn, loc); break; case general_node_type.function_node: function_node orig_fn = (function_node)(orig_node); rez_node = make_method(orig_fn, loc); break; case general_node_type.event_node: //(ssyy) Не знаю, что тут делать rez_node = orig_node; break; default: throw new CompilerInternalError("Unexpected definition_node."); } AddMember(orig_node, rez_node); } return rez_node; } public SymbolInfo ConvertSymbolInfo(SymbolInfo start) { SymbolInfo si = start; SymbolInfo rez_start = null; SymbolInfo rez_si = null; SymbolInfo rez_prev = null; while (si != null) { definition_node dnode = ConvertMember(si.sym_info); rez_si = new SymbolInfo(dnode, si.access_level, si.symbol_kind); //Дополняем список SymbolInfo преобразованным значением if (rez_start == null) { rez_start = rez_si; } else { rez_prev.Next = rez_si; } rez_prev = rez_si; si = si.Next; } if (rez_si != null) { rez_si.Next = null; } return rez_start; } public override SymbolInfo find(string name, bool no_search_in_extension_methods = false) { SymbolInfo si = _original_generic.find(name); si = ConvertSymbolInfo(si); return si; } public override SymbolInfo find_in_type(string name, bool no_search_in_extension_methods = false) { SymbolInfo si = _original_generic.find_in_type(name); si = ConvertSymbolInfo(si); return si; } public override SymbolInfo find_in_type(string name, SymbolTable.Scope CurrentScope, bool no_search_in_extension_methods = false) { SymbolInfo si = _original_generic.find_in_type(name, CurrentScope); si = ConvertSymbolInfo(si); return si; } private void conform_basic_function(string name, int base_func_num) { SymbolInfo si1 = _original_generic.find_in_type(name); AddMember(si1.sym_info, temp_names[base_func_num].sym_info); } public void conform_basic_functions() { conform_basic_function(compiler_string_consts.assign_name, 0); conform_basic_function(compiler_string_consts.eq_name, 1); conform_basic_function(compiler_string_consts.noteq_name, 2); temp_names = null; } public virtual List all_methods { get { return null; } } public virtual List all_field_types { get { return null; } } public override generic_instance_type_node base_generic_instance { get { return this; } } public override bool depended_from_indefinite { get { if (_instance_params == null) { return false; } foreach (type_node tn in _instance_params) { if (tn.depended_from_indefinite) { return true; } } return false; } } } //Класс, характеризующий одну псевдоинстанцию generic-типа public class compiled_generic_instance_type_node : generic_instance_type_node, SemanticTree.ICompiledGenericTypeInstance { public compiled_type_node compiled_original_generic { get { return _original_generic as compiled_type_node; } } public override string BaseFullName { get { return compiled_original_generic.BaseFullName; } } public compiled_generic_instance_type_node(compiled_type_node generic_definition, List param_types, type_node base_type, string name, SemanticTree.type_access_level type_access_level, common_namespace_node comprehensive_namespace, location loc) : base(generic_definition, param_types, base_type, name, type_access_level, comprehensive_namespace, loc) { } private List _all_methods = null; public override List all_methods { get { if (_all_methods != null) return _all_methods; _all_methods = new List(); System.Reflection.MemberInfo[] orig_members = compiled_original_generic.compiled_type.GetMembers(); foreach (System.Reflection.MemberInfo mi in orig_members) { if (mi.MemberType == System.Reflection.MemberTypes.Method) { compiled_function_node cmeth = compiled_function_node.get_compiled_method((System.Reflection.MethodInfo)mi); _all_methods.Add(ConvertMember(cmeth) as function_node); } } return _all_methods; } } private List _all_field_types = null; public override List all_field_types { get { if (_all_field_types != null) return _all_field_types; System.Reflection.FieldInfo[] fields = compiled_original_generic.compiled_type.GetFields(); _all_field_types = new List(); foreach (System.Reflection.FieldInfo fi in fields) { if (!fi.IsStatic) { _all_field_types.Add(generic_convertions.determine_type(compiled_type_node.get_type_node(fi.FieldType), instance_params, false)); } } return _all_field_types; } } } //Класс, характеризующий одну псевдоинстанцию generic-типа public class common_generic_instance_type_node : generic_instance_type_node, SemanticTree.ICommonGenericTypeInstance { public common_type_node common_original_generic { get { return _original_generic as common_type_node; } } public common_generic_instance_type_node(common_type_node generic_definition, List param_types, type_node base_type, string name, SemanticTree.type_access_level type_access_level, common_namespace_node comprehensive_namespace, location loc) : base(generic_definition, param_types, base_type, name, type_access_level, comprehensive_namespace, loc) { } private List _all_methods = null; public override List all_methods { get { if (_all_methods != null) return _all_methods; common_method_node_list orig_meths = common_original_generic.methods; _all_methods = new List(orig_meths.Count); foreach (common_method_node cnode in orig_meths) { _all_methods.Add(ConvertMember(cnode) as function_node); } return _all_methods; } } private List _all_field_types = null; public override List all_field_types { get { if (_all_field_types != null) return _all_field_types; class_field_list orig_fields = common_original_generic.fields; _all_field_types = new List(orig_fields.Count); foreach (class_field cf in orig_fields) { _all_field_types.Add(generic_convertions.determine_type(cf.type, this.instance_params, false)); } return _all_field_types; } } } //Класс для запрещения создания в одной области видимости generic-классов с одинаковым именем. public class generic_indicator : definition_node, SemanticTree.ILocated { private common_type_node _generic; public common_type_node generic { get { return _generic; } } public generic_indicator(common_type_node generic_type) { _generic = generic_type; } public SemanticTree.ILocation Location { get { return _generic.Location; } } public location loc { get { return _generic.loc; } } public override general_node_type general_node_type { get { return TreeRealization.general_node_type.generic_indicator; } } public override semantic_node_type semantic_node_type { get { return semantic_node_type.generic_indicator; } } } public class GenericParameterAbilities { public bool useful_for_pointers = false; public bool useful_for_binary_files = false; public bool useful_for_typed_files = false; } public class generic_method_instance_node : common_method_node, SemanticTree.IGenericFunctionInstance { protected List _instance_params; public List instance_params { get { return _instance_params; } } protected List _generic_parameters = null; public List generic_parameters { get { if (_generic_parameters == null) { _generic_parameters = new List(); foreach (type_node t in _instance_params) { _generic_parameters.Add(t); } } return _generic_parameters; } } protected function_node _original_function; SemanticTree.IFunctionNode SemanticTree.IGenericFunctionInstance.original_function { get { return _original_function; } } public override function_node original_function { get { return _original_function; } } public override bool is_generic_function_instance { get { return true; } } public override SemanticTree.ITypeNode comperehensive_type { get { return (_original_function as SemanticTree.IClassMemberNode).comperehensive_type; } } public generic_method_instance_node(function_node original_generic_function, List instance_parameters) : base( generic_convertions.MakePseudoInstanceName(original_generic_function.name, instance_parameters, false), null, null) { _original_function = original_generic_function; _instance_params = instance_parameters; this.field_access_level = original_generic_function.field_access_level; this.is_final = original_generic_function.is_final; this.is_overload = true; this.polymorphic_state = original_generic_function.polymorphic_state; this.return_value_type = generic_convertions.determine_type(original_generic_function.return_value_type, instance_parameters, true); foreach (parameter par in original_generic_function.parameters) { common_parameter cpar = new common_parameter(par.name, generic_convertions.determine_type(par.type, _instance_params, true), par.parameter_type, this, (par.parameter_type == SemanticTree.parameter_type.var) ? concrete_parameter_type.cpt_var : concrete_parameter_type.cpt_none, par.default_value, null); cpar.inital_value = par.inital_value; cpar.default_value = par.default_value; cpar.intrenal_is_params = par.is_params; cpar.is_ret_value = par.is_ret_value; cpar.is_special_name = par.is_special_name; parameters.AddElement(cpar); } } public override List get_generic_params_list() { return instance_params; } } public class generic_namespace_function_instance_node: common_namespace_function_node, SemanticTree.IGenericFunctionInstance { protected List _instance_params; public List instance_params { get { return _instance_params; } } protected List _generic_parameters = null; public List generic_parameters { get { if (_generic_parameters == null) { _generic_parameters = new List(); foreach (type_node t in _instance_params) { _generic_parameters.Add(t); } } return _generic_parameters; } } protected common_namespace_function_node _original_function; SemanticTree.IFunctionNode SemanticTree.IGenericFunctionInstance.original_function { get { return _original_function; } } public override function_node original_function { get { return _original_function; } } public override bool is_generic_function_instance { get { return true; } } public generic_namespace_function_instance_node(common_namespace_function_node original_generic_function, List instance_parameters) : base( generic_convertions.MakePseudoInstanceName(original_generic_function.name, instance_parameters, false), null, original_generic_function.namespace_node, null) { _original_function = original_generic_function; _instance_params = instance_parameters; this.field_access_level = original_generic_function.field_access_level; this.is_final = original_generic_function.is_final; this.is_overload = true; this.polymorphic_state = original_generic_function.polymorphic_state; this.return_value_type = generic_convertions.determine_type(original_generic_function.return_value_type, instance_parameters, true); foreach (parameter par in original_generic_function.parameters) { common_parameter cpar = new common_parameter(par.name, generic_convertions.determine_type(par.type, _instance_params, true), par.parameter_type, this, (par.parameter_type == SemanticTree.parameter_type.var) ? concrete_parameter_type.cpt_var : concrete_parameter_type.cpt_none, par.default_value, null); cpar.inital_value = par.inital_value; cpar.default_value = par.default_value; cpar.intrenal_is_params = par.is_params; cpar.is_ret_value = par.is_ret_value; cpar.is_special_name = par.is_special_name; parameters.AddElement(cpar); } } public override List get_generic_params_list() { return instance_params; } } public class default_operator_node : expression_node, SemanticTree.IDefaultOperatorNode { public default_operator_node(type_node tn, location loc) : base(tn, loc) { } public override semantic_node_type semantic_node_type { get { return semantic_node_type.default_operator; } } /// /// Метод для обхода дерева посетителем. /// /// Класс - посетитель дерева. public override void visit(SemanticTree.ISemanticVisitor visitor) { visitor.visit(this); } } }