pascalabcnet/TreeConverter/TreeRealization/generics.cs

2731 lines
130 KiB
C#
Raw Normal View History

2024-06-23 00:02:30 +03:00
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
2019-06-16 23:44:32 +03:00
// 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<type_node> param_types;
public generic_instance_type_node pseudo_instance;
public generic_type_instance_info(List<type_node> _param_types, generic_instance_type_node _pseudo_instance)
{
param_types = _param_types;
pseudo_instance = _pseudo_instance;
}
}
public class generic_function_instance_info
{
public List<type_node> param_types;
public function_node pseudo_instance;
public generic_function_instance_info(List<type_node> _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;
2021-01-31 14:08:33 +03:00
public bool has_explicit_default_ctor = false;
2019-06-16 23:44:32 +03:00
public type_node base_class = null;
public List<type_node> 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,
2019-06-16 23:44:32 +03:00
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));
2019-06-16 23:44:32 +03:00
param.has_default_constructor = true;
2021-01-31 14:08:33 +03:00
param.has_explicit_default_constructor = true;
2019-06-16 23:44:32 +03:00
}
public static List<generic_parameter_eliminations> make_eliminations_common(List<SemanticTree.ICommonTypeNode> generic_params)
{
List<generic_parameter_eliminations> _parameters_eliminations = new List<generic_parameter_eliminations>();
foreach (type_node t in generic_params)
{
generic_parameter_eliminations gpe = new generic_parameter_eliminations();
2023-05-14 12:36:08 +03:00
2019-06-16 23:44:32 +03:00
gpe.has_default_ctor = generic_convertions.type_has_default_ctor(t, false);
2021-01-31 14:08:33 +03:00
if (t is common_type_node && (t as common_type_node).has_explicit_default_constructor)
gpe.has_explicit_default_ctor = true;
2019-06-16 23:44:32 +03:00
gpe.is_class = t.is_class;
gpe.is_value = t.is_value;
gpe.base_class = t.base_type;
gpe.implementing_interfaces = new List<type_node>(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<generic_parameter_eliminations> make_eliminations_compiled(Type[] pars)
{
2022-09-26 14:25:15 +03:00
List<generic_parameter_eliminations> _parameters_eliminations = new List<generic_parameter_eliminations>(pars.Length);
2019-06-16 23:44:32 +03:00
foreach (Type t in pars)
{
generic_parameter_eliminations gpe = new generic_parameter_eliminations();
2022-09-26 14:25:15 +03:00
2019-06-16 23:44:32 +03:00
gpe.has_default_ctor =
((t.GenericParameterAttributes &
GenericParameterAttributes.DefaultConstructorConstraint) != 0);
2021-01-31 14:08:33 +03:00
if (gpe.has_default_ctor)
gpe.has_explicit_default_ctor = true;
2022-09-26 14:25:15 +03:00
2019-06-16 23:44:32 +03:00
gpe.is_class =
((t.GenericParameterAttributes &
GenericParameterAttributes.ReferenceTypeConstraint) != 0);
gpe.is_value =
((t.GenericParameterAttributes &
GenericParameterAttributes.NotNullableValueTypeConstraint) != 0);
2022-09-26 14:25:15 +03:00
2019-06-16 23:44:32 +03:00
gpe.base_class = compiled_type_node.get_type_node(t.BaseType);
2022-09-26 14:25:15 +03:00
if (gpe.is_value && gpe.base_class == SystemLibrary.SystemLibrary.value_type)
gpe.base_class = SystemLibrary.SystemLibrary.object_type;
2019-06-16 23:44:32 +03:00
Type[] net_interf = t.GetInterfaces();
gpe.implementing_interfaces = new List<type_node>(net_interf.Length);
foreach (Type net_t in net_interf)
{
gpe.implementing_interfaces.Add(compiled_type_node.get_type_node(net_t));
}
2022-09-26 14:25:15 +03:00
2019-06-16 23:44:32 +03:00
_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<type_node> tparams, List<generic_parameter_eliminations> gpe_list, bool method_param_types, out int i)
{
int count = tparams.Count;
2019-10-04 14:37:47 +03:00
2019-06-16 23:44:32 +03:00
for (i = 0; i < count; i++)
{
generic_parameter_eliminations gpe = gpe_list[i];
type_node tn = tparams[i];
2019-10-04 14:37:47 +03:00
2022-09-26 14:25:15 +03:00
if (gpe.base_class != null && gpe.base_class != SystemLibrary.SystemLibrary.object_type)
2019-06-16 23:44:32 +03:00
{
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*/)
2019-06-16 23:44:32 +03:00
{
2022-09-27 18:29:49 +03:00
return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_BE_DERIVED_FROM_{1}", tn.PrintableName, base_type.PrintableName);
2019-06-16 23:44:32 +03:00
}
}
2022-03-20 19:01:03 +03:00
if (gpe.is_class && !tn.is_class)
2022-03-20 00:08:57 +03:00
{
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);
}
2019-06-16 23:44:32 +03:00
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)))
{
2022-09-27 18:29:49 +03:00
return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_IMPLEMENT_INTERFACE_{1}", tn.PrintableName, di.PrintableName);
2019-06-16 23:44:32 +03:00
}
}
if (tn.IsStatic)
return new SimpleSemanticError(null, "USING_STATIC_CLASS_NOT_VALID");
if (gpe.has_default_ctor)
{
2020-07-09 21:36:29 +03:00
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))
2019-06-16 23:44:32 +03:00
{
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<SemanticTree.IGenericTypeInstance> all_type_instances =
new List<SemanticTree.IGenericTypeInstance>();
public static List<SemanticTree.IGenericFunctionInstance> all_function_instances =
new List<SemanticTree.IGenericFunctionInstance>();
2026-06-13 09:40:55 +03:00
public static Dictionary<definition_node, object> generic_instances =
new Dictionary<definition_node, object>();
2019-06-16 23:44:32 +03:00
public static syntax_tree_visitor visitor;
public static List<generic_type_instance_info> get_type_instances(type_node original_generic_type)
{
2026-06-13 09:40:55 +03:00
List<generic_type_instance_info> instances;
if ( generic_instances.TryGetValue(original_generic_type, out var temp) )
instances = (List<generic_type_instance_info>)temp;
else
2019-06-16 23:44:32 +03:00
{
instances = new List<generic_type_instance_info>();
generic_instances.Add(original_generic_type, instances);
}
return instances;
}
2021-11-07 12:14:35 +03:00
public static void remove_type_instances(type_node original_generic_type)
{
2026-06-13 09:40:55 +03:00
if (generic_instances.ContainsKey(original_generic_type))
2021-11-07 12:14:35 +03:00
generic_instances.Remove(original_generic_type);
}
2019-06-16 23:44:32 +03:00
public static List<generic_function_instance_info> get_function_instances(function_node original_generic_function)
{
2026-06-13 09:40:55 +03:00
List<generic_function_instance_info> instances;
if ( generic_instances.TryGetValue(original_generic_function, out var temp) )
instances = (List<generic_function_instance_info>)temp;
else
2019-06-16 23:44:32 +03:00
{
instances = new List<generic_function_instance_info>();
generic_instances.Add(original_generic_function, instances);
}
return instances;
}
public static type_node find_type_instance(List<generic_type_instance_info> _generic_instances, List<type_node> 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<type_instance_and_location> insts)
{
int num;
foreach (type_instance_and_location tia in insts)
{
List<generic_parameter_eliminations> 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_function_instance_info> _generic_instances, List<type_node> 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;
}
2023-07-02 22:22:49 +03:00
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*/)
2019-06-16 23:44:32 +03:00
{
var original = instance.original_generic;
var param_types = instance.instance_params;
2019-06-16 23:44:32 +03:00
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);
2021-01-02 15:22:21 +03:00
if (btype == null)
btype = SystemLibrary.SystemLibrary.object_type;
2019-06-16 23:44:32 +03:00
instance.SetBaseTypeIgnoringScope(btype);
//instance._scope = new SymbolTable.GenericTypeInstanceScope(instance, instance.original_generic.Scope, btype.Scope);
// Создаются лениво
/**
2019-06-16 23:44:32 +03:00
foreach (type_node interf in original.ImplementingInterfaces)
{
instance.ImplementingInterfaces.Add(
determine_type(interf, param_types, false)
);
}
/**/
2019-06-16 23:44:32 +03:00
SystemLibrary.SystemLibrary.init_reference_type(instance);
instance.conform_basic_functions();
//(ssyy) Нужно, чтобы добавились конструкторы
//ctnode.find_in_type(StringConstants.default_constructor_name);
2019-06-16 23:44:32 +03:00
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<ienumerable_auto_type>, т.к. потом они всё равно автовыводятся
{
//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();
}
//Определяет, как должен выглядеть тип в семантическом дереве.
//Возвращает этот тип.
2020-06-12 16:38:46 +03:00
public static type_node determine_type(Type t, List<type_node> param_types, bool method_param_types, List<type_node> generic_param_types = null)
2019-06-16 23:44:32 +03:00
{
if (t == null) return null;
if (t.IsGenericParameter)
{
//Если мы определяем тип-параметры метода, нет необходимости рассматривать
//тип-параметры типа, и наоборот. Это для поддержки generic-методов в
//generic-типе.
if (method_param_types == (t.DeclaringMethod != null))
{
2020-02-07 09:31:40 +03:00
try
{
return param_types[t.GenericParameterPosition];
}
catch(Exception e)
{
// e = e; // PVS 01/2022
2020-02-07 09:31:40 +03:00
}
2019-06-16 23:44:32 +03:00
}
else
{
return compiled_type_node.get_type_node(t);
}
}
if (t.IsGenericType)
{
//Формируем список типов-параметров
Type[] args = t.GetGenericArguments();
List<type_node> semantic_args = new List<type_node>();
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);
}
2020-06-12 16:38:46 +03:00
public static type_node determine_type(type_node tn, List<type_node> param_types, bool method_param_types, List<type_node> generic_param_types = null)
2019-06-16 23:44:32 +03:00
{
if (tn == null) return null;
ref_type_node rtn = tn as ref_type_node;
if (rtn != null)
{
2020-06-12 16:38:46 +03:00
type_node ptype = generic_convertions.determine_type(rtn.pointed_type, param_types, method_param_types, generic_param_types);
2019-06-16 23:44:32 +03:00
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)
{
2020-06-12 16:38:46 +03:00
type_node elem_tp = determine_type(ii.element_type, param_types, method_param_types, generic_param_types);
2019-06-16 23:44:32 +03:00
if (elem_tp != ii.element_type)
{
2024-06-23 00:02:30 +03:00
return SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.type_constructor.create_unsized_array(elem_tp, ii.rank, null);
2019-06-16 23:44:32 +03:00
}
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)
2019-06-16 23:44:32 +03:00
{
2020-06-12 16:38:46 +03:00
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];
}
2019-06-16 23:44:32 +03:00
}
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<type_node> semantic_args = new List<type_node>();
List<type_node> gitn_inst_parameters = gitn.instance_params;
foreach (type_node arg in gitn_inst_parameters)
{
2020-06-12 16:38:46 +03:00
semantic_args.Add(determine_type(arg, param_types, method_param_types, generic_param_types));
2019-06-16 23:44:32 +03:00
}
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)
{
2020-06-12 16:38:46 +03:00
type_node elem_tp = determine_type(comm_type.element_type, param_types, method_param_types, generic_param_types);
2019-06-16 23:44:32 +03:00
if (elem_tp != comm_type.element_type)
{
2024-06-23 00:02:30 +03:00
return SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.type_constructor.create_unsized_array(elem_tp, 1, comm_type.loc);
2019-06-16 23:44:32 +03:00
}
return tn;
}
if (comm_type.type_special_kind == SemanticTree.type_special_kind.set_type)
{
2020-06-12 16:38:46 +03:00
type_node elem_tp = determine_type(comm_type.element_type, param_types, method_param_types, generic_param_types);
2019-06-16 23:44:32 +03:00
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)
{
2020-06-12 16:38:46 +03:00
type_node elem_tp = determine_type(comm_type.element_type, param_types, method_param_types, generic_param_types);
2019-06-16 23:44:32 +03:00
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
{
2024-01-14 14:28:36 +03:00
if (formalType == null)
return false;
2019-06-16 23:44:32 +03:00
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<string, Tuple<List<type_node>, type_node>> SaveLambdasStates(IEnumerable<function_lambda_definition> lambdaParametersList)
{
var savedLambdasStates = new Dictionary<string, Tuple<List<type_node>, type_node>>();
foreach (var lambda in lambdaParametersList)
{
var parsTypes = new List<type_node>();
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<List<type_node>, type_node>(parsTypes, retType));
}
return savedLambdasStates;
}
//Восстановление типов в исходное состояние на случай подстановки других типов
private static void RestoreLambdasStates(List<function_lambda_definition> lambdaParametersList,
Dictionary<string, Tuple<List<type_node>, 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<int> nils,
2020-06-13 15:35:47 +03:00
out Exception exception_on_body_compilation, List<type_node> generic_params)
2019-06-16 23:44:32 +03:00
{
var there_are_undeduced_params = false;
var param_counter = 0;
var visitor = SystemLibrary.SystemLibrary.syn_visitor;
var result = true;
exception_on_body_compilation = null;
2021-01-14 23:04:51 +03:00
int errors_count = visitor.ErrorsList.Count;
2019-06-16 23:44:32 +03:00
/*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
{
2021-01-14 22:28:51 +03:00
there_are_undeduced_params = true; //иначе мы не сможем вывести тип возвращаемого значения
2019-06-16 23:44:32 +03:00
break;
}
}
param_counter += t.idents.idents.Count;
}
2021-01-14 22:28:51 +03:00
if (/*!there_are_undeduced_params
&& */lambda_syntax_node.return_type is lambda_inferred_type
2019-06-16 23:44:32 +03:00
&& ((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);
2019-06-16 23:44:32 +03:00
lambda_syntax_node.lambda_name = aux_name;
try
{
visitor.visit(lambda_syntax_node); //пробуем скомпилировать тело лямбды, вычислим тип возвращаемого значения
}
catch (Exception exc)
{
2021-01-14 22:28:51 +03:00
if (!there_are_undeduced_params)
{
exception_on_body_compilation = exc; // Если произошло исключение то запишем его в выходной параметр, оно потом будет обработано вызывающим методом
result = false;
}
2019-06-16 23:44:32 +03:00
}
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)
{
2021-01-14 23:04:51 +03:00
if (there_are_undeduced_params && visitor.ErrorsList.Count > errors_count)
2019-06-16 23:44:32 +03:00
{
2021-01-14 23:04:51 +03:00
visitor.ErrorsList.RemoveAt(visitor.ErrorsList.Count - 1);
2019-06-16 23:44:32 +03:00
}
else
2021-01-14 23:04:51 +03:00
{
if (formal_delegate == null) // SSM 5.12.15
2019-06-16 23:44:32 +03:00
{
result = false;
}
2021-01-14 23:04:51 +03:00
else
2019-06-16 23:44:32 +03:00
{
2021-01-14 23:04:51 +03:00
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;
}
2019-06-16 23:44:32 +03:00
}
}
2021-01-14 23:04:51 +03:00
2019-06-16 23:44:32 +03:00
}
}
}
return result;
}
public static function_node DeduceFunction(function_node func, expressions_list fact, bool alone, compilation_context context, location loc, List<SyntaxTree.expression> syntax_nodes_parameters = null)
{
parameter_list formal = func.parameters;
int formal_count = formal.Count;
int fact_count = fact.Count;
int generic_type_params_count = func.generic_parameters_count;
2020-06-13 15:35:47 +03:00
List<type_node> generic_params = func.get_generic_params_list();
2019-06-16 23:44:32 +03:00
type_node[] deduced = new type_node[generic_type_params_count];
List<int> nils = new List<int>();
int count_params_to_see = fact_count;
var lambda_syntax_nodes = new Dictionary<string, function_lambda_definition>(); //lroman Получим список фактических параметров-лямбд текущей вызываемой подпрограммы
if (syntax_nodes_parameters != null
&& syntax_nodes_parameters.Count > 0) //lroman
{
lambda_syntax_nodes = syntax_nodes_parameters
.OfType<function_lambda_definition>()
.ToDictionary(f => f.lambda_name, f => f);
}
var lambda_in_parameters = lambda_syntax_nodes.Count > 0;
var saved_lambdas_states = SaveLambdasStates(lambda_syntax_nodes.Select(ld => ld.Value)); // Сохраним типы лямбды перед вычислениями
if (fact_count < formal_count)
{
//Сравниваем количества параметров
parameter par = formal[fact_count];
if (par.default_value == null && !par.is_params)
{
if (alone)
throw new NoFunctionWithSameParametresNum(loc, alone, func);
return null;
}
}
else
{
type_node last_params_type = null;
bool last_is_params = false;
parameter par = null;
if (formal_count > 0)
{
par = formal[formal_count - 1];
last_is_params = par.is_params;
}
if (last_is_params)
{
array_internal_interface aii = par.type.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface;
last_params_type = aii.element_type;
}
if (fact_count > formal_count)
{
//Фактических больше, чем формальных. Последний формальный должен быть params...
if (last_is_params)
{
for (int i = formal_count - 1; i < fact_count; ++i)
{
//Проверяем фактические, попадающие под params...
2020-06-13 15:35:47 +03:00
if (!DeduceInstanceTypes(last_params_type, fact[i].type, deduced, nils, generic_params))
2019-06-16 23:44:32 +03:00
{
if (alone && fact[i].type is delegated_methods && (fact[i].type as delegated_methods).empty_param_method != null)
{
2020-06-13 15:35:47 +03:00
if (DeduceInstanceTypes(last_params_type, (fact[i].type as delegated_methods).empty_param_method.type, deduced, nils, generic_params))
2019-06-16 23:44:32 +03:00
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;
2021-12-14 22:42:39 +03:00
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;
}
2019-06-16 23:44:32 +03:00
if (tn.element_type != null && tn.type_special_kind != SemanticTree.type_special_kind.array_wrapper)
tn = tn.element_type;
2021-12-14 22:42:39 +03:00
2020-06-13 15:35:47 +03:00
if (!DeduceInstanceTypes(last_params_type, tn, deduced, nils, generic_params))
2019-06-16 23:44:32 +03:00
{
2021-12-14 22:42:39 +03:00
if (deduce_empty_func_call && DeduceInstanceTypes(last_params_type, fact[i].type, deduced, nils, generic_params))
continue;
2019-06-16 23:44:32 +03:00
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<string, delegate_internal_interface> formal_delegates = null;
while (continue_trying_to_infer_types) //Продолжаем пытаться вычислить типы до тех пор пока состояние о выведенных типах не будет отличаться от состояния на предыдущей итерации
{
var previous_deduce_state = deduced // Текущее состояние выведенных на данный момент типов. Простой список индексов с уже выведенными типами из массива deduced
.Select((t, i) => new { Type = t, Index = i })
.Where(t => t.Type != null)
.Select(t => t.Index)
.ToArray();
2021-07-10 10:45:02 +03:00
// 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;
}*/
2019-06-16 23:44:32 +03:00
for (int i = 0; i < count_params_to_see; ++i)
{
2020-06-13 15:35:47 +03:00
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))
2019-06-16 23:44:32 +03:00
continue;
else
2020-06-13 15:35:47 +03:00
if (!DeduceInstanceTypes(formal[i].type, fact[i].type, deduced, nils, generic_params))
2019-06-16 23:44:32 +03:00
{
if (alone && fact[i].type is delegated_methods && (fact[i].type as delegated_methods).empty_param_method != null)
{
2020-06-13 15:35:47 +03:00
if (DeduceInstanceTypes(formal[i].type, (fact[i].type as delegated_methods).empty_param_method.type, deduced, nils, generic_params))
2019-06-16 23:44:32 +03:00
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<string, delegate_internal_interface>();
for (int i = 0; i < count_params_to_see; ++i)
//Выделим из формальных параметров те, которые соотвтествуют фактическим параметрам-лямбдам
{
var lambda_func = fact[i].type as delegated_methods;
if (lambda_func != null
&& lambda_func.proper_methods.Count == 1
&& LambdaHelper.IsLambdaName(lambda_func.proper_methods[0].simple_function_node.name))
{
formal_delegates.Add(LambdaHelper.GetLambdaNamePartWithoutGenerics(lambda_func.proper_methods[0].simple_function_node.name),
formal[i].type.get_internal_interface(
internal_interface_kind.delegate_interface) as
delegate_internal_interface);
}
}
}
foreach (var formal_delegate in formal_delegates)
// Перебираем все полученные формальные параметры, соответствующие фактическим лямбдам
{
var lambda_syntax_node = lambda_syntax_nodes[formal_delegate.Key];
Exception on_lambda_body_compile_exception;
// Исключение которое может возникнуть в результате компиляции тела лямбды если мы выберем неправильные типы параметров
var b = TryToDeduceTypesInLambda(lambda_syntax_node, formal_delegate.Value, deduced, nils,
2020-06-13 15:35:47 +03:00
out on_lambda_body_compile_exception, generic_params);
2019-06-16 23:44:32 +03:00
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<int> tmp_nils = new List<int>();
tmp_nils.AddRange(nils);
2020-06-13 15:35:47 +03:00
if (!DeduceInstanceTypes(formal[count_params_to_see].type, fact[count_params_to_see].type, deduced, nils, generic_params))
2019-06-16 23:44:32 +03:00
{
//Второй шанс. Учитываем слово params.
deduced = tmp_deduced;
nils = tmp_nils;
2020-06-13 15:35:47 +03:00
if (!DeduceInstanceTypes(formal[count_params_to_see].type.element_type, fact[count_params_to_see].type, deduced, nils, generic_params))
2019-06-16 23:44:32 +03:00
{
if (alone)
throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name);
return null;
}
}
}
//Вывели всё, что могли. Теперь проверяем.
for (int i = 0; i < generic_type_params_count; ++i)
{
if (deduced[i] == null)
{
if (alone)
throw new SimpleSemanticError(loc, "CAN_NOT_DEDUCE_TYPE_PARAMS_FROM_CALL_{0}", func.name);
return null;
}
}
foreach (int num in nils)
{
if (!type_table.is_with_nil_allowed(deduced[num]))
{
if (alone)
throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name);
return null;
}
}
foreach (type_node tt in deduced)
{
CompilationErrorWithLocation check_err = generic_parameter_eliminations.check_type_generic_useful(tt, loc);
if (check_err != null)
{
if (alone)
throw check_err;
return null;
}
}
//Итак, вывели все параметры. Теперь инстанцируем.
List<type_node> deduced_list = new List<type_node>(generic_type_params_count);
deduced_list.AddRange(deduced);
return func.get_instance(deduced_list, alone, loc);
}
//Выведение типов
2020-06-13 15:35:47 +03:00
public static bool DeduceInstanceTypes(type_node formal_type, type_node fact_type, type_node[] deduced, List<int> nils, List<type_node> generic_params)
2019-06-16 23:44:32 +03:00
{
if (fact_type == null)//issue #347
return false;
2022-04-03 14:41:13 +03:00
if (formal_type == null)
return false;
2019-06-16 23:44:32 +03:00
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)
{
2020-06-13 15:35:47 +03:00
// SSM 13/06/20 Если formal_type не входит в generic_params, то вернуть false
if (!generic_params.Contains(formal_type)) // SSM 13.06.20 #2067
{
return true; // т.е. вывод закончен - нечего выводить
}
2019-06-16 23:44:32 +03:00
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;
}
2020-06-13 15:35:47 +03:00
return DeduceInstanceTypes(formal_ref.pointed_type, fact_ref.pointed_type, deduced, nils, generic_params);
2019-06-16 23:44:32 +03:00
}
//безразмерные массивы
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;
}
2020-06-13 15:35:47 +03:00
return DeduceInstanceTypes(formal_ii.element_type, fact_ii.element_type, deduced, nils, generic_params);
2019-06-16 23:44:32 +03:00
}
2020-06-13 15:35:47 +03:00
//Множества
2019-06-16 23:44:32 +03:00
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;
}
2020-06-13 15:35:47 +03:00
return DeduceInstanceTypes(formal_type.element_type, fact_type.element_type, deduced, nils, generic_params);
2019-06-16 23:44:32 +03:00
}
2020-06-13 15:35:47 +03:00
//Типизированные файлы
2019-06-16 23:44:32 +03:00
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;
}
2020-06-13 15:35:47 +03:00
return DeduceInstanceTypes(formal_type.element_type, fact_type.element_type, deduced, nils, generic_params);
2019-06-16 23:44:32 +03:00
}
//Делегаты
if (formal_type.IsDelegate)
{
//Если текущий параметр - лямбда, то просто выводим дженерик-параметры из типов, которые уже известны. Не трогаем lambda_any_type_node. Остальное выведется в цикле выше
2021-07-06 16:28:02 +03:00
var lambda_func = fact_type as delegated_methods; // Возвр true не только если fact_type - лямбда, но и если это имя функции
2021-03-21 13:24:27 +03:00
if (lambda_func != null
&& lambda_func.proper_methods.Count == 1
2019-06-16 23:44:32 +03:00
&& 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 параметра - видимо, была ошибка
2020-06-13 15:35:47 +03:00
if (!DeduceInstanceTypes(dii.parameters[i].type, fact_func.parameters[i].type, deduced, nils, generic_params))
2019-06-16 23:44:32 +03:00
//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 параметра - видимо, была ошибка
2020-06-13 15:35:47 +03:00
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<TResult>
2021-03-21 13:24:27 +03:00
// 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<TResult>
2019-06-16 23:44:32 +03:00
{
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;
2021-03-21 13:24:27 +03:00
List<function_node> fact_funcs = new List<function_node>();
2019-06-16 23:44:32 +03:00
if (dm != null && dm.proper_methods.Count == 1)
2021-03-21 13:24:27 +03:00
{
fact_funcs.Add(dm.proper_methods[0].simple_function_node);
}
2019-06-16 23:44:32 +03:00
else if (fact_type.IsDelegate)
{
var sil = fact_type.find_in_type("Invoke");
if (sil != null && sil.Count > 0)
2021-03-21 13:24:27 +03:00
{
fact_funcs.Add(sil[0].sym_info as function_node);
}
2019-06-16 23:44:32 +03:00
}
2021-07-10 10:45:02 +03:00
// SSM 09.07 - My(f: T->T1) при наличии двух f - следующие 2 else дают пропуск этой ошибки!! Она внесена 10.01 в 20:54 при исправлении 1093
// Видимо, это улучшило ситуацию - просто надо точнее отбрасывать часть fact_funcs
2021-01-10 20:54:40 +03:00
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)
{
2021-03-21 13:24:27 +03:00
fact_funcs.Add(fc.simple_function_node);
2021-01-10 20:54:40 +03:00
}
}
}
2021-03-21 13:24:27 +03:00
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);
}
}
2021-07-10 10:45:02 +03:00
}
// end SSM 09.07 - конец кода, который был написан раньше IB. Здесь поясняется его влияние на ошибки
2021-03-21 13:24:27 +03:00
for (int j = 0; j < fact_funcs.Count; j++)
2019-06-16 23:44:32 +03:00
{
2021-03-21 13:24:27 +03:00
fact_func = fact_funcs[j];
2019-06-16 23:44:32 +03:00
if (fact_func.parameters.Count != dii.parameters.Count)
{
2021-03-21 13:24:27 +03:00
if (j < fact_funcs.Count - 1)
continue;
2019-06-16 23:44:32 +03:00
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)
2021-03-21 13:24:27 +03:00
{
if (j < fact_funcs.Count - 1)
continue;
2019-06-16 23:44:32 +03:00
goto eq_cmp;
2021-03-21 13:24:27 +03:00
}
2019-06-16 23:44:32 +03:00
}
2021-07-06 16:28:02 +03:00
bool skip_j = false; // SSM 06/07/21
2019-06-16 23:44:32 +03:00
for (int i = 0; i < param_count; i++)
{
2020-06-13 15:35:47 +03:00
if (!DeduceInstanceTypes(dii.parameters[i].type, fact_func.parameters[i].type, deduced, nils, generic_params)) // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка
2019-06-16 23:44:32 +03:00
{
2021-03-21 13:24:27 +03:00
if (j < fact_funcs.Count - 1)
2021-07-06 16:28:02 +03:00
{
skip_j = true; // SSM 06/07/21
break;
//continue; // тут надо завершать итерацию по j, а не по i !!!
}
2019-06-16 23:44:32 +03:00
goto eq_cmp;
}
}
2021-07-06 16:28:02 +03:00
if (skip_j) // // SSM 06/07/21 пропустить текущую итерацию по j !!
continue;
2019-06-16 23:44:32 +03:00
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//
{
2021-03-21 13:24:27 +03:00
if (j < fact_funcs.Count - 1)
continue;
2019-06-16 23:44:32 +03:00
goto eq_cmp;
}
// 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка
2020-06-13 15:35:47 +03:00
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<TResult>
2021-03-21 13:24:27 +03:00
// 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<TResult>
2019-06-16 23:44:32 +03:00
{
2021-03-21 13:24:27 +03:00
if (j < fact_funcs.Count - 1)
continue;
2019-06-16 23:44:32 +03:00
goto eq_cmp;
}
2021-07-06 16:28:02 +03:00
return true; // SSM 06/07/21 тут сбита логика. Мы рассматриваем получается только первую fact_func[0] и выходим
2019-06-16 23:44:32 +03:00
}
}
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)
{
2021-03-16 22:29:26 +03:00
foreach (type_node ti in fact_type.ImplementingInterfaces)
2019-06-16 23:44:32 +03:00
{
2021-03-16 22:29:26 +03:00
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;
}
2019-06-16 23:44:32 +03:00
}
}
2021-03-16 22:29:26 +03:00
2019-06-16 23:44:32 +03:00
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)
{
2020-06-13 15:35:47 +03:00
if (!DeduceInstanceTypes(formal_type.instance_params[k], fact_type_converted.instance_params[k], deduced, nils, generic_params))
2019-06-16 23:44:32 +03:00
{
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<type_node> param_types, bool type_name)
{
string rez;
if (type_name)
{
int last = name.LastIndexOf(StringConstants.generic_params_infix);
2019-06-16 23:44:32 +03:00
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)
{
2021-01-26 22:41:42 +03:00
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))
2019-06-16 23:44:32 +03:00
return false;
List<SymbolInfo> sil = tn.find_in_type(StringConstants.default_constructor_name, tn.Scope);
2019-06-16 23:44:32 +03:00
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;
}
}
}
}
2020-06-28 16:01:06 +03:00
2019-06-16 23:44:32 +03:00
return false;
}
public static function_node get_function_instance(function_node orig, List<type_node> param_types)
{
List<generic_function_instance_info> _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<param_types.Count; i++)
{
if (param_types[i] is delegated_methods)
{
base_function_call bfc = (param_types[i] as delegated_methods).proper_methods[0];
var context = SystemLibrary.SystemLibrary.syn_visitor.context;
common_type_node del =
type_constructor.instance.create_delegate(context.get_delegate_type_name(), bfc.simple_function_node.return_value_type, bfc.simple_function_node.parameters, context.converted_namespace, null);
context.converted_namespace.types.AddElement(del);
param_types[i] = del;
}
}
//Создаём новую псевдо-инстанцию
common_function_node new_func = null;
SemanticTree.IGenericFunctionInstance new_inst = null;
if (orig.semantic_node_type == semantic_node_type.common_namespace_function_node)
{
generic_namespace_function_instance_node nnode = new generic_namespace_function_instance_node(orig as common_namespace_function_node, param_types);
nnode.ConnectedToType = (orig as common_namespace_function_node).ConnectedToType;
new_func = nnode;
new_inst = nnode;
}
else
{
generic_method_instance_node ctnode = new generic_method_instance_node(orig, param_types);
new_func = ctnode;
new_inst = ctnode;
}
common_function_node common_orig = orig as common_function_node;
if (common_orig != null)
{
new_func.num_of_default_variables = common_orig.num_of_default_variables;
}
var shouldAddToAllTypeInstances = true;
if (LambdaHelper.processingLambdaParametersForTypeInference != 0)
{
foreach (var par in param_types)
{
if (par is lambda_any_type_node)
{
shouldAddToAllTypeInstances = false;
break;
}
}
}
if (shouldAddToAllTypeInstances) //lroman// Если зашли сюда при выведении типов параметров лямбды, то функция инстанцироваться может с типом lambda_any_type_node. Поэтому, если выводим типы. То данную инстанцию не добавляем
{
_generic_instances.Add(new generic_function_instance_info(param_types, new_func));
all_function_instances.Add(new_inst);
}
return new_func;
}
}
public class generic_instance_type_node : common_type_node, SemanticTree.IGenericTypeInstance
{
protected Hashtable _members = new Hashtable();
protected Hashtable _member_definitions = new Hashtable();
protected type_node _original_generic;
public override SymbolTable.Scope Scope
{
get
{
return _original_generic.Scope;
}
}
SemanticTree.ITypeNode SemanticTree.IGenericTypeInstance.original_generic
{
get { return _original_generic; }
}
public override type_node original_generic
{
get { return _original_generic; }
}
public Hashtable used_members
{
get
{
return _members;
}
}
protected List<SemanticTree.ITypeNode> _generic_parameters = null;
protected List<type_node> _instance_params;
public generic_instance_type_node(type_node original_generic_type,
List<type_node> 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);
2019-06-16 23:44:32 +03:00
}
public List<SemanticTree.ITypeNode> generic_parameters
{
get
{
if (_generic_parameters == null)
{
_generic_parameters = new List<SemanticTree.ITypeNode>(_instance_params.Count);
foreach (type_node tn in _instance_params)
{
_generic_parameters.Add(tn);
}
}
return _generic_parameters;
}
}
public override List<SemanticTree.ITypeNode> ImplementingInterfaces
{
get
{
var res = base.ImplementingInterfaces;
if (res==null)
{
res = new List<SemanticTree.ITypeNode>();
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<SemanticTree.ITypeNode> ImplementingInterfacesOrEmpty
{
get
{
return base.ImplementingInterfaces ?? new List<SemanticTree.ITypeNode>();
}
}
2019-06-16 23:44:32 +03:00
2023-07-02 22:22:49 +03:00
/*public override property_node default_property_node
2023-07-02 21:48:21 +03:00
{
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;
}
2023-07-02 22:22:49 +03:00
}*/
2023-07-02 21:48:21 +03:00
2019-06-16 23:44:32 +03:00
private List<SymbolInfo> temp_names = new List<SymbolInfo>(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<type_node> meth_inst_pars = null;
2020-06-12 16:38:46 +03:00
List<type_node> orig_tpars = null;
2019-06-16 23:44:32 +03:00
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)
{
2020-06-12 16:38:46 +03:00
orig_tpars = orig_fn.get_generic_params_list();
2019-06-16 23:44:32 +03:00
int type_count = orig_tpars.Count;
cmn.generic_params = new List<PascalABCCompiler.SemanticTree.ICommonTypeNode>(orig_tpars.Count);
foreach (type_node t in orig_tpars)
{
common_type_node par = new common_type_node(t.name, PascalABCCompiler.SemanticTree.type_access_level.tal_public,
null, SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.symbol_table.CreateInterfaceScope(null, SystemLibrary.SystemLibrary.object_type.Scope, null), null);
SystemLibrary.SystemLibrary.init_reference_type(par);
par.SetBaseType(SystemLibrary.SystemLibrary.object_type);
cmn.generic_params.Add(par);
par.generic_function_container = cmn;
}
meth_inst_pars = cmn.get_generic_params_list();
List<generic_parameter_eliminations> gpes = orig_fn.parameters_eliminations;
for (int i = 0; i < type_count; ++i)
{
common_type_node p = (common_type_node)(meth_inst_pars[i]);
generic_parameter_eliminations gpe = gpes[i];
p.SetBaseType(generic_convertions.determine_type(
generic_convertions.determine_type(gpe.base_class, _instance_params, false),
meth_inst_pars, true));
p.is_class = gpe.is_class;
p.internal_is_value = gpe.is_value;
foreach (type_node interf in gpe.implementing_interfaces)
{
type_table.AddInterface(p, generic_convertions.determine_type(
generic_convertions.determine_type(interf, _instance_params, false),
meth_inst_pars, true), null);
}
if (gpe.has_default_ctor)
{
generic_parameter_eliminations.add_default_ctor(p);
}
}
}
cmn.parameters.AddRange(make_parameters(orig_fn.parameters, cmn));
if (orig_fn.is_generic_function) // orig_fn м.б. generic-методом, но и класс м.б.generic!!! Смешение параметров! А у нас либо класс, либо функция
2019-06-16 23:44:32 +03:00
{
foreach (common_parameter cp in cmn.parameters)
{
//if (cp.type.PrintableName == "Action<TSource>" || cp.type.PrintableName == "TSource") { } // ничего не надо делать, поскольку
//cp.type = generic_convertions.determine_type(cp.type, _instance_params, false);
//else
// Action<T,T2> - T м.б. от класса, а T2 - от метода! И надо передавать оба: meth_inst_pars и _instance_params
// И индексом м.б. не обойдёшься
2020-06-12 16:38:46 +03:00
cp.type = generic_convertions.determine_type(cp.type, meth_inst_pars, true, orig_tpars);
2019-06-16 23:44:32 +03:00
}
}
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)
{
2021-12-29 17:02:15 +03:00
cmn.return_value_type = generic_convertions.determine_type(cmn.return_value_type, meth_inst_pars, true, orig_tpars);
2019-06-16 23:44:32 +03:00
}
if (orig_fn is common_function_node)
{
cmn.return_variable = (orig_fn as common_function_node)?.return_variable;
}
2020-08-01 16:04:54 +03:00
cmn.IsOperator = orig_fn.IsOperator;
2024-01-04 19:44:29 +03:00
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());
}
2019-06-16 23:44:32 +03:00
return cmn;
}
2023-05-14 12:36:08 +03:00
public override bool IsAbstract
{
get
{
return original_generic.IsAbstract;
}
}
2019-06-16 23:44:32 +03:00
public override List<type_node> 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);
}
2019-06-16 23:44:32 +03:00
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); // ну так себе метод - сколько операций = столько и будет удаляться и повторно создаваться :)
}*/
2019-06-16 23:44:32 +03:00
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<integer> - наследника List<integer>
// Это поздно - надо как-то раньше
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<T>
2019-06-16 23:44:32 +03:00
if (compr_type == null)
{
compiled_type_node bbt = null; // SSM 14/06/20 - это для #1647 IGrouping<t1, byte>: IEnumerable<byte>
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<byte>
break;
}
}
compiled_function_node cfn = orig_node as compiled_function_node; // #1647 orig_node = cfn = IEnumerator<TElement> GetEnumerator()
2019-06-16 23:44:32 +03:00
if (cfn == null)
{
return orig_node;
}
compiled_type_node cct = tn as compiled_type_node; // cct = IEnumerable<T>
if (bbt != null) // #1647
cct = orig_member.comperehensive_type as compiled_type_node;
2019-06-16 23:44:32 +03:00
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
2019-06-16 23:44:32 +03:00
MethodInfo[] meths = cct._compiled_type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic |
2019-06-16 23:44:32 +03:00
BindingFlags.Static | BindingFlags.Instance);
int num = System.Array.IndexOf(meths, cfn.method_info);
2019-06-16 23:44:32 +03:00
MethodInfo mi = ((compiled_type_node)inst_type)._compiled_type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Static | BindingFlags.Instance)[num];
2019-06-16 23:44:32 +03:00
return compiled_function_node.get_compiled_method(mi);
}
else
return compr_type.ConvertMember(orig_node);
}
else
return orig_node;
}
2019-06-16 23:44:32 +03:00
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<SymbolInfo> ConvertSymbolInfo(List<SymbolInfo> start)
{
List<SymbolInfo> rez_start = null;
SymbolInfo rez_si = null;
if (start != null)
{
foreach (SymbolInfo si in start)
{
2020-05-24 21:23:46 +03:00
if (si.sym_info == null)
{
if (rez_start == null)
rez_start = new List<SymbolInfo>();
rez_start.Add(si);
continue;
}
2019-06-21 08:24:10 +03:00
// Бурмистров Артем 13.06.19 begin
2019-06-16 23:44:32 +03:00
// Поправил странное поведение для локальных переменных, у которых не generic тип
// Исправление для #1993
2019-06-21 08:24:10 +03:00
if (si.sym_info is /*var_definition_node*/ local_block_variable vdn && !vdn.type.is_generic_parameter)
2019-06-16 23:44:32 +03:00
{
2019-06-13 23:43:54 +03:00
rez_si = si;
2019-06-16 23:44:32 +03:00
}
2019-06-13 23:43:54 +03:00
else
{
definition_node dnode = ConvertMember(si.sym_info);
rez_si = new SymbolInfo(dnode, si.access_level, si.symbol_kind);
rez_si.scope = si.scope;
2019-06-16 23:44:32 +03:00
}
// aab 13.06.19 end
//Дополняем список SymbolInfo преобразованным значением
if (rez_start == null)
{
rez_start = new List<SymbolInfo>();
rez_start.Add(rez_si);
}
else
{
rez_start.Add(rez_si);
}
}
}
return rez_start;
}
public override List<SymbolInfo> find(string name, bool no_search_in_extension_methods = false)
{
List<SymbolInfo> si = _original_generic.find(name);
return ConvertSymbolInfo(si);//delete
}
public override List<SymbolInfo> find_in_type(string name, bool no_search_in_extension_methods = false)
{
List<SymbolInfo> sil = _original_generic.find_in_type(name);
sil = ConvertSymbolInfo(sil);
return sil;
}
public override List<SymbolInfo> 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<SymbolInfo> 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)
{
2021-04-05 16:33:16 +03:00
SymbolInfo si1 = null;
List<SymbolInfo> 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;
}
2019-06-16 23:44:32 +03:00
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);
}
2019-06-16 23:44:32 +03:00
temp_names = null;
}
public virtual List<function_node> all_methods
{
get
{
return null;
}
}
public virtual List<type_node> 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<type_node> 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<function_node> _all_methods = null;
public override List<function_node> all_methods
{
get
{
if (_all_methods != null) return _all_methods;
_all_methods = new List<function_node>();
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<type_node> _all_field_types = null;
public override List<type_node> 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<type_node>();
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<type_node> 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<function_node> _all_methods = null;
public override List<function_node> all_methods
{
get
{
if (_all_methods != null) return _all_methods;
common_method_node_list orig_meths = common_original_generic.methods;
_all_methods = new List<function_node>(orig_meths.Count);
foreach (common_method_node cnode in orig_meths)
{
_all_methods.Add(ConvertMember(cnode) as function_node);
}
return _all_methods;
}
}
private List<type_node> _all_field_types = null;
public override List<type_node> 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<type_node>(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<type_node> _instance_params;
public List<type_node> instance_params
{
get
{
return _instance_params;
}
}
protected List<SemanticTree.ITypeNode> _generic_parameters = null;
public List<SemanticTree.ITypeNode> generic_parameters
{
get
{
if (_generic_parameters == null)
{
_generic_parameters = new List<SemanticTree.ITypeNode>();
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;
}
}
2021-11-21 16:37:34 +03:00
public override bool is_extension_method
{
get
{
return _original_function.is_extension_method;
}
}
2019-06-16 23:44:32 +03:00
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<type_node> instance_parameters)
: base(
generic_convertions.MakePseudoInstanceName(original_generic_function.name, instance_parameters, false),
null, null)
{
_original_function = original_generic_function;
_instance_params = instance_parameters;
2020-06-12 16:38:46 +03:00
List<type_node> orig_gen_params =
original_generic_function.get_generic_params_list(); // #2068 попытка
2019-06-16 23:44:32 +03:00
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;
2020-06-12 16:38:46 +03:00
this.return_value_type = generic_convertions.determine_type(original_generic_function.return_value_type, instance_parameters, true, orig_gen_params);
2019-06-16 23:44:32 +03:00
foreach (parameter par in original_generic_function.parameters)
{
common_parameter cpar = new common_parameter(par.name,
2020-06-12 16:38:46 +03:00
generic_convertions.determine_type(par.type, _instance_params, true, orig_gen_params),
2019-06-16 23:44:32 +03:00
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<type_node> get_generic_params_list()
{
return instance_params;
}
}
public class generic_namespace_function_instance_node: common_namespace_function_node, SemanticTree.IGenericFunctionInstance
{
protected List<type_node> _instance_params;
public List<type_node> instance_params
{
get
{
return _instance_params;
}
}
protected List<SemanticTree.ITypeNode> _generic_parameters = null;
public List<SemanticTree.ITypeNode> generic_parameters
{
get
{
if (_generic_parameters == null)
{
_generic_parameters = new List<SemanticTree.ITypeNode>();
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<type_node> 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;
2020-06-12 16:38:46 +03:00
List<type_node> orig_gen_params =
original_generic_function.generic_params.Select(p => p as type_node).ToList(); // #2068 попытка
2019-06-16 23:44:32 +03:00
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;
2020-06-12 16:38:46 +03:00
this.return_value_type = generic_convertions.determine_type(original_generic_function.return_value_type, instance_parameters, true, orig_gen_params);
2019-06-16 23:44:32 +03:00
foreach (parameter par in original_generic_function.parameters)
{
common_parameter cpar = new common_parameter(par.name,
2020-06-12 16:38:46 +03:00
generic_convertions.determine_type(par.type, _instance_params, true, orig_gen_params),
2019-06-16 23:44:32 +03:00
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);
2019-06-16 23:44:32 +03:00
cpar.inital_value = par.inital_value;
2023-11-01 15:48:08 +03:00
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)
2023-11-01 15:48:08 +03:00
{
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;
2023-11-01 15:48:08 +03:00
}
2019-06-16 23:44:32 +03:00
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<type_node> 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;
}
}
/// <summary>
/// Метод для обхода дерева посетителем.
/// </summary>
/// <param name="visitor">Класс - посетитель дерева.</param>
public override void visit(SemanticTree.ISemanticVisitor visitor)
{
visitor.visit(this);
}
}
}