// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (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 bool has_explicit_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( StringConstants.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(StringConstants.default_constructor_name, new SymbolInfo(cnode)); param.has_default_constructor = true; param.has_explicit_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); if (t is common_type_node && (t as common_type_node).has_explicit_default_constructor) gpe.has_explicit_default_ctor = true; 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(pars.Length); foreach (Type t in pars) { generic_parameter_eliminations gpe = new generic_parameter_eliminations(); gpe.has_default_ctor = ((t.GenericParameterAttributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0); if (gpe.has_default_ctor) gpe.has_explicit_default_ctor = true; 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); if (gpe.is_value && gpe.base_class == SystemLibrary.SystemLibrary.value_type) gpe.base_class = SystemLibrary.SystemLibrary.object_type; 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); SystemLibrary.SystemLibrary.syn_visitor.check_using_static_class(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.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); // Если tn не соврадает со своим базовым типом и // tn не наследуется от base_type и // tn - не generic параметр - закомментировал if (base_type != tn && !type_table.is_derived(base_type, tn) /*&& !tn.is_generic_parameter*/) { return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_BE_DERIVED_FROM_{1}", tn.PrintableName, base_type.PrintableName); } } 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 || tn.BaseFullName != null && tn.BaseFullName.StartsWith("System.Nullable")) /*&& !tn.is_generic_parameter*/) { return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_BE_VALUE_TYPE", tn.PrintableName); } 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.PrintableName); } } if (tn.IsStatic) return new SimpleSemanticError(null, "USING_STATIC_CLASS_NOT_VALID"); if (gpe.has_default_ctor) { if (tn.IsAbstract) { return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_NOT_BE_ABSTRACT", tn.PrintableName); } if (tn.IsStatic || !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-типов. //TODO: sdelat singletonom. staticheskie klassy eto gadost 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 Dictionary generic_instances = new Dictionary(); public static syntax_tree_visitor visitor; public static List get_type_instances(type_node original_generic_type) { List instances; if ( generic_instances.TryGetValue(original_generic_type, out var temp) ) instances = (List)temp; else { instances = new List(); generic_instances.Add(original_generic_type, instances); } return instances; } public static void remove_type_instances(type_node original_generic_type) { if (generic_instances.ContainsKey(original_generic_type)) generic_instances.Remove(original_generic_type); } public static List get_function_instances(function_node original_generic_function) { List instances; if ( generic_instances.TryGetValue(original_generic_function, out var temp) ) instances = (List)temp; else { 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 instance_default_property(generic_instance_type_node instance) { var original = instance.original_generic; 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; } } } } public static void init_generic_instance(generic_instance_type_node instance/*, SymbolTable.ClassScope instance_scope*/) { var original = instance.original_generic; var param_types = instance.instance_params; 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); if (btype == null) btype = SystemLibrary.SystemLibrary.object_type; 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(StringConstants.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, List generic_param_types = null) { if (t == null) return null; if (t.IsGenericParameter) { //Если мы определяем тип-параметры метода, нет необходимости рассматривать //тип-параметры типа, и наоборот. Это для поддержки generic-методов в //generic-типе. if (method_param_types == (t.DeclaringMethod != null)) { try { return param_types[t.GenericParameterPosition]; } catch(Exception e) { // e = e; // PVS 01/2022 } } 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, List generic_param_types = null) { 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, generic_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, generic_param_types); if (elem_tp != ii.element_type) { return SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.type_constructor.create_unsized_array(elem_tp, 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) { if (generic_param_types == null) return param_types[comm_type.generic_param_index]; else { // Мы устанавливаем, содержится ли comm_type среди generic_param_types, и если да, то меняем его по этому же алгоритму, а если нет, то ничего не делаем var found = generic_param_types.Contains(comm_type); if (found) 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, generic_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, generic_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, 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, generic_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, generic_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 == null) return false; 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, List generic_params) { var there_are_undeduced_params = false; var param_counter = 0; var visitor = SystemLibrary.SystemLibrary.syn_visitor; var result = true; exception_on_body_compilation = null; int errors_count = visitor.ErrorsList.Count; /*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; }*/ if (lambda_syntax_node.formal_parameters != null) 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, visitor.GeneratedNamesManager); lambda_syntax_node.lambda_name = aux_name; try { visitor.visit(lambda_syntax_node); //пробуем скомпилировать тело лямбды, вычислим тип возвращаемого значения } catch (Exception exc) { if (!there_are_undeduced_params) { 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 (there_are_undeduced_params && visitor.ErrorsList.Count > errors_count) { visitor.ErrorsList.RemoveAt(visitor.ErrorsList.Count - 1); } else { 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, generic_params)) //Выводим дженерик-параметры после того как вычислили тип возвращаемого значения { result = false; } } } } } } return result; } public static function_node DeduceFunction(function_node func, expressions_list fact, bool alone, compilation_context context, 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; List generic_params = func.get_generic_params_list(); 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, generic_params)) { if (alone && fact[i].type is delegated_methods && (fact[i].type as delegated_methods).empty_param_method != null) { if (DeduceInstanceTypes(last_params_type, (fact[i].type as delegated_methods).empty_param_method.type, deduced, nils, generic_params)) continue; } else 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; bool deduce_empty_func_call = false; if (tn is delegated_methods && (tn as delegated_methods).empty_param_method != null && last_params_type.is_generic_parameter) { tn = (tn as delegated_methods).empty_param_method.ret_type; deduce_empty_func_call = true; } 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, generic_params)) { if (deduce_empty_func_call && DeduceInstanceTypes(last_params_type, fact[i].type, deduced, nils, generic_params)) continue; 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(); // SSM 08/07/21 попытаться вывести нефункциональные параметры первыми /*for (int i = 0; i < count_params_to_see; ++i) if (!(fact[i].type is delegated_methods)) { bool b = DeduceInstanceTypes(formal[i].type, fact[i].type, deduced, nils, generic_params); b = b; }*/ 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, generic_params)) continue; else if (!DeduceInstanceTypes(formal[i].type, fact[i].type, deduced, nils, generic_params)) { 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, generic_params)) 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; // Исключение которое может возникнуть в результате компиляции тела лямбды если мы выберем неправильные типы параметров var b = TryToDeduceTypesInLambda(lambda_syntax_node, formal_delegate.Value, deduced, nils, out on_lambda_body_compile_exception, generic_params); if (!b) // Пробуем вычислить типы из лямбд { 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, generic_params)) { //Второй шанс. Учитываем слово 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, generic_params)) { 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, List generic_params) { if (fact_type == null)//issue #347 return false; if (formal_type == null) 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) { // SSM 13/06/20 Если formal_type не входит в generic_params, то вернуть false if (!generic_params.Contains(formal_type)) // SSM 13.06.20 #2067 { return true; // т.е. вывод закончен - нечего выводить } 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; //if (fact_type is delegated_methods) // fact_type = visitor.CreateDelegate((fact_type as delegated_methods).proper_methods[0].simple_function_node); deduced[par_num] = fact_type; return true; } //Этот тип-параметр уже был выведен. Сравниваем с выведенным. if (!convertion_data_and_alghoritms.eq_type_nodes(fact_type, deduced[par_num], true)) { if (fact_type is delegated_methods && deduced[par_num].IsDelegate) { delegate_internal_interface d1 = deduced[par_num].get_internal_interface(internal_interface_kind.delegate_interface) as delegate_internal_interface; return convertion_data_and_alghoritms.function_eq_params_and_result((fact_type as delegated_methods).proper_methods[0].simple_function_node, d1.invoke_method); } else if (fact_type is delegated_methods && deduced[par_num] is delegated_methods) { return convertion_data_and_alghoritms.function_eq_params_and_result((fact_type as delegated_methods).proper_methods[0].simple_function_node, (deduced[par_num] as delegated_methods).proper_methods[0].simple_function_node); } 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, generic_params); } //безразмерные массивы 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, generic_params); } //Множества 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, generic_params); } //Типизированные файлы 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, generic_params); } //Делегаты if (formal_type.IsDelegate) { //Если текущий параметр - лямбда, то просто выводим дженерик-параметры из типов, которые уже известны. Не трогаем lambda_any_type_node. Остальное выведется в цикле выше var lambda_func = fact_type as delegated_methods; // Возвр true не только если fact_type - лямбда, но и если это имя функции 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, generic_params)) //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, generic_params)) // 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; function_node fact_func = null; List fact_funcs = new List(); if (dm != null && dm.proper_methods.Count == 1) { fact_funcs.Add(dm.proper_methods[0].simple_function_node); } else if (fact_type.IsDelegate) { var sil = fact_type.find_in_type("Invoke"); if (sil != null && sil.Count > 0) { fact_funcs.Add(sil[0].sym_info as function_node); } } // SSM 09.07 - My(f: T->T1) при наличии двух f - следующие 2 else дают пропуск этой ошибки!! Она внесена 10.01 в 20:54 при исправлении 1093 // Видимо, это улучшило ситуацию - просто надо точнее отбрасывать часть fact_funcs else if (dm != null && dm.proper_methods.Count > 1 && formal_type.original_generic is compiled_type_node && (formal_type.original_generic as compiled_type_node).compiled_type.FullName.StartsWith("System.Func`")) { var ctn = formal_type.original_generic as compiled_type_node; foreach (var fc in dm.proper_methods) { if (fc.simple_function_node.parameters.Count == formal_type.instance_params.Count - 1) { fact_funcs.Add(fc.simple_function_node); } } } else if (dm != null && dm.proper_methods.Count > 1 && formal_type.original_generic is compiled_type_node && (formal_type.original_generic as compiled_type_node).compiled_type.FullName.StartsWith("System.Action`")) { var ctn = formal_type.original_generic as compiled_type_node; foreach (var fc in dm.proper_methods) { if (fc.simple_function_node.parameters.Count == formal_type.instance_params.Count) { fact_funcs.Add(fc.simple_function_node); } } } // end SSM 09.07 - конец кода, который был написан раньше IB. Здесь поясняется его влияние на ошибки for (int j = 0; j < fact_funcs.Count; j++) { fact_func = fact_funcs[j]; if (fact_func.parameters.Count != dii.parameters.Count) { if (j < fact_funcs.Count - 1) continue; 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) { if (j < fact_funcs.Count - 1) continue; goto eq_cmp; } } bool skip_j = false; // SSM 06/07/21 for (int i = 0; i < param_count; i++) { if (!DeduceInstanceTypes(dii.parameters[i].type, fact_func.parameters[i].type, deduced, nils, generic_params)) // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка { if (j < fact_funcs.Count - 1) { skip_j = true; // SSM 06/07/21 break; //continue; // тут надо завершать итерацию по j, а не по i !!! } goto eq_cmp; } } if (skip_j) // // SSM 06/07/21 пропустить текущую итерацию по j !! continue; 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// { if (j < fact_funcs.Count - 1) continue; 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, generic_params)) // 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 { if (j < fact_funcs.Count - 1) continue; goto eq_cmp; } return true; // SSM 06/07/21 тут сбита логика. Мы рассматриваем получается только первую fact_func[0] и выходим } } 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; type_node base_type = fact_type.base_type; while (base_type != null) { if (base_type.original_generic == formal_type.original_generic) { fact_type_converted = base_type; break; } base_type = base_type.base_type; } if (fact_type.ImplementingInterfaces != null && fact_type_converted == 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) { base_type = fact_type.base_type; while (base_type != null) { if (base_type.ImplementingInterfaces != null) foreach (type_node ti in base_type.ImplementingInterfaces) { if (ti.original_generic == formal_type.original_generic) { fact_type_converted = ti; break; } } if (fact_type_converted != null) break; base_type = base_type.base_type; } } } 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, generic_params)) { 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(StringConstants.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) { if (tn.is_generic_parameter && tn.base_type != null && tn.base_type.IsAbstract && !(tn is common_type_node && (tn as common_type_node).has_default_constructor)) return false; List sil = tn.find_in_type(StringConstants.default_constructor_name, tn.Scope); if (sil != null) { foreach (SymbolInfo si in sil) { 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; } } } } 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; SetImplementingInterfaces(null); } 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; } } public override List ImplementingInterfaces { get { var res = base.ImplementingInterfaces; if (res==null) { res = new List(); foreach (type_node interf in original_generic.ImplementingInterfaces) res.Add(generic_convertions.determine_type(interf, this.instance_params, false)); SetImplementingInterfaces(res); } return res; } } public override List ImplementingInterfacesOrEmpty { get { return base.ImplementingInterfaces ?? new List(); } } /*public override property_node default_property_node { get { if (default_property != null) return default_property; if (original_generic.default_property_node != null) default_property = ConvertMember(original_generic.default_property_node) as common_property_node; return default_property; } }*/ 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) { var cf = original as class_field; #if DEBUG /*if (cf != null && cf.name == "XYZW") { cf = cf; } */ #endif // Этот код дает перекрестные ошибки далее поэтому эта идея неправильна. Комментирую /*if (cf != null) // значит это поле и заменять original на соответствующее поле оригинального класса { var or = this.original_generic as common_type_node; original = or.fields.First(f => f.name == cf.name); if (original==null) { original = original; } } */ if (!_members.ContainsValue(original)) // SSM 30.12.18 bug fix #907 { // Если это поле и T1->Anything, то как-то надо находить оригинальный класс Base и заменять на T->Anything // Вторая версия - делать это в GetMember - там доступны все _members // Закомментировал всё кроме того что было - изменение вместо добавления срабатывает только если мы в предыдущем коде меняли original, а именно эта идея признана ошибочной //if (!_members.ContainsKey(original)) //{ _members.Add(original, converted); _member_definitions.Add(converted, original); //} /*else { _members[original] = converted; _member_definitions[original] = converted; } */ } else // SSM 30.12.18 bug fix #907 { object kk = null; foreach (System.Collections.DictionaryEntry x in _members) { if (x.Value == original) kk = x.Key; } _members[kk] = converted; _member_definitions.Remove(original); _member_definitions[converted] = kk; } } 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; List orig_tpars = 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) { 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) // orig_fn м.б. generic-методом, но и класс м.б.generic!!! Смешение параметров! А у нас либо класс, либо функция { foreach (common_parameter cp in cmn.parameters) { //if (cp.type.PrintableName == "Action" || cp.type.PrintableName == "TSource") { } // ничего не надо делать, поскольку //cp.type = generic_convertions.determine_type(cp.type, _instance_params, false); //else // Action - T м.б. от класса, а T2 - от метода! И надо передавать оба: meth_inst_pars и _instance_params // И индексом м.б. не обойдёшься cp.type = generic_convertions.determine_type(cp.type, meth_inst_pars, true, orig_tpars); } } 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 (common_orig != null) cmn.overrided_method = common_orig.overrided_method; if (orig_fn.is_generic_function) { cmn.return_value_type = generic_convertions.determine_type(cmn.return_value_type, meth_inst_pars, true, orig_tpars); } if (orig_fn is common_function_node) { cmn.return_variable = (orig_fn as common_function_node)?.return_variable; } cmn.IsOperator = orig_fn.IsOperator; if (orig_fn is compiled_function_node) { compiled_function_node fn_orig = orig_fn as compiled_function_node; if (fn_orig.method_info.GetBaseDefinition() != null) cmn.overrided_method = compiled_function_node.get_compiled_method(fn_orig.method_info.GetBaseDefinition()); } return cmn; } public override bool IsAbstract { get { return original_generic.IsAbstract; } } 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_event make_event(event_node orig_event, location loc) { common_event cme = orig_event as common_event; compiled_event ce = orig_event as compiled_event; if (_members[orig_event.add_method] == null) ConvertMember(orig_event.add_method); if (_members[orig_event.remove_method] == null) ConvertMember(orig_event.remove_method); if (orig_event.raise_method != null && _members[orig_event.raise_method] == null) ConvertMember(orig_event.raise_method); common_event evnt = new common_event(orig_event.name, generic_convertions.determine_type( orig_event.delegate_type, _instance_params, false), this, _members[orig_event.add_method] as common_method_node, _members[orig_event.remove_method] as common_method_node, orig_event.raise_method != null ? _members[orig_event.raise_method] as common_method_node : null, cme != null ? cme.field_access_level : SemanticTree.field_access_level.fal_public, orig_event.is_static ? SemanticTree.polymorphic_state.ps_static : SemanticTree.polymorphic_state.ps_common, loc ); if (orig_event is common_event commonEvent) { evnt.field = (class_field)ConvertMember(commonEvent.field); } return evnt; } 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) && this.BaseFullName == "PABCSystem.NewSet`1" && orig_node is compiled_function_node cfn2 && cfn2.name == "op_Equality") { rez_node = null; _members.Remove(orig_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); //!!! прикольно, но индексы в meths и instmeths не совпадают!!! MethodInfo[] instmeths = ((compiled_type_node)inst_type)._compiled_type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); //var mt1 = meths.Select(m => m.MetadataToken).OrderBy(x => x); //var mt2 = instmeths.Select(m => m.MetadataToken).OrderBy(x => x); MethodInfo mi = instmeths[num];*/ // SSM 2018.05.05 bug fix #664 var mdtok = cfn.method_info.MetadataToken; MethodInfo[] instmeths = ((compiled_type_node)inst_type)._compiled_type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); MethodInfo mi = System.Array.Find(instmeths, m => m.MetadataToken == mdtok); // SSM 2018.05.05 end bug fix #664 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) { /* // SSM 29/04/18 - проба - как достать IndexOf из MyList - наследника List // Это поздно - надо как-то раньше if (tn is compiled_type_node) tn = generic_convertions.determine_type((tn as compiled_type_node).compiled_type, instance_params,false); var tn1 = tn as compiled_type_node; var ff = tn1.find_in_type("IndexOf");*/ generic_instance_type_node compr_type = find_instance_type_from(tn); // #1647 tn = IEnumerable if (compr_type == null) { compiled_type_node bbt = null; // SSM 14/06/20 - это для #1647 IGrouping: IEnumerable foreach (type_node tn1 in ImplementingInterfaces) { var bt = tn1 as compiled_type_node; if (bt != null && bt.original_generic == tn) { bbt = bt; // #1647 bbt = IEnumerable break; } } compiled_function_node cfn = orig_node as compiled_function_node; // #1647 orig_node = cfn = IEnumerator GetEnumerator() if (cfn == null) { return orig_node; } compiled_type_node cct = tn as compiled_type_node; // cct = IEnumerable if (bbt != null) // #1647 cct = orig_member.comperehensive_type as compiled_type_node; type_node inst_type = this; // До этого цикла проверить bbt - если оно не null, то в роли inst_type как раз и надо брать bbt!!! if (bbt == null) 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)); else inst_type = bbt; // #1647 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) Не знаю, что тут делать event_node orig_event = (event_node)orig_node; rez_node = make_event(orig_event, loc); break; default: throw new CompilerInternalError("Unexpected definition_node."); } /*if (orig_node is class_field cf) { if (cf.type.name == "T1") orig_node = orig_node; else AddMember(orig_node, rez_node); } else*/ AddMember(orig_node, rez_node); } return rez_node; } public List ConvertSymbolInfo(List start) { List rez_start = null; SymbolInfo rez_si = null; if (start != null) { foreach (SymbolInfo si in start) { if (si.sym_info == null) { if (rez_start == null) rez_start = new List(); rez_start.Add(si); continue; } // Бурмистров Артем 13.06.19 begin // Поправил странное поведение для локальных переменных, у которых не generic тип // Исправление для #1993 if (si.sym_info is /*var_definition_node*/ local_block_variable vdn && !vdn.type.is_generic_parameter) { rez_si = si; } else { definition_node dnode = ConvertMember(si.sym_info); rez_si = new SymbolInfo(dnode, si.access_level, si.symbol_kind); rez_si.scope = si.scope; } // aab 13.06.19 end //Дополняем список SymbolInfo преобразованным значением if (rez_start == null) { rez_start = new List(); rez_start.Add(rez_si); } else { rez_start.Add(rez_si); } } } return rez_start; } public override List find(string name, bool no_search_in_extension_methods = false) { List si = _original_generic.find(name); return ConvertSymbolInfo(si);//delete } public override List find_in_type(string name, bool no_search_in_extension_methods = false) { List sil = _original_generic.find_in_type(name); sil = ConvertSymbolInfo(sil); return sil; } public override List find_in_type(string name, SymbolTable.Scope CurrentScope, type_node orig_generic_or_null = null, bool no_search_in_extension_methods = false) { //var or = generic_convertions.determine_type(_original_generic,this.instance_params,false); // циклится List sil = null; /*var ctn = base_type as compiled_type_node; if (ctn != null && ctn.is_generic_type_instance) { sil = ctn.find_in_type(name, CurrentScope, no_search_in_extension_methods); var sil1 = _original_generic.find_in_type(name, CurrentScope); sil1 = ConvertSymbolInfo(sil1); if (sil!=null) sil1.InsertRange(0,sil); return sil1; }*/ #if DEBUG /*if (name == "XYZW") { var y = name; } */ #endif sil = _original_generic.find_in_type(name, CurrentScope, _original_generic); // передача _original_generic - это костыль для устранения бага #1674. // параметр _original_generic - фиктивный: если он не null (это только здесь), то в common_type_node выполнение в одном месте идет по другой ветке sil = ConvertSymbolInfo(sil); return sil; } private void conform_basic_function(string name, int base_func_num) { SymbolInfo si1 = null; List sil = _original_generic.find_in_type(name, true); foreach (SymbolInfo si in sil) if (si.sym_info is function_node && !(si.sym_info as function_node).is_extension_method) { si1 = si; break; } AddMember(si1.sym_info, temp_names[base_func_num].sym_info); } public void conform_basic_functions() { // Вообще говоря, надо эти операции добавлять только если пользовательские не определены if (BaseFullName != "PABCSystem.NewSet`1") // SSM 19/11/24 - для типа встроенных множеств где эти операции переопределены { conform_basic_function(StringConstants.assign_name, 0); conform_basic_function(StringConstants.eq_name, 1); conform_basic_function(StringConstants.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_extension_method { get { return _original_function.is_extension_method; } } 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; List orig_gen_params = original_generic_function.get_generic_params_list(); // #2068 попытка 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, orig_gen_params); 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, orig_gen_params), 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; List orig_gen_params = original_generic_function.generic_params.Select(p => p as type_node).ToList(); // #2068 попытка 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, orig_gen_params); 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, orig_gen_params), par.parameter_type, this, (par.parameter_type == SemanticTree.parameter_type.var) ? concrete_parameter_type.cpt_var : concrete_parameter_type.cpt_none, par.default_value?.ShallowCopy(), null); cpar.inital_value = par.inital_value; if (cpar.default_value is default_operator_node) (cpar.default_value as default_operator_node).type = generic_convertions.determine_type(cpar.default_value.type, _instance_params, true, orig_gen_params); else if (cpar.default_value is default_operator_node_as_constant def_oper_as_constant) { def_oper_as_constant.type = generic_convertions.determine_type(cpar.default_value.type, _instance_params, true, orig_gen_params); def_oper_as_constant.default_operator = (default_operator_node)def_oper_as_constant.default_operator.ShallowCopy(); // ShallowCopy здесь и выше, чтобы не портить исходный тип шаблона EVA 26.03.2026 def_oper_as_constant.default_operator.type = def_oper_as_constant.type; } 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); } } }