From e1d6336bee7d6e9608d5d5c3b41910c28fbd5c10 Mon Sep 17 00:00:00 2001 From: Mikhalkovich Stanislav Date: Sun, 16 Jun 2019 23:44:32 +0300 Subject: [PATCH] bug fix #1270 --- Configuration/GlobalAssemblyInfo.cs | 2 +- Configuration/Version.defs | 2 +- ReleaseGenerators/PascalABCNET_version.nsh | 2 +- SyntaxVisitors/SyntaxVisitors.csproj | 1 + .../RenameSameVarNamesVisitor.cs | 181 + ...tExprWithLambdaInForeachSequenceVisitor.cs | 170 - TestSuite/lambda_nested1.pas | 9 + .../TreeConversion/syntax_tree_visitor.cs | 93 +- TreeConverter/TreeRealization/generics.cs | 4792 ++++++++--------- 9 files changed, 2642 insertions(+), 2610 deletions(-) create mode 100644 SyntaxVisitors/VisitorsForLambdas/RenameSameVarNamesVisitor.cs create mode 100644 TestSuite/lambda_nested1.pas diff --git a/Configuration/GlobalAssemblyInfo.cs b/Configuration/GlobalAssemblyInfo.cs index e79a49feb..b5a0b0780 100644 --- a/Configuration/GlobalAssemblyInfo.cs +++ b/Configuration/GlobalAssemblyInfo.cs @@ -15,7 +15,7 @@ internal static class RevisionClass public const string Major = "3"; public const string Minor = "5"; public const string Build = "0"; - public const string Revision = "2106"; + public const string Revision = "2110"; public const string MainVersion = Major + "." + Minor; public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision; diff --git a/Configuration/Version.defs b/Configuration/Version.defs index 3304c8ca3..3b542fc74 100644 --- a/Configuration/Version.defs +++ b/Configuration/Version.defs @@ -1,4 +1,4 @@ %COREVERSION%=0 -%REVISION%=2106 +%REVISION%=2110 %MINOR%=5 %MAJOR%=3 diff --git a/ReleaseGenerators/PascalABCNET_version.nsh b/ReleaseGenerators/PascalABCNET_version.nsh index acf761028..9f2260a75 100644 --- a/ReleaseGenerators/PascalABCNET_version.nsh +++ b/ReleaseGenerators/PascalABCNET_version.nsh @@ -1 +1 @@ -!define VERSION '3.5.0.2106' +!define VERSION '3.5.0.2110' diff --git a/SyntaxVisitors/SyntaxVisitors.csproj b/SyntaxVisitors/SyntaxVisitors.csproj index 8410aa8dd..00b7ce314 100644 --- a/SyntaxVisitors/SyntaxVisitors.csproj +++ b/SyntaxVisitors/SyntaxVisitors.csproj @@ -59,6 +59,7 @@ + diff --git a/SyntaxVisitors/VisitorsForLambdas/RenameSameVarNamesVisitor.cs b/SyntaxVisitors/VisitorsForLambdas/RenameSameVarNamesVisitor.cs new file mode 100644 index 000000000..0eef1ac24 --- /dev/null +++ b/SyntaxVisitors/VisitorsForLambdas/RenameSameVarNamesVisitor.cs @@ -0,0 +1,181 @@ +// Copyright (c) Ivan Bondarev, Stanislav Mihalkovich (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +using System; +using System.Collections.Generic; +using System.Linq; +using PascalABCCompiler.SyntaxTree; + +namespace PascalABCCompiler.SyntaxTreeConverters +{ + + // Первое предназначение - вынести последовательность из заголовка в foreach до foreach как отдельное присваивание + // Второе предназначение - переименовать все переменные, совпадающие по имени с типом T обобщенного класса, в котором находится метод, содержащий лямбду + public class VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer: CollectLightSymInfoVisitor + { + /// + /// Надо приводить к нижнему регистру + /// + //public List NamesForReplace = new List(); + + private int LambdaNestedLevel = 0; + + Dictionary d = new Dictionary(); // словарь скоупов для каждого имени + // При входе в обобщенный класс или запись мы в словарь добавляем все его обобщенные параметры со значением nil + // При выходе из класса мы очищаем словарь + // При встрече описания переменной с именем, совпадающим с одним из ключей в словаре, мы заменяем значение null на пространство имен, в котором мы находимся + // Описание переменной в словарь добавляется только если она описана в методе, но вне лямбды, поскольку в лямбде конфликтов имен нет + // При выходе из пространства имен мы проверяем, есть ли в словаре такое значение, и если да, очищаем его, присваивая null + // Переименовывать будем все имена name если ключ name есть в словаре и d[name] != null + public static new VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer New + { + get => new VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer(); + } + public override void AddSymbol(ident name, SymKind kind, type_definition td = null, Attributes attr = 0) + { + if (name == null || name.name == null) + { + return; + } + var n = name.name.ToLower(); + //if (LambdaNestedLevel > 0) // т.е. впервые встретилось переопределение именно в лямбде, тогда пропускать эту лямбду + // return; + if (d.ContainsKey(n) && d[n] == null && (kind == SymKind.var || kind == SymKind.param)) // Добавляем не все, а только разыскиваемые и только если это - переменная + { + d[n] = this.Current; + base.AddSymbol(name, kind, td, attr); + } + } + public override void Enter(syntax_tree_node st) + { + base.Enter(st); + if (st is function_lambda_definition) + LambdaNestedLevel += 1; + else if (st is class_definition cl) + { + var td = cl.Parent as type_declaration; + if (td?.type_name is template_type_name ttn) + { + foreach (var id in ttn.template_args.idents) + { + d[id.name.ToLower()] = null; + } + } + } + else if (st is procedure_definition pd) + { + var cn = pd.proc_header.name?.class_name; + if (cn is template_type_name ttn) + { + foreach (var id in ttn.template_args.idents) + { + d[id.name.ToLower()] = null; + } + } + } + } + public override void PreExitScope(syntax_tree_node st) + { + var l = d.Keys.Where(k => d[k] == Current).ToList(); + // Обходим все словари и смотрим у них вершину стеков + foreach (var k in l) + { + d[k] = null; // т.е. в этом пространстве имен мы захватили одноименное описание переменной - освобождаем его + } + } + public override void Exit(syntax_tree_node st) + { + if (st is function_lambda_definition) + LambdaNestedLevel -= 1; + else if (st is class_definition) // то мы не ищем переопределение имен, поскольку мы вышли из класса + { + d.Clear(); + } + else if (st is procedure_definition pd) // мы вышли из метода вида t1.p + { + var cn = pd.proc_header.name?.class_name; + if (cn is template_type_name ttn) + d.Clear(); + } + base.Exit(st); + } + + public override void visit(template_type_name tn) + { + // игнорировать чтобы там ничего не переименовывалось + } + public override void visit(ident id) + { + ReplaceNameOrNot(id); + } + public override void visit(dot_node dn) + { + if (dn.left is ident id) + ReplaceNameOrNot(id); + else ProcessNode(dn.left); + } + + public static int ReplaceNum = 0; + public void ReplaceNameOrNot(ident id) + { + var n = id.name.ToLower(); + if (d.ContainsKey(n) && d[n] != null) // Переименовываем без страха + { + id.name = id.name + "$Replace$" + ReplaceNum; // имя такое чтобы при выдаче сообщения об ошибке в нем можно было бы обрезать конец + } + } + } + + // Может, переименовать все T? Всё равно алгоритм переименовывания будет один + // Искать описания с T. Как нашли - с этого места переименовывать + // Сделать визитор LocalRenamer и переименовывать с места описания + + /*public class LocalRenamer : BaseChangeVisitor + { + + public static void RenameFrom(var_def_statement vd, string Name, string NewName) + { + var lr = new LocalRenamer(); + lr.ProcessNode(vd); + } + }*/ + + + // Поиск всех захваченных переменных в лямбде + // Это сложно + /*public class LambdaCapturedNamesSearcher : BaseChangeVisitor + { + List idents = new List(); + public static LambdaCapturedNamesSearcher New + { + get + { + return new LambdaCapturedNamesSearcher(); + } + } + public override void visit(ident id) + { + // хорошо бы всё здесь захватить! Но вдруг это - описание... + } + public override void visit(dot_node dn) + { + // это точно надо захватывать + } + + public override void visit(var_def_statement vds) + { + // имена обойти отдельно, инициализатор - отдельно + foreach (var id in vds.vars.idents) + { + // Надо проверять совпадение имен с именами в параметрах обобщения + // если не совпадают, то просто пропускаем + // если совпадают, то исключаем это имя из списка проверки! Всё - имя уже переопределено! И это произошло в лямбде, что можно + } + visit(vds.inital_value); + } + public override void visit(function_lambda_definition ld) + { + // параметры обойти отдельно, тело отдельно + // проблема, что могут быть вложенные лямбды. Т.е это - основная, а в ней - ещё. + } + }*/ +} diff --git a/SyntaxVisitors/VisitorsForLambdas/StandOutExprWithLambdaInForeachSequenceVisitor.cs b/SyntaxVisitors/VisitorsForLambdas/StandOutExprWithLambdaInForeachSequenceVisitor.cs index 6a6d387c5..e01f1505e 100644 --- a/SyntaxVisitors/VisitorsForLambdas/StandOutExprWithLambdaInForeachSequenceVisitor.cs +++ b/SyntaxVisitors/VisitorsForLambdas/StandOutExprWithLambdaInForeachSequenceVisitor.cs @@ -45,174 +45,4 @@ namespace PascalABCCompiler.SyntaxTreeConverters base.visit(fe); } } - - - public class VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer: CollectLightSymInfoVisitor - { - /// - /// Надо приводить к нижнему регистру - /// - //public List NamesForReplace = new List(); - - private int LambdaNestedLevel = 0; - - Dictionary d = new Dictionary(); // словарь скоупов для каждого имени - // При входе в обобщенный класс или запись мы в словарь добавляем все его обобщенные параметры со значением nil - // При выходе из класса мы очищаем словарь - // При встрече описания переменной с именем, совпадающим с одним из ключей в словаре, мы заменяем значение null на пространство имен, в котором мы находимся - // Описание переменной в словарь добавляется только если она описана в методе, но вне лямбды, поскольку в лямбде конфликтов имен нет - // При выходе из пространства имен мы проверяем, есть ли в словаре такое значение, и если да, очищаем его, присваивая null - // Переименовывать будем все имена name если ключ name есть в словаре и d[name] != null - public static new VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer New - { - get => new VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer(); - } - public override void AddSymbol(ident name, SymKind kind, type_definition td = null, Attributes attr = 0) - { - if (name == null || name.name == null) - { - return; - } - var n = name.name.ToLower(); - //if (LambdaNestedLevel > 0) // т.е. впервые встретилось переопределение именно в лямбде, тогда пропускать эту лямбду - // return; - if (d.ContainsKey(n) && d[n] == null && (kind == SymKind.var || kind == SymKind.param)) // Добавляем не все, а только разыскиваемые и только если это - переменная - { - d[n] = this.Current; - base.AddSymbol(name, kind, td, attr); - } - } - public override void Enter(syntax_tree_node st) - { - base.Enter(st); - if (st is function_lambda_definition) - LambdaNestedLevel += 1; - else if (st is class_definition cl) - { - var td = cl.Parent as type_declaration; - if (td?.type_name is template_type_name ttn) - { - foreach (var id in ttn.template_args.idents) - { - d[id.name.ToLower()] = null; - } - } - } - else if (st is procedure_definition pd) - { - var cn = pd.proc_header.name?.class_name; - if (cn is template_type_name ttn) - { - foreach (var id in ttn.template_args.idents) - { - d[id.name.ToLower()] = null; - } - } - } - } - public override void PreExitScope(syntax_tree_node st) - { - var l = d.Keys.Where(k => d[k] == Current).ToList(); - // Обходим все словари и смотрим у них вершину стеков - foreach (var k in l) - { - d[k] = null; // т.е. в этом пространстве имен мы захватили одноименное описание переменной - освобождаем его - } - } - public override void Exit(syntax_tree_node st) - { - if (st is function_lambda_definition) - LambdaNestedLevel -= 1; - else if (st is class_definition) // то мы не ищем переопределение имен, поскольку мы вышли из класса - { - d.Clear(); - } - else if (st is procedure_definition pd) // мы вышли из метода вида t1.p - { - var cn = pd.proc_header.name?.class_name; - if (cn is template_type_name ttn) - d.Clear(); - } - base.Exit(st); - } - - public override void visit(template_type_name tn) - { - // игнорировать чтобы там ничего не переименовывалось - } - public override void visit(ident id) - { - ReplaceNameOrNot(id); - } - public override void visit(dot_node dn) - { - if (dn.left is ident id) - ReplaceNameOrNot(id); - else ProcessNode(dn.left); - } - - public static int ReplaceNum = 0; - public void ReplaceNameOrNot(ident id) - { - var n = id.name.ToLower(); - if (d.ContainsKey(n) && d[n] != null) // Переименовываем без страха - { - id.name = id.name + "$Replace$" + ReplaceNum; // имя такое чтобы при выдаче сообщения об ошибке в нем можно было бы обрезать конец - } - } - } - - // Может, переименовать все T? Всё равно алгоритм переименовывания будет один - // Искать описания с T. Как нашли - с этого места переименовывать - // Сделать визитор LocalRenamer и переименовывать с места описания - - /*public class LocalRenamer : BaseChangeVisitor - { - - public static void RenameFrom(var_def_statement vd, string Name, string NewName) - { - var lr = new LocalRenamer(); - lr.ProcessNode(vd); - } - }*/ - - - // Поиск всех захваченных переменных в лямбде - // Это сложно - /*public class LambdaCapturedNamesSearcher : BaseChangeVisitor - { - List idents = new List(); - public static LambdaCapturedNamesSearcher New - { - get - { - return new LambdaCapturedNamesSearcher(); - } - } - public override void visit(ident id) - { - // хорошо бы всё здесь захватить! Но вдруг это - описание... - } - public override void visit(dot_node dn) - { - // это точно надо захватывать - } - - public override void visit(var_def_statement vds) - { - // имена обойти отдельно, инициализатор - отдельно - foreach (var id in vds.vars.idents) - { - // Надо проверять совпадение имен с именами в параметрах обобщения - // если не совпадают, то просто пропускаем - // если совпадают, то исключаем это имя из списка проверки! Всё - имя уже переопределено! И это произошло в лямбде, что можно - } - visit(vds.inital_value); - } - public override void visit(function_lambda_definition ld) - { - // параметры обойти отдельно, тело отдельно - // проблема, что могут быть вложенные лямбды. Т.е это - основная, а в ней - ещё. - } - }*/ } diff --git a/TestSuite/lambda_nested1.pas b/TestSuite/lambda_nested1.pas new file mode 100644 index 000000000..7d8c2793d --- /dev/null +++ b/TestSuite/lambda_nested1.pas @@ -0,0 +1,9 @@ +begin + var s: sequence of integer := Seq(1,2); + + Assert(s.SelectMany( + t1-> + s.Select(t2->t1+t2).Where(t->true) + ).First = 2) + +end. \ No newline at end of file diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index 54f00d8da..c2376eae9 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -2739,6 +2739,16 @@ namespace PascalABCCompiler.TreeConverter lambdaProcessingState = LambdaProcessingState.TypeInferencePhase; visit_program_code(_block.program_code); + // Грубо - удаление мусора при разборе лямбд. Происходит исключение - заголовок разбирается, тело остается пустым - и из-за этого была ошибка #1270. + while (context._cmn.functions.Count > 0 && context._cmn.functions[context._cmn.functions.Count-1].function_code == null && context._cmn.functions[context._cmn.functions.Count - 1].name.StartsWith("<>lambda") && !context._cmn.functions[context._cmn.functions.Count - 1].name.StartsWith("<>lambda_initializer")) + { +#if DEBUG + System.IO.File.AppendAllText("d:\\aa.txt", context._cmn.functions[context._cmn.functions.Count - 1].name+"\n"); +#endif + context._cmn.functions.remove_at(context._cmn.functions.Count - 1); + + } + lambdaProcessingState = LambdaProcessingState.ClosuresProcessingPhase; CapturedVariablesSubstitutionsManager.Substitute(this, _block.defs, _block.program_code); @@ -19397,6 +19407,47 @@ namespace PascalABCCompiler.TreeConverter } } + public expression ProcedureForLambdaAndVisit(function_lambda_definition lambdaDefinition, ident_list tempParsList, where_definition_list whereSection) + { + var procDecl = LambdaHelper.ConvertLambdaNodeToProcDefNode(lambdaDefinition); + + if (tempParsList != null) + { + procDecl.proc_header.template_args = tempParsList; + } + + if (whereSection != null && whereSection.defs != null && whereSection.defs.Count != 0) + { + procDecl.proc_header.where_defs = whereSection; + } + + if (!context.func_stack.Empty && context.func_stack.top().polymorphic_state == SemanticTree.polymorphic_state.ps_static + || context.converted_type != null && context.converted_type.IsStatic) + { + procDecl.proc_header.class_keyword = true; + if (procDecl.proc_header.proc_attributes == null) + procDecl.proc_header.proc_attributes = new SyntaxTree.procedure_attributes_list(); + procDecl.proc_header.proc_attributes.proc_attributes.Add(new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static)); + } + + try + { + visit(procDecl); + } + catch + { + context.remove_lambda_function(procDecl.proc_header.name.meth_name.name, true); + throw; + } + + context.remove_lambda_function(procDecl.proc_header.name.meth_name.name, false); + + return tempParsList == null ? + (expression)procDecl.proc_header.name.meth_name : + (expression)new ident_with_templateparams(procDecl.proc_header.name.meth_name, new template_param_list(tempParsList.idents.Select(l => SyntaxTreeBuilder.BuildSimpleType(l.name)).ToList())); + + } + int ccc = 0; public override void visit(SyntaxTree.function_lambda_definition _function_lambda_definition) { @@ -19432,47 +19483,7 @@ namespace PascalABCCompiler.TreeConverter return; } - Func makeProcedureForLambdaAndVisit = - (lambdaDefinition, tempParsList, whereSection) => - { - var procDecl = LambdaHelper.ConvertLambdaNodeToProcDefNode(lambdaDefinition); - - if (tempParsList != null) - { - procDecl.proc_header.template_args = tempParsList; - } - - if (whereSection != null && whereSection.defs != null && whereSection.defs.Count != 0) - { - procDecl.proc_header.where_defs = whereSection; - } - - if (!context.func_stack.Empty && context.func_stack.top().polymorphic_state == SemanticTree.polymorphic_state.ps_static - || context.converted_type != null && context.converted_type.IsStatic) - { - procDecl.proc_header.class_keyword = true; - if (procDecl.proc_header.proc_attributes == null) - procDecl.proc_header.proc_attributes = new SyntaxTree.procedure_attributes_list(); - procDecl.proc_header.proc_attributes.proc_attributes.Add(new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static)); - } - - try - { - visit(procDecl); - } - catch - { - context.remove_lambda_function(procDecl.proc_header.name.meth_name.name, true); - throw; - } - - context.remove_lambda_function(procDecl.proc_header.name.meth_name.name, false); - - return tempParsList == null ? - (expression)procDecl.proc_header.name.meth_name : - (expression)new ident_with_templateparams(procDecl.proc_header.name.meth_name, new template_param_list(tempParsList.idents.Select(l => SyntaxTreeBuilder.BuildSimpleType(l.name)).ToList())); - }; - + Func makeProcedureForLambdaAndVisit = ProcedureForLambdaAndVisit; switch (lambdaProcessingState) { diff --git a/TreeConverter/TreeRealization/generics.cs b/TreeConverter/TreeRealization/generics.cs index b4b926b0d..1c305e1ad 100644 --- a/TreeConverter/TreeRealization/generics.cs +++ b/TreeConverter/TreeRealization/generics.cs @@ -1,2403 +1,2403 @@ -// Copyright (c) Ivan Bondarev, Stanislav Mihalkovich (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) -//Здесь описана реализация generic-типов -//Файлом владеет ssyy. - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using PascalABCCompiler.SyntaxTree; -using PascalABCCompiler.TreeConverter; - -namespace PascalABCCompiler.TreeRealization -{ - //Вспомогательный класс для реализации generic-типов - public class generic_type_instance_info - { - public List param_types; - public generic_instance_type_node pseudo_instance; - - public generic_type_instance_info(List _param_types, generic_instance_type_node _pseudo_instance) - { - param_types = _param_types; - pseudo_instance = _pseudo_instance; - } - } - - public class generic_function_instance_info - { - public List param_types; - public function_node pseudo_instance; - - public generic_function_instance_info(List _param_types, function_node _pseudo_instance) - { - param_types = _param_types; - pseudo_instance = _pseudo_instance; - } - } - - public class generic_parameter_eliminations - { - public bool is_class = false; - public bool is_value = false; - public bool has_default_ctor = false; - public type_node base_class = null; - public List implementing_interfaces = null; - - public static void add_default_ctor(common_type_node param) - { - common_method_node cnode = new common_method_node( - compiler_string_consts.default_constructor_name, param, null, - param, SemanticTree.polymorphic_state.ps_common, - SemanticTree.field_access_level.fal_public, null); - cnode.is_constructor = true; - param.methods.AddElement(cnode); - param.add_name(compiler_string_consts.default_constructor_name, new SymbolInfo(cnode)); - param.has_default_constructor = true; - } - - public static List make_eliminations_common(List generic_params) - { - List _parameters_eliminations = new List(); - foreach (type_node t in generic_params) - { - generic_parameter_eliminations gpe = new generic_parameter_eliminations(); - gpe.has_default_ctor = generic_convertions.type_has_default_ctor(t, false); - gpe.is_class = t.is_class; - gpe.is_value = t.is_value; - gpe.base_class = t.base_type; - gpe.implementing_interfaces = new List(t.ImplementingInterfaces.Count); - foreach (type_node interf in t.ImplementingInterfaces) - { - gpe.implementing_interfaces.Add(interf); - } - _parameters_eliminations.Add(gpe); - } - return _parameters_eliminations; - } - - public static List make_eliminations_compiled(Type[] pars) - { - List _parameters_eliminations = new List(); - foreach (Type t in pars) - { - generic_parameter_eliminations gpe = new generic_parameter_eliminations(); - gpe.has_default_ctor = - ((t.GenericParameterAttributes & - GenericParameterAttributes.DefaultConstructorConstraint) != 0); - gpe.is_class = - ((t.GenericParameterAttributes & - GenericParameterAttributes.ReferenceTypeConstraint) != 0); - gpe.is_value = - ((t.GenericParameterAttributes & - GenericParameterAttributes.NotNullableValueTypeConstraint) != 0); - gpe.base_class = compiled_type_node.get_type_node(t.BaseType); - Type[] net_interf = t.GetInterfaces(); - gpe.implementing_interfaces = new List(net_interf.Length); - foreach (Type net_t in net_interf) - { - gpe.implementing_interfaces.Add(compiled_type_node.get_type_node(net_t)); - } - _parameters_eliminations.Add(gpe); - } - return _parameters_eliminations; - } - - public static CompilationErrorWithLocation check_type_generic_useful(type_node tn, location loc) - { - if (tn == null) - { - return new SimpleSemanticError(loc, "TYPE_NAME_EXPECTED"); - } - if (tn.IsPointer) - { - return new SimpleSemanticError(loc, "CANNOT_USE_POINTER_AS_GENERIC_ARGUMENT"); - } - switch (tn.type_special_kind) - { - case PascalABCCompiler.SemanticTree.type_special_kind.diap_type: - return new SimpleSemanticError(loc, "CANNOT_USE_DIAPASON_AS_GENERIC_ARGUMENT"); - case PascalABCCompiler.SemanticTree.type_special_kind.typed_file: - return new SimpleSemanticError(loc, "CANNOT_USE_TYPED_FILE_AS_GENERIC_ARGUMENT"); - case PascalABCCompiler.SemanticTree.type_special_kind.short_string: - return new SimpleSemanticError(loc, "CANNOT_USE_SHORT_STRING_AS_GENERIC_ARGUMENT"); - } - /*if (tn == SystemLibrary.SystemLibrary.void_type) - { - return new VoidNotValid(loc); - }*/ - SystemLibrary.SystemLibrary.syn_visitor.check_for_type_allowed(tn,loc); - 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.is_class && !tn.is_class && !(tn.base_type != null && tn.base_type.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); - } - if (gpe.base_class != null && gpe.base_class != SystemLibrary.SystemLibrary.object_type) - { - type_node base_type = generic_convertions.determine_type(gpe.base_class, tparams, method_param_types); - if (base_type != tn && !type_table.is_derived(base_type, tn) && !tn.is_generic_parameter) - { - return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_BE_DERIVED_FROM_{1}", tn.PrintableName, base_type.name); - } - } - foreach (type_node interf in gpe.implementing_interfaces) - { - type_node di = generic_convertions.determine_type(interf, tparams, method_param_types); - if (di != tn && - (tn.ImplementingInterfaces == null || - !type_table.is_derived(di, tn))) - { - return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_IMPLEMENT_INTERFACE_{1}", tn.PrintableName, di.name); - } - } - if (tn.IsStatic) - return new SimpleSemanticError(null, "USING_STATIC_CLASS_NOT_VALID"); - if (gpe.has_default_ctor) - { - if (tn.IsAbstract || 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 Hashtable generic_instances = new Hashtable(); - - public static syntax_tree_visitor visitor; - - public static List get_type_instances(type_node original_generic_type) - { - List instances = generic_instances[original_generic_type] as List; - if (instances == null) - { - instances = new List(); - generic_instances.Add(original_generic_type, instances); - } - return instances; - } - - public static List get_function_instances(function_node original_generic_function) - { - List instances = generic_instances[original_generic_function] as List; - if (instances == null) - { - instances = new List(); - generic_instances.Add(original_generic_function, instances); - } - return instances; - } - - public static type_node find_type_instance(List _generic_instances, List param_types) - { - int count = param_types.Count; - foreach (generic_type_instance_info gii in _generic_instances) - { - bool equals = true; - for (int i = 0; equals && i < count; ++i) - { - equals = (param_types[i] == gii.param_types[i]); - } - if (equals) - { - //Такая инстанция уже есть - return gii.pseudo_instance; - } - } - return null; - } - - public static void check_instances_are_correct(List insts) - { - int num; - foreach (type_instance_and_location tia in insts) - { - List gpes = tia.instance.original_generic.parameters_eliminations; - CompilationErrorWithLocation err = generic_parameter_eliminations.check_type_list(tia.instance.instance_params, gpes, false, out num); - if (err != null) - { - err.loc = tia.loc; - throw err; - } - } - } - - public static function_node find_function_instance(List _generic_instances, List param_types) - { - int count = param_types.Count; - foreach (generic_function_instance_info gii in _generic_instances) - { - bool equals = true; - for (int i = 0; equals && i < count; ++i) - { - equals = (param_types[i] == gii.param_types[i]); - } - if (equals) - { - //Такая инстанция уже есть - return gii.pseudo_instance; - } - } - return null; - } - - public static void init_generic_instance(type_node original, generic_instance_type_node instance, /*SymbolTable.ClassScope instance_scope,*/ List param_types) - { - instance.IsInterface = original.IsInterface; - instance.is_class = original.is_class; - instance.internal_is_value = original.is_value; - instance.SetIsSealed(original.IsSealed); - instance.IsDelegate = original.IsDelegate; - instance.type_special_kind = original.type_special_kind; - - //Определяем базовый тип - type_node btype = determine_type( - original.base_type, param_types, false); - instance.SetBaseTypeIgnoringScope(btype); - - //instance._scope = new SymbolTable.GenericTypeInstanceScope(instance, instance.original_generic.Scope, btype.Scope); - - foreach (type_node interf in original.ImplementingInterfaces) - { - instance.ImplementingInterfaces.Add( - determine_type(interf, param_types, false) - ); - } - - SystemLibrary.SystemLibrary.init_reference_type(instance); - instance.conform_basic_functions(); - //(ssyy) Нужно, чтобы добавились конструкторы - //ctnode.find_in_type(compiler_string_consts.default_constructor_name); - instance.instance_params = param_types; - - property_node orig_pn = original.default_property_node; - if (orig_pn != null) - { - if (orig_pn.comprehensive_type == original) - { - //Свойство по умолчанию описано в оригинальном коде generic-a; - //конвертируем его - instance.default_property = instance.ConvertMember(orig_pn) as common_property_node; - } - else - { - //Свойство по умолчанию описано в каком-то предке оригинального generic-a - if (orig_pn.comprehensive_type.is_generic_type_definition) - { - instance.default_property = instance.find_instance_type_from(orig_pn.comprehensive_type).default_property; - } - } - } - - var shouldAddToAllTypeInstances = true; - if (LambdaHelper.processingLambdaParametersForTypeInference != 0) - { - foreach (var par in instance.generic_parameters) - { - if (par is lambda_any_type_node) - { - shouldAddToAllTypeInstances = false; - break; - } - } - } - - if (shouldAddToAllTypeInstances) //lroman// Если зашли сюда при выведении типов параметров лямбды, то тип инстанцироваться может с типом lambda_any_type_node. Поэтому, если выводим типы. То данную инстанцию не добавляем - { - if (instance.instance_params[0] is ienumerable_auto_type) // SSM 10.07.16 (yields) в эту таблицу не включаются типы IEnumerable, т.к. потом они всё равно автовыводятся - { - //instance = instance; - } - else - { - generic_convertions.all_type_instances.Add(instance); - } - } - - internal_interface ii = original.get_internal_interface(internal_interface_kind.delegate_interface); - if (ii != null) - { - delegate_internal_interface dii = ii as delegate_internal_interface; - common_method_node inv = instance.ConvertMember(dii.invoke_method) as common_method_node; - common_method_node constr = instance.ConvertMember(dii.constructor) as common_method_node; - constr.function_code = new runtime_statement(SemanticTree.runtime_statement_type.ctor_delegate, null); - delegate_internal_interface converted_dii = new delegate_internal_interface(inv.return_value_type, - inv, constr); - converted_dii.parameters.AddRange(inv.parameters); - instance.add_internal_interface(converted_dii); - } - } - - public static void reset_generics() - { - generic_instances.Clear(); - all_type_instances.Clear(); - all_function_instances.Clear(); - } - - //Определяет, как должен выглядеть тип в семантическом дереве. - //Возвращает этот тип. - public static type_node determine_type(Type t, List param_types, bool method_param_types) - { - if (t == null) return null; - if (t.IsGenericParameter) - { - //Если мы определяем тип-параметры метода, нет необходимости рассматривать - //тип-параметры типа, и наоборот. Это для поддержки generic-методов в - //generic-типе. - if (method_param_types == (t.DeclaringMethod != null)) - { - return param_types[t.GenericParameterPosition]; - } - else - { - return compiled_type_node.get_type_node(t); - } - } - if (t.IsGenericType) - { - //Формируем список типов-параметров - Type[] args = t.GetGenericArguments(); - List semantic_args = new List(); - foreach (Type arg in args) - { - semantic_args.Add(determine_type(arg, param_types, method_param_types)); - } - - //Получаем описание generic-класса - Type def = t.GetGenericTypeDefinition(); - compiled_type_node ct_def = compiled_type_node.get_type_node(def); - - //Создаём псевдо-инстанцию - return ct_def.get_instance(semantic_args); - } - - //Для типов, не имеющих отношения к generic-типам. - return compiled_type_node.get_type_node(t); - } - - public static type_node determine_type(type_node tn, List param_types, bool method_param_types) - { - if (tn == null) return null; - ref_type_node rtn = tn as ref_type_node; - if (rtn != null) - { - type_node ptype = generic_convertions.determine_type(rtn.pointed_type, param_types, method_param_types); - if (ptype == rtn.pointed_type) return tn; - ref_type_node rez_ref = ptype.ref_type; - rez_ref.loc = rtn.loc; - return rez_ref; - } - array_internal_interface ii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; - if (ii != null) - { - type_node elem_tp = determine_type(ii.element_type, param_types, method_param_types); - if (elem_tp != ii.element_type) - { - return SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.type_constructor.create_unsized_array(elem_tp, null, ii.rank, null); - } - return tn; - } - common_type_node comm_type = tn as common_type_node; - if (comm_type != null) - { - if (comm_type.is_generic_parameter) - { - if (method_param_types && comm_type.generic_function_container != null) - { - return param_types[comm_type.generic_param_index]; - } - else if (!method_param_types && comm_type.generic_type_container != null) - { - return param_types[comm_type.generic_param_index]; - } - return tn; - } - generic_instance_type_node gitn = tn as generic_instance_type_node; - if (gitn != null) - { - List semantic_args = new List(); - List gitn_inst_parameters = gitn.instance_params; - foreach (type_node arg in gitn_inst_parameters) - { - semantic_args.Add(determine_type(arg, param_types, method_param_types)); - } - return gitn.original_generic.get_instance(semantic_args); - } - if (comm_type.is_generic_type_definition) - { - return comm_type.get_instance(param_types); - } - if (comm_type.type_special_kind == SemanticTree.type_special_kind.array_kind) - { - type_node elem_tp = determine_type(comm_type.element_type, param_types, method_param_types); - if (elem_tp != comm_type.element_type) - { - return SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.type_constructor.create_unsized_array(elem_tp, null, 1, comm_type.loc); - } - return tn; - } - if (comm_type.type_special_kind == SemanticTree.type_special_kind.set_type) - { - type_node elem_tp = determine_type(comm_type.element_type, param_types, method_param_types); - if (elem_tp != comm_type.element_type) - { - return SystemLibrary.SystemLibrary.syn_visitor.context.create_set_type(elem_tp, comm_type.loc); - } - return tn; - } - if (comm_type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.typed_file) - { - type_node elem_tp = determine_type(comm_type.element_type, param_types, method_param_types); - if (elem_tp != comm_type.element_type) - { - return SystemLibrary.SystemLibrary.syn_visitor.context.create_typed_file_type(elem_tp, comm_type.loc); - } - return tn; - } - return tn; - } - compiled_type_node ctn = tn as compiled_type_node; - if (ctn == null || (!ctn.compiled_type.IsGenericType && !ctn.compiled_type.IsGenericParameter)) - { - return tn; - } - return determine_type(ctn.compiled_type, param_types, method_param_types); - } - - private static bool CheckIfTypeDependsOnUndeducedGenericParameters(type_node formalType, type_node[] deduced) //lroman - { - if (formalType.generic_function_container != null) - { - var par_num = formalType.generic_param_index; - return deduced[par_num] == null; - } - - var formalRef = formalType as ref_type_node; - if (formalRef != null) - { - return CheckIfTypeDependsOnUndeducedGenericParameters(formalRef.pointed_type, deduced); - } - - var formalIi = formalType.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; - if (formalIi != null) - { - return CheckIfTypeDependsOnUndeducedGenericParameters(formalIi.element_type, deduced); - } - - if (formalType.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.set_type) - { - return CheckIfTypeDependsOnUndeducedGenericParameters(formalType.element_type, deduced); - } - - if (formalType.IsDelegate) - { - var dii = formalType.get_internal_interface(internal_interface_kind.delegate_interface) as delegate_internal_interface; - var paramCount = dii.parameters.Count; - for (var i = 0; i < paramCount; i++) - { - if (!CheckIfTypeDependsOnUndeducedGenericParameters(dii.parameters[i].type, deduced)) - { - return false; - } - } - return CheckIfTypeDependsOnUndeducedGenericParameters(dii.return_value_type, deduced); - } - - if (formalType.is_generic_type_instance) - { - var pcount = formalType.instance_params.Count; - for (var k = 0; k < pcount; ++k) - { - if (!CheckIfTypeDependsOnUndeducedGenericParameters(formalType.instance_params[k], deduced)) - { - return false; - } - } - return true; - } - return false; - } - - //Сохранить типы параметров и тип возвращаемого значения лямбд перед попыткой вычисления реального типа возвращаемого знаяения лямбд - private static Dictionary, type_node>> SaveLambdasStates(IEnumerable lambdaParametersList) - { - var savedLambdasStates = new Dictionary, type_node>>(); - - foreach (var lambda in lambdaParametersList) - { - var parsTypes = new List(); - if (lambda.formal_parameters != null && lambda.formal_parameters.params_list != null && - lambda.formal_parameters.params_list.Count > 0) - { - parsTypes.AddRange(lambda - .formal_parameters - .params_list - .Select(t => - { - var lambdaNode = t.vars_type as lambda_inferred_type; - if (lambdaNode == null) - { - return null; - } - return lambdaNode.real_type is lambda_any_type_node - ? (lambda_any_type_node) lambdaNode.real_type - : null; - })); - } - - type_node retType; - var lambdaResNode = lambda.return_type as lambda_inferred_type; - if (lambdaResNode == null) - { - retType = null; - } - else - { - retType = lambdaResNode.real_type is lambda_any_type_node - ? (lambda_any_type_node)lambdaResNode.real_type - : null; - } - - savedLambdasStates.Add(lambda.lambda_name, - new Tuple, type_node>(parsTypes, retType)); - } - - return savedLambdasStates; - } - - //Восстановление типов в исходное состояние на случай подстановки других типов - private static void RestoreLambdasStates(List lambdaParametersList, - Dictionary, type_node>> savedLambdasStates) - { - for (var i = 0; i < lambdaParametersList.Count; i++) - { - var state = savedLambdasStates[lambdaParametersList[i].lambda_name]; - var lambdaPar = lambdaParametersList[i]; - for (var k = 0; k < state.Item1.Count; k++) - { - var lambdaNode = lambdaPar.formal_parameters.params_list[k].vars_type as lambda_inferred_type; - if (lambdaNode != null - && state.Item1[k] != null) - { - lambdaNode.real_type = state.Item1[k]; - } - } - - var resLambdaNode = lambdaPar.return_type as lambda_inferred_type; - if (resLambdaNode != null - && state.Item2 != null) - { - resLambdaNode.real_type = state.Item2; - } - } - } - - //Попытка вычислить типы после подстановки типов формальных параметров - public static bool TryToDeduceTypesInLambda(function_lambda_definition lambda_syntax_node, - delegate_internal_interface formal_delegate, - type_node[] deduced, List nils, - out Exception exception_on_body_compilation) - { - var there_are_undeduced_params = false; - var param_counter = 0; - var visitor = SystemLibrary.SystemLibrary.syn_visitor; - var result = true; - exception_on_body_compilation = null; - - /*if (lambda_syntax_node.formal_parameters == null - || lambda_syntax_node.formal_parameters.params_list == null - || lambda_syntax_node.formal_parameters.params_list.Count == 0) - { - return false; - }*/ - 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); - lambda_syntax_node.lambda_name = aux_name; - - try - { - visitor.visit(lambda_syntax_node); //пробуем скомпилировать тело лямбды, вычислим тип возвращаемого значения - } - catch (Exception exc) - { - exception_on_body_compilation = exc; // Если произошло исключение то запишем его в выходной параметр, оно потом будет обработано вызывающим методом - result = false; - } - finally - { - var context = visitor.context; - - //Далее надо удалить ненужный узел из списка функций - LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, lambda_syntax_node); - - lambda_syntax_node.lambda_name = lambdaName; - lambda_syntax_node.lambda_visit_mode = fl; - - if (result) - { - if (formal_delegate == null) // SSM 5.12.15 - { - result = false; - } - else - { - if (formal_delegate.return_value_type==null) // SSM 19/04/16 - эта проверка в связи с падением при передаче функции вместо процедуры в качестве функционального параметра: a.Foreach(x->1) - { - result = false; - } - else if (!DeduceInstanceTypes(formal_delegate.return_value_type, - (type_node)((lambda_inferred_type)lambda_syntax_node.return_type).real_type, - deduced, nils)) //Выводим дженерик-параметры после того как вычислили тип возвращаемого значения - { - result = false; - } - } - } - } - } - return result; - } - - public static function_node DeduceFunction(function_node func, expressions_list fact, bool alone, 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; - type_node[] deduced = new type_node[generic_type_params_count]; - List nils = new List(); - int count_params_to_see = fact_count; - - var lambda_syntax_nodes = new Dictionary(); //lroman Получим список фактических параметров-лямбд текущей вызываемой подпрограммы - if (syntax_nodes_parameters != null - && syntax_nodes_parameters.Count > 0) //lroman - { - lambda_syntax_nodes = syntax_nodes_parameters - .OfType() - .ToDictionary(f => f.lambda_name, f => f); - } - - var lambda_in_parameters = lambda_syntax_nodes.Count > 0; - var saved_lambdas_states = SaveLambdasStates(lambda_syntax_nodes.Select(ld => ld.Value)); // Сохраним типы лямбды перед вычислениями - - if (fact_count < formal_count) - { - //Сравниваем количества параметров - parameter par = formal[fact_count]; - if (par.default_value == null && !par.is_params) - { - if (alone) - throw new NoFunctionWithSameParametresNum(loc, alone, func); - return null; - } - } - else - { - type_node last_params_type = null; - bool last_is_params = false; - parameter par = null; - if (formal_count > 0) - { - par = formal[formal_count - 1]; - last_is_params = par.is_params; - } - if (last_is_params) - { - array_internal_interface aii = par.type.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; - last_params_type = aii.element_type; - } - if (fact_count > formal_count) - { - //Фактических больше, чем формальных. Последний формальный должен быть params... - if (last_is_params) - { - for (int i = formal_count - 1; i < fact_count; ++i) - { - //Проверяем фактические, попадающие под params... - if (!DeduceInstanceTypes(last_params_type, fact[i].type, deduced, nils)) - { - if (alone && 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)) - 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; - if (tn.element_type != null && tn.type_special_kind != SemanticTree.type_special_kind.array_wrapper) - tn = tn.element_type; - if (!DeduceInstanceTypes(last_params_type, tn, deduced, nils)) - { - if (alone) - throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); - return null; - } - } - count_params_to_see = formal_count - 1; - } - } - bool need_params_work = (count_params_to_see > 0 && formal[count_params_to_see - 1].is_params); - if (need_params_work) - { - count_params_to_see -= 1; - } - - var continue_trying_to_infer_types = true; - Dictionary formal_delegates = null; - - while (continue_trying_to_infer_types) //Продолжаем пытаться вычислить типы до тех пор пока состояние о выведенных типах не будет отличаться от состояния на предыдущей итерации - { - var previous_deduce_state = deduced // Текущее состояние выведенных на данный момент типов. Простой список индексов с уже выведенными типами из массива deduced - .Select((t, i) => new { Type = t, Index = i }) - .Where(t => t.Type != null) - .Select(t => t.Index) - .ToArray(); - - for (int i = 0; i < count_params_to_see; ++i) - { - if (alone && fact[i].type is delegated_methods && (fact[i].type as delegated_methods).empty_param_method != null && DeduceInstanceTypes(formal[i].type, (fact[i].type as delegated_methods).empty_param_method.type, deduced, nils)) - continue; - else - if (!DeduceInstanceTypes(formal[i].type, fact[i].type, deduced, nils)) - { - if (alone && fact[i].type is delegated_methods && (fact[i].type as delegated_methods).empty_param_method != null) - { - if (DeduceInstanceTypes(formal[i].type, (fact[i].type as delegated_methods).empty_param_method.type, deduced, nils)) - continue; - } - if (alone) - throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); - RestoreLambdasStates(lambda_syntax_nodes.Values.ToList(), saved_lambdas_states); - return null; - } - - } - - if (lambda_in_parameters) - { - if (formal_delegates == null) - { - formal_delegates = new Dictionary(); - - for (int i = 0; i < count_params_to_see; ++i) - //Выделим из формальных параметров те, которые соотвтествуют фактическим параметрам-лямбдам - { - var lambda_func = fact[i].type as delegated_methods; - if (lambda_func != null - && lambda_func.proper_methods.Count == 1 - && LambdaHelper.IsLambdaName(lambda_func.proper_methods[0].simple_function_node.name)) - { - formal_delegates.Add(LambdaHelper.GetLambdaNamePartWithoutGenerics(lambda_func.proper_methods[0].simple_function_node.name), - formal[i].type.get_internal_interface( - internal_interface_kind.delegate_interface) as - delegate_internal_interface); - } - } - } - - foreach (var formal_delegate in formal_delegates) - // Перебираем все полученные формальные параметры, соответствующие фактическим лямбдам - { - var lambda_syntax_node = lambda_syntax_nodes[formal_delegate.Key]; - Exception on_lambda_body_compile_exception; - // Исключение которое может возникнуть в результате компиляции тела лямбды если мы выберем неправильные типы параметров - var b = TryToDeduceTypesInLambda(lambda_syntax_node, formal_delegate.Value, deduced, nils, - out on_lambda_body_compile_exception); - 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)) - { - //Второй шанс. Учитываем слово params. - deduced = tmp_deduced; - nils = tmp_nils; - if (!DeduceInstanceTypes(formal[count_params_to_see].type.element_type, fact[count_params_to_see].type, deduced, nils)) - { - if (alone) - throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); - return null; - } - } - } - //Вывели всё, что могли. Теперь проверяем. - for (int i = 0; i < generic_type_params_count; ++i) - { - if (deduced[i] == null) - { - if (alone) - throw new SimpleSemanticError(loc, "CAN_NOT_DEDUCE_TYPE_PARAMS_FROM_CALL_{0}", func.name); - return null; - } - } - foreach (int num in nils) - { - if (!type_table.is_with_nil_allowed(deduced[num])) - { - if (alone) - throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); - return null; - } - } - foreach (type_node tt in deduced) - { - CompilationErrorWithLocation check_err = generic_parameter_eliminations.check_type_generic_useful(tt, loc); - if (check_err != null) - { - if (alone) - throw check_err; - return null; - } - } - //Итак, вывели все параметры. Теперь инстанцируем. - List deduced_list = new List(generic_type_params_count); - deduced_list.AddRange(deduced); - return func.get_instance(deduced_list, alone, loc); - } - - //Выведение типов - public static bool DeduceInstanceTypes(type_node formal_type, type_node fact_type, type_node[] deduced, List nils) - { - if (fact_type == null)//issue #347 - return false; - if (formal_type.generic_function_container == null && fact_type.generic_function_container != null) - { - //swap - type_node tmp = formal_type; - formal_type = fact_type; - fact_type = tmp; - } - //Формальный тип - generic-параметр функции. Выводим. - if (formal_type.generic_function_container != null) - { - int par_num = formal_type.generic_param_index; - if (fact_type.semantic_node_type == semantic_node_type.null_type_node) - { - nils.Add(par_num); - return true; - } - if (deduced[par_num] == null) - { - //Этот тип-параметр ещё не был выведен. - if (fact_type is delegated_methods && (fact_type as delegated_methods).empty_param_method != null && (fact_type as delegated_methods).empty_param_method.ret_type != null) - fact_type = (fact_type as delegated_methods).empty_param_method.ret_type; - //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); - } - //безразмерные массивы - array_internal_interface formal_ii = formal_type.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; - if (formal_ii != null) - { - array_internal_interface fact_ii = fact_type.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; - if (fact_ii == null) - { - goto eq_cmp; - } - return DeduceInstanceTypes(formal_ii.element_type, fact_ii.element_type, deduced, nils); - } - //множества - if (formal_type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.set_type) - { - if (fact_type.type_special_kind != PascalABCCompiler.SemanticTree.type_special_kind.set_type) - { - goto eq_cmp; - } - return DeduceInstanceTypes(formal_type.element_type, fact_type.element_type, deduced, nils); - } - //множества - if (formal_type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.typed_file) - { - if (fact_type.type_special_kind != PascalABCCompiler.SemanticTree.type_special_kind.typed_file) - { - goto eq_cmp; - } - return DeduceInstanceTypes(formal_type.element_type, fact_type.element_type, deduced, nils); - } - //Делегаты - if (formal_type.IsDelegate) - { - //Если текущий параметр - лямбда, то просто выводим дженерик-параметры из типов, которые уже известны. Не трогаем lambda_any_type_node. Остальное выведется в цикле выше - var lambda_func = fact_type as delegated_methods; - if (lambda_func != null - && lambda_func.proper_methods.Count == 1 - && LambdaHelper.IsLambdaName(lambda_func.proper_methods[0].simple_function_node.name)) - { - var dii = formal_type.get_internal_interface(internal_interface_kind.delegate_interface) as delegate_internal_interface; - var fact_func = lambda_func.proper_methods[0].simple_function_node; - - if (fact_func.parameters.Count != dii.parameters.Count) - { - goto eq_cmp; - } - - var param_count = fact_func.parameters.Count; - - for (var i = 0; i < param_count; i++) - { - if (fact_func.parameters[i].parameter_type != dii.parameters[i].parameter_type || - fact_func.parameters[i].is_params != dii.parameters[i].is_params) - goto eq_cmp; - } - for (var i = 0; i < param_count; i++) - { - if (fact_func.parameters[i].type is lambda_any_type_node) - { - continue; - } - // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка - if (!DeduceInstanceTypes(dii.parameters[i].type, fact_func.parameters[i].type, deduced, nils)) - //if (!DeduceInstanceTypes(fact_func.parameters[i].type, dii.parameters[i].type, deduced, nils)) - { - goto eq_cmp; - } - } - if (fact_func.return_value_type == null && dii.return_value_type == null) - { - //ok - } - else if (fact_func.return_value_type is lambda_any_type_node) //lroman// - { - if (dii.return_value_type == null) - { - goto eq_cmp; - } - return true; - } - // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка - else if (fact_func.return_value_type == null || !DeduceInstanceTypes(dii.return_value_type, fact_func.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable -// else if (fact_func.return_value_type == null || !DeduceInstanceTypes(fact_func.return_value_type, dii.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable - { - goto eq_cmp; - } - return true; - } - - if (!convertion_data_and_alghoritms.eq_type_nodes(formal_type, fact_type, true)) - { - delegate_internal_interface dii = formal_type.get_internal_interface(internal_interface_kind.delegate_interface) as delegate_internal_interface; - delegated_methods dm = fact_type as delegated_methods; - function_node fact_func = null; - if (dm != null && dm.proper_methods.Count == 1) - fact_func = 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_func = sil[0].sym_info as function_node; - } - - if (fact_func != null) - { - if (fact_func.parameters.Count != dii.parameters.Count) - { - goto eq_cmp; - } - int param_count = fact_func.parameters.Count; - for (int i = 0; i < param_count; i++) - { - if (fact_func.parameters[i].parameter_type != dii.parameters[i].parameter_type || - fact_func.parameters[i].is_params != dii.parameters[i].is_params) - goto eq_cmp; - } - for (int i = 0; i < param_count; i++) - { - if (!DeduceInstanceTypes(dii.parameters[i].type, fact_func.parameters[i].type, deduced, nils)) // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка - //if (!DeduceInstanceTypes(fact_func.parameters[i].type, dii.parameters[i].type, deduced, nils)) - { - goto eq_cmp; - } - } - if (fact_func.return_value_type == null && dii.return_value_type == null) - { - //ok - } - else if (fact_func.return_value_type is lambda_any_type_node && dii.return_value_type == null) //lroman// - { - goto eq_cmp; - } - // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка - else if (fact_func.return_value_type == null || !DeduceInstanceTypes(dii.return_value_type, fact_func.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable -// else if (fact_func.return_value_type == null || !DeduceInstanceTypes(fact_func.return_value_type, dii.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable - { - goto eq_cmp; - } - return true; - } - } - if (fact_type.IsDelegate && fact_type.semantic_node_type == semantic_node_type.delegated_method) - return true; - //goto eq_cmp; - } - //Инстанции дженериков - if (formal_type.is_generic_type_instance) - { - //if () goto eq_cmp; - type_node fact_type_converted; //Сюда будет записан фактический тип или интерфейс, к которому он приводится - if (!fact_type.is_generic_type_instance || formal_type.original_generic != fact_type.original_generic) - { - //if (!formal_type.IsInterface) goto eq_cmp; - fact_type_converted = null; - 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) goto eq_cmp; - } - else - { - fact_type_converted = fact_type; - } - int pcount = formal_type.instance_params.Count; - for (int k = 0; k < pcount; ++k) - { - if (!DeduceInstanceTypes(formal_type.instance_params[k], fact_type_converted.instance_params[k], deduced, nils)) - { - goto eq_cmp; - } - } - return true; - } - //Если совпадают - всё хорошо. - eq_cmp: - if (convertion_data_and_alghoritms.eq_type_nodes(formal_type, fact_type, true)) - { - return true; - } - possible_type_convertions ptc = type_table.get_convertions(fact_type, formal_type); - if (ptc.first != null) - { - return true; - } - return false; - } - - public static string MakePseudoInstanceName(string name, List param_types, bool type_name) - { - string rez; - if (type_name) - { - int last = name.LastIndexOf(compiler_string_consts.generic_params_infix); - if (last < 0) - { - rez = name; - } - else - { - rez = name.Substring(0, last); - } - } - else - { - rez = name; - } - bool first = true; - foreach (type_node tnode in param_types) - { - rez += ((first) ? "<" : ",") + tnode.PrintableName; - first = false; - } - rez += ">"; - return rez; - } - - public static bool type_has_default_ctor(type_node tn, bool find_protected_ctors) - { - if (tn.is_generic_parameter && tn.base_type != null && tn.base_type.IsAbstract) - return false; - List sil = tn.find_in_type(compiler_string_consts.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; - } - - public List generic_parameters - { - get - { - if (_generic_parameters == null) - { - _generic_parameters = new List(_instance_params.Count); - foreach (type_node tn in _instance_params) - { - _generic_parameters.Add(tn); - } - } - return _generic_parameters; - } - } - - private List temp_names = new List(3); - - public override void add_name(string name, SymbolInfo si) - { - temp_names.Add(si); - } - - protected void AddMember(object original, object converted) - { - 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; - SemanticTree.IClassMemberNode orig_member = orig_fn as SemanticTree.IClassMemberNode; - common_method_node cmn = new common_method_node( - orig_fn.name, - //generic_convertions.determine_type(orig_fn.return_value_type, _instance_params, false), - null, - loc, this, orig_member.polymorphic_state, orig_member.field_access_level, - null); - if (orig_fn.is_generic_function) - { - List orig_tpars = orig_fn.get_generic_params_list(); - int type_count = orig_tpars.Count; - cmn.generic_params = new List(orig_tpars.Count); - foreach (type_node t in orig_tpars) - { - common_type_node par = new common_type_node(t.name, PascalABCCompiler.SemanticTree.type_access_level.tal_public, - null, SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.symbol_table.CreateInterfaceScope(null, SystemLibrary.SystemLibrary.object_type.Scope, null), null); - SystemLibrary.SystemLibrary.init_reference_type(par); - par.SetBaseType(SystemLibrary.SystemLibrary.object_type); - cmn.generic_params.Add(par); - par.generic_function_container = cmn; - } - meth_inst_pars = cmn.get_generic_params_list(); - List gpes = orig_fn.parameters_eliminations; - for (int i = 0; i < type_count; ++i) - { - common_type_node p = (common_type_node)(meth_inst_pars[i]); - generic_parameter_eliminations gpe = gpes[i]; - p.SetBaseType(generic_convertions.determine_type( - generic_convertions.determine_type(gpe.base_class, _instance_params, false), - meth_inst_pars, true)); - p.is_class = gpe.is_class; - p.internal_is_value = gpe.is_value; - foreach (type_node interf in gpe.implementing_interfaces) - { - type_table.AddInterface(p, generic_convertions.determine_type( - generic_convertions.determine_type(interf, _instance_params, false), - meth_inst_pars, true), null); - } - if (gpe.has_default_ctor) - { - generic_parameter_eliminations.add_default_ctor(p); - } - } - } - cmn.parameters.AddRange(make_parameters(orig_fn.parameters, cmn)); - if (orig_fn.is_generic_function) - { - foreach (common_parameter cp in cmn.parameters) - { - cp.type = generic_convertions.determine_type(cp.type, meth_inst_pars, true); - } - } - common_method_node common_orig = orig_fn as common_method_node; - if (common_orig != null) - { - cmn.num_of_default_variables = common_orig.num_of_default_variables; - } - compiled_constructor_node compiled_orig = orig_fn as compiled_constructor_node; - cmn.is_constructor = (compiled_orig != null || - (common_orig != null && common_orig.is_constructor)); - cmn.return_value_type = generic_convertions.determine_type(orig_fn.return_value_type, _instance_params, false); - if (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); - } - if (orig_fn is common_function_node) - { - cmn.return_variable = (orig_fn as common_function_node)?.return_variable; - } - return cmn; - } - - public override List instance_params - { - get - { - return _instance_params; - } - set - { - _instance_params = value; - } - } - - public override bool is_generic_type_instance - { - get - { - return true; - } - } - - protected void AddPropertyAccessors(property_node pn) - { - if (pn.get_function != null) - { - if (_members[pn.get_function] == null) - { - ConvertMember(pn.get_function); - } - } - if (pn.set_function != null) - { - if (_members[pn.set_function] == null) - { - ConvertMember(pn.set_function); - } - } - } - - protected common_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 - ); - 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) - { - //Преобразуем найденный член класса. - 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); - if (compr_type == null) - { - compiled_function_node cfn = orig_node as compiled_function_node; - if (cfn == null) - { - return orig_node; - } - compiled_type_node cct = tn as compiled_type_node; - type_node inst_type = this; - do - { - inst_type = inst_type.base_type; - } - while (inst_type.semantic_node_type != semantic_node_type.compiled_type_node || - (inst_type != cct && inst_type.original_generic != cct)); - - - MethodInfo[] meths = cct._compiled_type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | - BindingFlags.Static | BindingFlags.Instance); - int num = System.Array.IndexOf(meths, cfn.method_info); - - MethodInfo mi = ((compiled_type_node)inst_type)._compiled_type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | - BindingFlags.Static | BindingFlags.Instance)[num]; - return compiled_function_node.get_compiled_method(mi); - } - else - return compr_type.ConvertMember(orig_node); - // - } - else - return orig_node; - } - SemanticTree.ILocated orig_loc = orig_node as SemanticTree.ILocated; - location loc = (orig_loc == null) ? null : (orig_loc.Location as location); - switch (orig_node.general_node_type) - { - case general_node_type.constant_definition: - constant_definition_node orig_cdn = orig_node as constant_definition_node; - rez_node = new class_constant_definition( - orig_cdn.name, orig_cdn.const_value, - loc, this, orig_member.field_access_level); - break; - case general_node_type.variable_node: - var_definition_node orig_cf = (var_definition_node)(orig_node); - rez_node = new class_field(orig_cf.name, - generic_convertions.determine_type(orig_cf.type, _instance_params, false), - this, orig_member.polymorphic_state, - orig_member.field_access_level, loc); - break; - case general_node_type.property_node: - property_node orig_pn = (property_node)(orig_node); - rez_node = make_property(orig_pn, loc); - break; - case general_node_type.function_node: - function_node orig_fn = (function_node)(orig_node); - rez_node = make_method(orig_fn, loc); - break; - case general_node_type.event_node: - //(ssyy) Не знаю, что тут делать - 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) - { - // aab 13.06.19 begin - // Поправил странное поведение для локальных переменных, у которых не generic тип - // Исправление для #1993 +// Copyright (c) Ivan Bondarev, Stanislav Mihalkovich (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +//Здесь описана реализация generic-типов +//Файлом владеет ssyy. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using PascalABCCompiler.SyntaxTree; +using PascalABCCompiler.TreeConverter; + +namespace PascalABCCompiler.TreeRealization +{ + //Вспомогательный класс для реализации generic-типов + public class generic_type_instance_info + { + public List param_types; + public generic_instance_type_node pseudo_instance; + + public generic_type_instance_info(List _param_types, generic_instance_type_node _pseudo_instance) + { + param_types = _param_types; + pseudo_instance = _pseudo_instance; + } + } + + public class generic_function_instance_info + { + public List param_types; + public function_node pseudo_instance; + + public generic_function_instance_info(List _param_types, function_node _pseudo_instance) + { + param_types = _param_types; + pseudo_instance = _pseudo_instance; + } + } + + public class generic_parameter_eliminations + { + public bool is_class = false; + public bool is_value = false; + public bool has_default_ctor = false; + public type_node base_class = null; + public List implementing_interfaces = null; + + public static void add_default_ctor(common_type_node param) + { + common_method_node cnode = new common_method_node( + compiler_string_consts.default_constructor_name, param, null, + param, SemanticTree.polymorphic_state.ps_common, + SemanticTree.field_access_level.fal_public, null); + cnode.is_constructor = true; + param.methods.AddElement(cnode); + param.add_name(compiler_string_consts.default_constructor_name, new SymbolInfo(cnode)); + param.has_default_constructor = true; + } + + public static List make_eliminations_common(List generic_params) + { + List _parameters_eliminations = new List(); + foreach (type_node t in generic_params) + { + generic_parameter_eliminations gpe = new generic_parameter_eliminations(); + gpe.has_default_ctor = generic_convertions.type_has_default_ctor(t, false); + gpe.is_class = t.is_class; + gpe.is_value = t.is_value; + gpe.base_class = t.base_type; + gpe.implementing_interfaces = new List(t.ImplementingInterfaces.Count); + foreach (type_node interf in t.ImplementingInterfaces) + { + gpe.implementing_interfaces.Add(interf); + } + _parameters_eliminations.Add(gpe); + } + return _parameters_eliminations; + } + + public static List make_eliminations_compiled(Type[] pars) + { + List _parameters_eliminations = new List(); + foreach (Type t in pars) + { + generic_parameter_eliminations gpe = new generic_parameter_eliminations(); + gpe.has_default_ctor = + ((t.GenericParameterAttributes & + GenericParameterAttributes.DefaultConstructorConstraint) != 0); + gpe.is_class = + ((t.GenericParameterAttributes & + GenericParameterAttributes.ReferenceTypeConstraint) != 0); + gpe.is_value = + ((t.GenericParameterAttributes & + GenericParameterAttributes.NotNullableValueTypeConstraint) != 0); + gpe.base_class = compiled_type_node.get_type_node(t.BaseType); + Type[] net_interf = t.GetInterfaces(); + gpe.implementing_interfaces = new List(net_interf.Length); + foreach (Type net_t in net_interf) + { + gpe.implementing_interfaces.Add(compiled_type_node.get_type_node(net_t)); + } + _parameters_eliminations.Add(gpe); + } + return _parameters_eliminations; + } + + public static CompilationErrorWithLocation check_type_generic_useful(type_node tn, location loc) + { + if (tn == null) + { + return new SimpleSemanticError(loc, "TYPE_NAME_EXPECTED"); + } + if (tn.IsPointer) + { + return new SimpleSemanticError(loc, "CANNOT_USE_POINTER_AS_GENERIC_ARGUMENT"); + } + switch (tn.type_special_kind) + { + case PascalABCCompiler.SemanticTree.type_special_kind.diap_type: + return new SimpleSemanticError(loc, "CANNOT_USE_DIAPASON_AS_GENERIC_ARGUMENT"); + case PascalABCCompiler.SemanticTree.type_special_kind.typed_file: + return new SimpleSemanticError(loc, "CANNOT_USE_TYPED_FILE_AS_GENERIC_ARGUMENT"); + case PascalABCCompiler.SemanticTree.type_special_kind.short_string: + return new SimpleSemanticError(loc, "CANNOT_USE_SHORT_STRING_AS_GENERIC_ARGUMENT"); + } + /*if (tn == SystemLibrary.SystemLibrary.void_type) + { + return new VoidNotValid(loc); + }*/ + SystemLibrary.SystemLibrary.syn_visitor.check_for_type_allowed(tn,loc); + 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.is_class && !tn.is_class && !(tn.base_type != null && tn.base_type.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); + } + if (gpe.base_class != null && gpe.base_class != SystemLibrary.SystemLibrary.object_type) + { + type_node base_type = generic_convertions.determine_type(gpe.base_class, tparams, method_param_types); + if (base_type != tn && !type_table.is_derived(base_type, tn) && !tn.is_generic_parameter) + { + return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_BE_DERIVED_FROM_{1}", tn.PrintableName, base_type.name); + } + } + foreach (type_node interf in gpe.implementing_interfaces) + { + type_node di = generic_convertions.determine_type(interf, tparams, method_param_types); + if (di != tn && + (tn.ImplementingInterfaces == null || + !type_table.is_derived(di, tn))) + { + return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_IMPLEMENT_INTERFACE_{1}", tn.PrintableName, di.name); + } + } + if (tn.IsStatic) + return new SimpleSemanticError(null, "USING_STATIC_CLASS_NOT_VALID"); + if (gpe.has_default_ctor) + { + if (tn.IsAbstract || 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 Hashtable generic_instances = new Hashtable(); + + public static syntax_tree_visitor visitor; + + public static List get_type_instances(type_node original_generic_type) + { + List instances = generic_instances[original_generic_type] as List; + if (instances == null) + { + instances = new List(); + generic_instances.Add(original_generic_type, instances); + } + return instances; + } + + public static List get_function_instances(function_node original_generic_function) + { + List instances = generic_instances[original_generic_function] as List; + if (instances == null) + { + instances = new List(); + generic_instances.Add(original_generic_function, instances); + } + return instances; + } + + public static type_node find_type_instance(List _generic_instances, List param_types) + { + int count = param_types.Count; + foreach (generic_type_instance_info gii in _generic_instances) + { + bool equals = true; + for (int i = 0; equals && i < count; ++i) + { + equals = (param_types[i] == gii.param_types[i]); + } + if (equals) + { + //Такая инстанция уже есть + return gii.pseudo_instance; + } + } + return null; + } + + public static void check_instances_are_correct(List insts) + { + int num; + foreach (type_instance_and_location tia in insts) + { + List gpes = tia.instance.original_generic.parameters_eliminations; + CompilationErrorWithLocation err = generic_parameter_eliminations.check_type_list(tia.instance.instance_params, gpes, false, out num); + if (err != null) + { + err.loc = tia.loc; + throw err; + } + } + } + + public static function_node find_function_instance(List _generic_instances, List param_types) + { + int count = param_types.Count; + foreach (generic_function_instance_info gii in _generic_instances) + { + bool equals = true; + for (int i = 0; equals && i < count; ++i) + { + equals = (param_types[i] == gii.param_types[i]); + } + if (equals) + { + //Такая инстанция уже есть + return gii.pseudo_instance; + } + } + return null; + } + + public static void init_generic_instance(type_node original, generic_instance_type_node instance, /*SymbolTable.ClassScope instance_scope,*/ List param_types) + { + instance.IsInterface = original.IsInterface; + instance.is_class = original.is_class; + instance.internal_is_value = original.is_value; + instance.SetIsSealed(original.IsSealed); + instance.IsDelegate = original.IsDelegate; + instance.type_special_kind = original.type_special_kind; + + //Определяем базовый тип + type_node btype = determine_type( + original.base_type, param_types, false); + instance.SetBaseTypeIgnoringScope(btype); + + //instance._scope = new SymbolTable.GenericTypeInstanceScope(instance, instance.original_generic.Scope, btype.Scope); + + foreach (type_node interf in original.ImplementingInterfaces) + { + instance.ImplementingInterfaces.Add( + determine_type(interf, param_types, false) + ); + } + + SystemLibrary.SystemLibrary.init_reference_type(instance); + instance.conform_basic_functions(); + //(ssyy) Нужно, чтобы добавились конструкторы + //ctnode.find_in_type(compiler_string_consts.default_constructor_name); + instance.instance_params = param_types; + + property_node orig_pn = original.default_property_node; + if (orig_pn != null) + { + if (orig_pn.comprehensive_type == original) + { + //Свойство по умолчанию описано в оригинальном коде generic-a; + //конвертируем его + instance.default_property = instance.ConvertMember(orig_pn) as common_property_node; + } + else + { + //Свойство по умолчанию описано в каком-то предке оригинального generic-a + if (orig_pn.comprehensive_type.is_generic_type_definition) + { + instance.default_property = instance.find_instance_type_from(orig_pn.comprehensive_type).default_property; + } + } + } + + var shouldAddToAllTypeInstances = true; + if (LambdaHelper.processingLambdaParametersForTypeInference != 0) + { + foreach (var par in instance.generic_parameters) + { + if (par is lambda_any_type_node) + { + shouldAddToAllTypeInstances = false; + break; + } + } + } + + if (shouldAddToAllTypeInstances) //lroman// Если зашли сюда при выведении типов параметров лямбды, то тип инстанцироваться может с типом lambda_any_type_node. Поэтому, если выводим типы. То данную инстанцию не добавляем + { + if (instance.instance_params[0] is ienumerable_auto_type) // SSM 10.07.16 (yields) в эту таблицу не включаются типы IEnumerable, т.к. потом они всё равно автовыводятся + { + //instance = instance; + } + else + { + generic_convertions.all_type_instances.Add(instance); + } + } + + internal_interface ii = original.get_internal_interface(internal_interface_kind.delegate_interface); + if (ii != null) + { + delegate_internal_interface dii = ii as delegate_internal_interface; + common_method_node inv = instance.ConvertMember(dii.invoke_method) as common_method_node; + common_method_node constr = instance.ConvertMember(dii.constructor) as common_method_node; + constr.function_code = new runtime_statement(SemanticTree.runtime_statement_type.ctor_delegate, null); + delegate_internal_interface converted_dii = new delegate_internal_interface(inv.return_value_type, + inv, constr); + converted_dii.parameters.AddRange(inv.parameters); + instance.add_internal_interface(converted_dii); + } + } + + public static void reset_generics() + { + generic_instances.Clear(); + all_type_instances.Clear(); + all_function_instances.Clear(); + } + + //Определяет, как должен выглядеть тип в семантическом дереве. + //Возвращает этот тип. + public static type_node determine_type(Type t, List param_types, bool method_param_types) + { + if (t == null) return null; + if (t.IsGenericParameter) + { + //Если мы определяем тип-параметры метода, нет необходимости рассматривать + //тип-параметры типа, и наоборот. Это для поддержки generic-методов в + //generic-типе. + if (method_param_types == (t.DeclaringMethod != null)) + { + return param_types[t.GenericParameterPosition]; + } + else + { + return compiled_type_node.get_type_node(t); + } + } + if (t.IsGenericType) + { + //Формируем список типов-параметров + Type[] args = t.GetGenericArguments(); + List semantic_args = new List(); + foreach (Type arg in args) + { + semantic_args.Add(determine_type(arg, param_types, method_param_types)); + } + + //Получаем описание generic-класса + Type def = t.GetGenericTypeDefinition(); + compiled_type_node ct_def = compiled_type_node.get_type_node(def); + + //Создаём псевдо-инстанцию + return ct_def.get_instance(semantic_args); + } + + //Для типов, не имеющих отношения к generic-типам. + return compiled_type_node.get_type_node(t); + } + + public static type_node determine_type(type_node tn, List param_types, bool method_param_types) + { + if (tn == null) return null; + ref_type_node rtn = tn as ref_type_node; + if (rtn != null) + { + type_node ptype = generic_convertions.determine_type(rtn.pointed_type, param_types, method_param_types); + if (ptype == rtn.pointed_type) return tn; + ref_type_node rez_ref = ptype.ref_type; + rez_ref.loc = rtn.loc; + return rez_ref; + } + array_internal_interface ii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; + if (ii != null) + { + type_node elem_tp = determine_type(ii.element_type, param_types, method_param_types); + if (elem_tp != ii.element_type) + { + return SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.type_constructor.create_unsized_array(elem_tp, null, ii.rank, null); + } + return tn; + } + common_type_node comm_type = tn as common_type_node; + if (comm_type != null) + { + if (comm_type.is_generic_parameter) + { + if (method_param_types && comm_type.generic_function_container != null) + { + return param_types[comm_type.generic_param_index]; + } + else if (!method_param_types && comm_type.generic_type_container != null) + { + return param_types[comm_type.generic_param_index]; + } + return tn; + } + generic_instance_type_node gitn = tn as generic_instance_type_node; + if (gitn != null) + { + List semantic_args = new List(); + List gitn_inst_parameters = gitn.instance_params; + foreach (type_node arg in gitn_inst_parameters) + { + semantic_args.Add(determine_type(arg, param_types, method_param_types)); + } + return gitn.original_generic.get_instance(semantic_args); + } + if (comm_type.is_generic_type_definition) + { + return comm_type.get_instance(param_types); + } + if (comm_type.type_special_kind == SemanticTree.type_special_kind.array_kind) + { + type_node elem_tp = determine_type(comm_type.element_type, param_types, method_param_types); + if (elem_tp != comm_type.element_type) + { + return SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.type_constructor.create_unsized_array(elem_tp, null, 1, comm_type.loc); + } + return tn; + } + if (comm_type.type_special_kind == SemanticTree.type_special_kind.set_type) + { + type_node elem_tp = determine_type(comm_type.element_type, param_types, method_param_types); + if (elem_tp != comm_type.element_type) + { + return SystemLibrary.SystemLibrary.syn_visitor.context.create_set_type(elem_tp, comm_type.loc); + } + return tn; + } + if (comm_type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.typed_file) + { + type_node elem_tp = determine_type(comm_type.element_type, param_types, method_param_types); + if (elem_tp != comm_type.element_type) + { + return SystemLibrary.SystemLibrary.syn_visitor.context.create_typed_file_type(elem_tp, comm_type.loc); + } + return tn; + } + return tn; + } + compiled_type_node ctn = tn as compiled_type_node; + if (ctn == null || (!ctn.compiled_type.IsGenericType && !ctn.compiled_type.IsGenericParameter)) + { + return tn; + } + return determine_type(ctn.compiled_type, param_types, method_param_types); + } + + private static bool CheckIfTypeDependsOnUndeducedGenericParameters(type_node formalType, type_node[] deduced) //lroman + { + if (formalType.generic_function_container != null) + { + var par_num = formalType.generic_param_index; + return deduced[par_num] == null; + } + + var formalRef = formalType as ref_type_node; + if (formalRef != null) + { + return CheckIfTypeDependsOnUndeducedGenericParameters(formalRef.pointed_type, deduced); + } + + var formalIi = formalType.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; + if (formalIi != null) + { + return CheckIfTypeDependsOnUndeducedGenericParameters(formalIi.element_type, deduced); + } + + if (formalType.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.set_type) + { + return CheckIfTypeDependsOnUndeducedGenericParameters(formalType.element_type, deduced); + } + + if (formalType.IsDelegate) + { + var dii = formalType.get_internal_interface(internal_interface_kind.delegate_interface) as delegate_internal_interface; + var paramCount = dii.parameters.Count; + for (var i = 0; i < paramCount; i++) + { + if (!CheckIfTypeDependsOnUndeducedGenericParameters(dii.parameters[i].type, deduced)) + { + return false; + } + } + return CheckIfTypeDependsOnUndeducedGenericParameters(dii.return_value_type, deduced); + } + + if (formalType.is_generic_type_instance) + { + var pcount = formalType.instance_params.Count; + for (var k = 0; k < pcount; ++k) + { + if (!CheckIfTypeDependsOnUndeducedGenericParameters(formalType.instance_params[k], deduced)) + { + return false; + } + } + return true; + } + return false; + } + + //Сохранить типы параметров и тип возвращаемого значения лямбд перед попыткой вычисления реального типа возвращаемого знаяения лямбд + private static Dictionary, type_node>> SaveLambdasStates(IEnumerable lambdaParametersList) + { + var savedLambdasStates = new Dictionary, type_node>>(); + + foreach (var lambda in lambdaParametersList) + { + var parsTypes = new List(); + if (lambda.formal_parameters != null && lambda.formal_parameters.params_list != null && + lambda.formal_parameters.params_list.Count > 0) + { + parsTypes.AddRange(lambda + .formal_parameters + .params_list + .Select(t => + { + var lambdaNode = t.vars_type as lambda_inferred_type; + if (lambdaNode == null) + { + return null; + } + return lambdaNode.real_type is lambda_any_type_node + ? (lambda_any_type_node) lambdaNode.real_type + : null; + })); + } + + type_node retType; + var lambdaResNode = lambda.return_type as lambda_inferred_type; + if (lambdaResNode == null) + { + retType = null; + } + else + { + retType = lambdaResNode.real_type is lambda_any_type_node + ? (lambda_any_type_node)lambdaResNode.real_type + : null; + } + + savedLambdasStates.Add(lambda.lambda_name, + new Tuple, type_node>(parsTypes, retType)); + } + + return savedLambdasStates; + } + + //Восстановление типов в исходное состояние на случай подстановки других типов + private static void RestoreLambdasStates(List lambdaParametersList, + Dictionary, type_node>> savedLambdasStates) + { + for (var i = 0; i < lambdaParametersList.Count; i++) + { + var state = savedLambdasStates[lambdaParametersList[i].lambda_name]; + var lambdaPar = lambdaParametersList[i]; + for (var k = 0; k < state.Item1.Count; k++) + { + var lambdaNode = lambdaPar.formal_parameters.params_list[k].vars_type as lambda_inferred_type; + if (lambdaNode != null + && state.Item1[k] != null) + { + lambdaNode.real_type = state.Item1[k]; + } + } + + var resLambdaNode = lambdaPar.return_type as lambda_inferred_type; + if (resLambdaNode != null + && state.Item2 != null) + { + resLambdaNode.real_type = state.Item2; + } + } + } + + //Попытка вычислить типы после подстановки типов формальных параметров + public static bool TryToDeduceTypesInLambda(function_lambda_definition lambda_syntax_node, + delegate_internal_interface formal_delegate, + type_node[] deduced, List nils, + out Exception exception_on_body_compilation) + { + var there_are_undeduced_params = false; + var param_counter = 0; + var visitor = SystemLibrary.SystemLibrary.syn_visitor; + var result = true; + exception_on_body_compilation = null; + + /*if (lambda_syntax_node.formal_parameters == null + || lambda_syntax_node.formal_parameters.params_list == null + || lambda_syntax_node.formal_parameters.params_list.Count == 0) + { + return false; + }*/ + 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); + lambda_syntax_node.lambda_name = aux_name; + + try + { + visitor.visit(lambda_syntax_node); //пробуем скомпилировать тело лямбды, вычислим тип возвращаемого значения + } + catch (Exception exc) + { + exception_on_body_compilation = exc; // Если произошло исключение то запишем его в выходной параметр, оно потом будет обработано вызывающим методом + result = false; + } + finally + { + var context = visitor.context; + + //Далее надо удалить ненужный узел из списка функций + LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, lambda_syntax_node); + + lambda_syntax_node.lambda_name = lambdaName; + lambda_syntax_node.lambda_visit_mode = fl; + + if (result) + { + if (formal_delegate == null) // SSM 5.12.15 + { + result = false; + } + else + { + if (formal_delegate.return_value_type==null) // SSM 19/04/16 - эта проверка в связи с падением при передаче функции вместо процедуры в качестве функционального параметра: a.Foreach(x->1) + { + result = false; + } + else if (!DeduceInstanceTypes(formal_delegate.return_value_type, + (type_node)((lambda_inferred_type)lambda_syntax_node.return_type).real_type, + deduced, nils)) //Выводим дженерик-параметры после того как вычислили тип возвращаемого значения + { + result = false; + } + } + } + } + } + return result; + } + + public static function_node DeduceFunction(function_node func, expressions_list fact, bool alone, 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; + type_node[] deduced = new type_node[generic_type_params_count]; + List nils = new List(); + int count_params_to_see = fact_count; + + var lambda_syntax_nodes = new Dictionary(); //lroman Получим список фактических параметров-лямбд текущей вызываемой подпрограммы + if (syntax_nodes_parameters != null + && syntax_nodes_parameters.Count > 0) //lroman + { + lambda_syntax_nodes = syntax_nodes_parameters + .OfType() + .ToDictionary(f => f.lambda_name, f => f); + } + + var lambda_in_parameters = lambda_syntax_nodes.Count > 0; + var saved_lambdas_states = SaveLambdasStates(lambda_syntax_nodes.Select(ld => ld.Value)); // Сохраним типы лямбды перед вычислениями + + if (fact_count < formal_count) + { + //Сравниваем количества параметров + parameter par = formal[fact_count]; + if (par.default_value == null && !par.is_params) + { + if (alone) + throw new NoFunctionWithSameParametresNum(loc, alone, func); + return null; + } + } + else + { + type_node last_params_type = null; + bool last_is_params = false; + parameter par = null; + if (formal_count > 0) + { + par = formal[formal_count - 1]; + last_is_params = par.is_params; + } + if (last_is_params) + { + array_internal_interface aii = par.type.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; + last_params_type = aii.element_type; + } + if (fact_count > formal_count) + { + //Фактических больше, чем формальных. Последний формальный должен быть params... + if (last_is_params) + { + for (int i = formal_count - 1; i < fact_count; ++i) + { + //Проверяем фактические, попадающие под params... + if (!DeduceInstanceTypes(last_params_type, fact[i].type, deduced, nils)) + { + if (alone && 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)) + 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; + if (tn.element_type != null && tn.type_special_kind != SemanticTree.type_special_kind.array_wrapper) + tn = tn.element_type; + if (!DeduceInstanceTypes(last_params_type, tn, deduced, nils)) + { + if (alone) + throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); + return null; + } + } + count_params_to_see = formal_count - 1; + } + } + bool need_params_work = (count_params_to_see > 0 && formal[count_params_to_see - 1].is_params); + if (need_params_work) + { + count_params_to_see -= 1; + } + + var continue_trying_to_infer_types = true; + Dictionary formal_delegates = null; + + while (continue_trying_to_infer_types) //Продолжаем пытаться вычислить типы до тех пор пока состояние о выведенных типах не будет отличаться от состояния на предыдущей итерации + { + var previous_deduce_state = deduced // Текущее состояние выведенных на данный момент типов. Простой список индексов с уже выведенными типами из массива deduced + .Select((t, i) => new { Type = t, Index = i }) + .Where(t => t.Type != null) + .Select(t => t.Index) + .ToArray(); + + for (int i = 0; i < count_params_to_see; ++i) + { + if (alone && fact[i].type is delegated_methods && (fact[i].type as delegated_methods).empty_param_method != null && DeduceInstanceTypes(formal[i].type, (fact[i].type as delegated_methods).empty_param_method.type, deduced, nils)) + continue; + else + if (!DeduceInstanceTypes(formal[i].type, fact[i].type, deduced, nils)) + { + if (alone && fact[i].type is delegated_methods && (fact[i].type as delegated_methods).empty_param_method != null) + { + if (DeduceInstanceTypes(formal[i].type, (fact[i].type as delegated_methods).empty_param_method.type, deduced, nils)) + continue; + } + if (alone) + throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); + RestoreLambdasStates(lambda_syntax_nodes.Values.ToList(), saved_lambdas_states); + return null; + } + + } + + if (lambda_in_parameters) + { + if (formal_delegates == null) + { + formal_delegates = new Dictionary(); + + for (int i = 0; i < count_params_to_see; ++i) + //Выделим из формальных параметров те, которые соотвтествуют фактическим параметрам-лямбдам + { + var lambda_func = fact[i].type as delegated_methods; + if (lambda_func != null + && lambda_func.proper_methods.Count == 1 + && LambdaHelper.IsLambdaName(lambda_func.proper_methods[0].simple_function_node.name)) + { + formal_delegates.Add(LambdaHelper.GetLambdaNamePartWithoutGenerics(lambda_func.proper_methods[0].simple_function_node.name), + formal[i].type.get_internal_interface( + internal_interface_kind.delegate_interface) as + delegate_internal_interface); + } + } + } + + foreach (var formal_delegate in formal_delegates) + // Перебираем все полученные формальные параметры, соответствующие фактическим лямбдам + { + var lambda_syntax_node = lambda_syntax_nodes[formal_delegate.Key]; + Exception on_lambda_body_compile_exception; + // Исключение которое может возникнуть в результате компиляции тела лямбды если мы выберем неправильные типы параметров + var b = TryToDeduceTypesInLambda(lambda_syntax_node, formal_delegate.Value, deduced, nils, + out on_lambda_body_compile_exception); + 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)) + { + //Второй шанс. Учитываем слово params. + deduced = tmp_deduced; + nils = tmp_nils; + if (!DeduceInstanceTypes(formal[count_params_to_see].type.element_type, fact[count_params_to_see].type, deduced, nils)) + { + if (alone) + throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); + return null; + } + } + } + //Вывели всё, что могли. Теперь проверяем. + for (int i = 0; i < generic_type_params_count; ++i) + { + if (deduced[i] == null) + { + if (alone) + throw new SimpleSemanticError(loc, "CAN_NOT_DEDUCE_TYPE_PARAMS_FROM_CALL_{0}", func.name); + return null; + } + } + foreach (int num in nils) + { + if (!type_table.is_with_nil_allowed(deduced[num])) + { + if (alone) + throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); + return null; + } + } + foreach (type_node tt in deduced) + { + CompilationErrorWithLocation check_err = generic_parameter_eliminations.check_type_generic_useful(tt, loc); + if (check_err != null) + { + if (alone) + throw check_err; + return null; + } + } + //Итак, вывели все параметры. Теперь инстанцируем. + List deduced_list = new List(generic_type_params_count); + deduced_list.AddRange(deduced); + return func.get_instance(deduced_list, alone, loc); + } + + //Выведение типов + public static bool DeduceInstanceTypes(type_node formal_type, type_node fact_type, type_node[] deduced, List nils) + { + if (fact_type == null)//issue #347 + return false; + if (formal_type.generic_function_container == null && fact_type.generic_function_container != null) + { + //swap + type_node tmp = formal_type; + formal_type = fact_type; + fact_type = tmp; + } + //Формальный тип - generic-параметр функции. Выводим. + if (formal_type.generic_function_container != null) + { + int par_num = formal_type.generic_param_index; + if (fact_type.semantic_node_type == semantic_node_type.null_type_node) + { + nils.Add(par_num); + return true; + } + if (deduced[par_num] == null) + { + //Этот тип-параметр ещё не был выведен. + if (fact_type is delegated_methods && (fact_type as delegated_methods).empty_param_method != null && (fact_type as delegated_methods).empty_param_method.ret_type != null) + fact_type = (fact_type as delegated_methods).empty_param_method.ret_type; + //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); + } + //безразмерные массивы + array_internal_interface formal_ii = formal_type.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; + if (formal_ii != null) + { + array_internal_interface fact_ii = fact_type.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; + if (fact_ii == null) + { + goto eq_cmp; + } + return DeduceInstanceTypes(formal_ii.element_type, fact_ii.element_type, deduced, nils); + } + //множества + if (formal_type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.set_type) + { + if (fact_type.type_special_kind != PascalABCCompiler.SemanticTree.type_special_kind.set_type) + { + goto eq_cmp; + } + return DeduceInstanceTypes(formal_type.element_type, fact_type.element_type, deduced, nils); + } + //множества + if (formal_type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.typed_file) + { + if (fact_type.type_special_kind != PascalABCCompiler.SemanticTree.type_special_kind.typed_file) + { + goto eq_cmp; + } + return DeduceInstanceTypes(formal_type.element_type, fact_type.element_type, deduced, nils); + } + //Делегаты + if (formal_type.IsDelegate) + { + //Если текущий параметр - лямбда, то просто выводим дженерик-параметры из типов, которые уже известны. Не трогаем lambda_any_type_node. Остальное выведется в цикле выше + var lambda_func = fact_type as delegated_methods; + if (lambda_func != null + && lambda_func.proper_methods.Count == 1 + && LambdaHelper.IsLambdaName(lambda_func.proper_methods[0].simple_function_node.name)) + { + var dii = formal_type.get_internal_interface(internal_interface_kind.delegate_interface) as delegate_internal_interface; + var fact_func = lambda_func.proper_methods[0].simple_function_node; + + if (fact_func.parameters.Count != dii.parameters.Count) + { + goto eq_cmp; + } + + var param_count = fact_func.parameters.Count; + + for (var i = 0; i < param_count; i++) + { + if (fact_func.parameters[i].parameter_type != dii.parameters[i].parameter_type || + fact_func.parameters[i].is_params != dii.parameters[i].is_params) + goto eq_cmp; + } + for (var i = 0; i < param_count; i++) + { + if (fact_func.parameters[i].type is lambda_any_type_node) + { + continue; + } + // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка + if (!DeduceInstanceTypes(dii.parameters[i].type, fact_func.parameters[i].type, deduced, nils)) + //if (!DeduceInstanceTypes(fact_func.parameters[i].type, dii.parameters[i].type, deduced, nils)) + { + goto eq_cmp; + } + } + if (fact_func.return_value_type == null && dii.return_value_type == null) + { + //ok + } + else if (fact_func.return_value_type is lambda_any_type_node) //lroman// + { + if (dii.return_value_type == null) + { + goto eq_cmp; + } + return true; + } + // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка + else if (fact_func.return_value_type == null || !DeduceInstanceTypes(dii.return_value_type, fact_func.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable +// else if (fact_func.return_value_type == null || !DeduceInstanceTypes(fact_func.return_value_type, dii.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable + { + goto eq_cmp; + } + return true; + } + + if (!convertion_data_and_alghoritms.eq_type_nodes(formal_type, fact_type, true)) + { + delegate_internal_interface dii = formal_type.get_internal_interface(internal_interface_kind.delegate_interface) as delegate_internal_interface; + delegated_methods dm = fact_type as delegated_methods; + function_node fact_func = null; + if (dm != null && dm.proper_methods.Count == 1) + fact_func = 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_func = sil[0].sym_info as function_node; + } + + if (fact_func != null) + { + if (fact_func.parameters.Count != dii.parameters.Count) + { + goto eq_cmp; + } + int param_count = fact_func.parameters.Count; + for (int i = 0; i < param_count; i++) + { + if (fact_func.parameters[i].parameter_type != dii.parameters[i].parameter_type || + fact_func.parameters[i].is_params != dii.parameters[i].is_params) + goto eq_cmp; + } + for (int i = 0; i < param_count; i++) + { + if (!DeduceInstanceTypes(dii.parameters[i].type, fact_func.parameters[i].type, deduced, nils)) // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка + //if (!DeduceInstanceTypes(fact_func.parameters[i].type, dii.parameters[i].type, deduced, nils)) + { + goto eq_cmp; + } + } + if (fact_func.return_value_type == null && dii.return_value_type == null) + { + //ok + } + else if (fact_func.return_value_type is lambda_any_type_node && dii.return_value_type == null) //lroman// + { + goto eq_cmp; + } + // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка + else if (fact_func.return_value_type == null || !DeduceInstanceTypes(dii.return_value_type, fact_func.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable +// else if (fact_func.return_value_type == null || !DeduceInstanceTypes(fact_func.return_value_type, dii.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable + { + goto eq_cmp; + } + return true; + } + } + if (fact_type.IsDelegate && fact_type.semantic_node_type == semantic_node_type.delegated_method) + return true; + //goto eq_cmp; + } + //Инстанции дженериков + if (formal_type.is_generic_type_instance) + { + //if () goto eq_cmp; + type_node fact_type_converted; //Сюда будет записан фактический тип или интерфейс, к которому он приводится + if (!fact_type.is_generic_type_instance || formal_type.original_generic != fact_type.original_generic) + { + //if (!formal_type.IsInterface) goto eq_cmp; + fact_type_converted = null; + 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) goto eq_cmp; + } + else + { + fact_type_converted = fact_type; + } + int pcount = formal_type.instance_params.Count; + for (int k = 0; k < pcount; ++k) + { + if (!DeduceInstanceTypes(formal_type.instance_params[k], fact_type_converted.instance_params[k], deduced, nils)) + { + goto eq_cmp; + } + } + return true; + } + //Если совпадают - всё хорошо. + eq_cmp: + if (convertion_data_and_alghoritms.eq_type_nodes(formal_type, fact_type, true)) + { + return true; + } + possible_type_convertions ptc = type_table.get_convertions(fact_type, formal_type); + if (ptc.first != null) + { + return true; + } + return false; + } + + public static string MakePseudoInstanceName(string name, List param_types, bool type_name) + { + string rez; + if (type_name) + { + int last = name.LastIndexOf(compiler_string_consts.generic_params_infix); + if (last < 0) + { + rez = name; + } + else + { + rez = name.Substring(0, last); + } + } + else + { + rez = name; + } + bool first = true; + foreach (type_node tnode in param_types) + { + rez += ((first) ? "<" : ",") + tnode.PrintableName; + first = false; + } + rez += ">"; + return rez; + } + + public static bool type_has_default_ctor(type_node tn, bool find_protected_ctors) + { + if (tn.is_generic_parameter && tn.base_type != null && tn.base_type.IsAbstract) + return false; + List sil = tn.find_in_type(compiler_string_consts.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; + } + + public List generic_parameters + { + get + { + if (_generic_parameters == null) + { + _generic_parameters = new List(_instance_params.Count); + foreach (type_node tn in _instance_params) + { + _generic_parameters.Add(tn); + } + } + return _generic_parameters; + } + } + + private List temp_names = new List(3); + + public override void add_name(string name, SymbolInfo si) + { + temp_names.Add(si); + } + + protected void AddMember(object original, object converted) + { + 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; + SemanticTree.IClassMemberNode orig_member = orig_fn as SemanticTree.IClassMemberNode; + common_method_node cmn = new common_method_node( + orig_fn.name, + //generic_convertions.determine_type(orig_fn.return_value_type, _instance_params, false), + null, + loc, this, orig_member.polymorphic_state, orig_member.field_access_level, + null); + if (orig_fn.is_generic_function) + { + List orig_tpars = orig_fn.get_generic_params_list(); + int type_count = orig_tpars.Count; + cmn.generic_params = new List(orig_tpars.Count); + foreach (type_node t in orig_tpars) + { + common_type_node par = new common_type_node(t.name, PascalABCCompiler.SemanticTree.type_access_level.tal_public, + null, SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.symbol_table.CreateInterfaceScope(null, SystemLibrary.SystemLibrary.object_type.Scope, null), null); + SystemLibrary.SystemLibrary.init_reference_type(par); + par.SetBaseType(SystemLibrary.SystemLibrary.object_type); + cmn.generic_params.Add(par); + par.generic_function_container = cmn; + } + meth_inst_pars = cmn.get_generic_params_list(); + List gpes = orig_fn.parameters_eliminations; + for (int i = 0; i < type_count; ++i) + { + common_type_node p = (common_type_node)(meth_inst_pars[i]); + generic_parameter_eliminations gpe = gpes[i]; + p.SetBaseType(generic_convertions.determine_type( + generic_convertions.determine_type(gpe.base_class, _instance_params, false), + meth_inst_pars, true)); + p.is_class = gpe.is_class; + p.internal_is_value = gpe.is_value; + foreach (type_node interf in gpe.implementing_interfaces) + { + type_table.AddInterface(p, generic_convertions.determine_type( + generic_convertions.determine_type(interf, _instance_params, false), + meth_inst_pars, true), null); + } + if (gpe.has_default_ctor) + { + generic_parameter_eliminations.add_default_ctor(p); + } + } + } + cmn.parameters.AddRange(make_parameters(orig_fn.parameters, cmn)); + if (orig_fn.is_generic_function) + { + foreach (common_parameter cp in cmn.parameters) + { + cp.type = generic_convertions.determine_type(cp.type, meth_inst_pars, true); + } + } + common_method_node common_orig = orig_fn as common_method_node; + if (common_orig != null) + { + cmn.num_of_default_variables = common_orig.num_of_default_variables; + } + compiled_constructor_node compiled_orig = orig_fn as compiled_constructor_node; + cmn.is_constructor = (compiled_orig != null || + (common_orig != null && common_orig.is_constructor)); + cmn.return_value_type = generic_convertions.determine_type(orig_fn.return_value_type, _instance_params, false); + if (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); + } + if (orig_fn is common_function_node) + { + cmn.return_variable = (orig_fn as common_function_node)?.return_variable; + } + return cmn; + } + + public override List instance_params + { + get + { + return _instance_params; + } + set + { + _instance_params = value; + } + } + + public override bool is_generic_type_instance + { + get + { + return true; + } + } + + protected void AddPropertyAccessors(property_node pn) + { + if (pn.get_function != null) + { + if (_members[pn.get_function] == null) + { + ConvertMember(pn.get_function); + } + } + if (pn.set_function != null) + { + if (_members[pn.set_function] == null) + { + ConvertMember(pn.set_function); + } + } + } + + protected common_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 + ); + 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) + { + //Преобразуем найденный член класса. + 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); + if (compr_type == null) + { + compiled_function_node cfn = orig_node as compiled_function_node; + if (cfn == null) + { + return orig_node; + } + compiled_type_node cct = tn as compiled_type_node; + type_node inst_type = this; + do + { + inst_type = inst_type.base_type; + } + while (inst_type.semantic_node_type != semantic_node_type.compiled_type_node || + (inst_type != cct && inst_type.original_generic != cct)); + + + MethodInfo[] meths = cct._compiled_type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | + BindingFlags.Static | BindingFlags.Instance); + int num = System.Array.IndexOf(meths, cfn.method_info); + + MethodInfo mi = ((compiled_type_node)inst_type)._compiled_type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | + BindingFlags.Static | BindingFlags.Instance)[num]; + return compiled_function_node.get_compiled_method(mi); + } + else + return compr_type.ConvertMember(orig_node); + // + } + else + return orig_node; + } + SemanticTree.ILocated orig_loc = orig_node as SemanticTree.ILocated; + location loc = (orig_loc == null) ? null : (orig_loc.Location as location); + switch (orig_node.general_node_type) + { + case general_node_type.constant_definition: + constant_definition_node orig_cdn = orig_node as constant_definition_node; + rez_node = new class_constant_definition( + orig_cdn.name, orig_cdn.const_value, + loc, this, orig_member.field_access_level); + break; + case general_node_type.variable_node: + var_definition_node orig_cf = (var_definition_node)(orig_node); + rez_node = new class_field(orig_cf.name, + generic_convertions.determine_type(orig_cf.type, _instance_params, false), + this, orig_member.polymorphic_state, + orig_member.field_access_level, loc); + break; + case general_node_type.property_node: + property_node orig_pn = (property_node)(orig_node); + rez_node = make_property(orig_pn, loc); + break; + case general_node_type.function_node: + function_node orig_fn = (function_node)(orig_node); + rez_node = make_method(orig_fn, loc); + break; + case general_node_type.event_node: + //(ssyy) Не знаю, что тут делать + 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) + { + // aab 13.06.19 begin + // Поправил странное поведение для локальных переменных, у которых не generic тип + // Исправление для #1993 if (si.sym_info is local_block_variable variable && !variable.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 = _original_generic.find_first_in_type(name, true); - AddMember(si1.sym_info, temp_names[base_func_num].sym_info); - } - - public void conform_basic_functions() - { - conform_basic_function(compiler_string_consts.assign_name, 0); - conform_basic_function(compiler_string_consts.eq_name, 1); - conform_basic_function(compiler_string_consts.noteq_name, 2); - temp_names = null; - } - - public virtual List all_methods - { - get - { - return null; - } - } - - public virtual List all_field_types - { - get - { - return null; - } - } - - public override generic_instance_type_node base_generic_instance - { - get - { - return this; - } - } - - public override bool depended_from_indefinite - { - get - { - if (_instance_params == null) - { - return false; - } - foreach (type_node tn in _instance_params) - { - if (tn.depended_from_indefinite) - { - return true; - } - } - return false; - } - } - - } - - //Класс, характеризующий одну псевдоинстанцию generic-типа - public class compiled_generic_instance_type_node : generic_instance_type_node, SemanticTree.ICompiledGenericTypeInstance - { - public compiled_type_node compiled_original_generic - { - get - { - return _original_generic as compiled_type_node; - } - } - - public override string BaseFullName - { - get - { - return compiled_original_generic.BaseFullName; - } - } - - public compiled_generic_instance_type_node(compiled_type_node generic_definition, - List param_types, - type_node base_type, string name, - SemanticTree.type_access_level type_access_level, - common_namespace_node comprehensive_namespace, - location loc) - : - base(generic_definition, param_types, base_type, name, type_access_level, comprehensive_namespace, - loc) - { - } - - private List _all_methods = null; - - public override List all_methods - { - get - { - if (_all_methods != null) return _all_methods; - _all_methods = new List(); - System.Reflection.MemberInfo[] orig_members = compiled_original_generic.compiled_type.GetMembers(); - foreach (System.Reflection.MemberInfo mi in orig_members) - { - if (mi.MemberType == System.Reflection.MemberTypes.Method) - { - compiled_function_node cmeth = compiled_function_node.get_compiled_method((System.Reflection.MethodInfo)mi); - _all_methods.Add(ConvertMember(cmeth) as function_node); - } - } - return _all_methods; - } - } - - private List _all_field_types = null; - public override List all_field_types - { - get - { - if (_all_field_types != null) return _all_field_types; - System.Reflection.FieldInfo[] fields = compiled_original_generic.compiled_type.GetFields(); - _all_field_types = new List(); - foreach (System.Reflection.FieldInfo fi in fields) - { - if (!fi.IsStatic) - { - _all_field_types.Add(generic_convertions.determine_type(compiled_type_node.get_type_node(fi.FieldType), instance_params, false)); - } - } - return _all_field_types; - } - } - } - - //Класс, характеризующий одну псевдоинстанцию generic-типа - public class common_generic_instance_type_node : generic_instance_type_node, SemanticTree.ICommonGenericTypeInstance - { - public common_type_node common_original_generic - { - get - { - return _original_generic as common_type_node; - } - } - - public common_generic_instance_type_node(common_type_node generic_definition, - List param_types, - type_node base_type, string name, - SemanticTree.type_access_level type_access_level, - common_namespace_node comprehensive_namespace, - location loc) - : - base(generic_definition, param_types, base_type, name, type_access_level, comprehensive_namespace, - loc) - { - } - - private List _all_methods = null; - public override List all_methods - { - get - { - if (_all_methods != null) return _all_methods; - common_method_node_list orig_meths = common_original_generic.methods; - _all_methods = new List(orig_meths.Count); - foreach (common_method_node cnode in orig_meths) - { - _all_methods.Add(ConvertMember(cnode) as function_node); - } - return _all_methods; - } - } - - private List _all_field_types = null; - public override List all_field_types - { - get - { - if (_all_field_types != null) return _all_field_types; - class_field_list orig_fields = common_original_generic.fields; - _all_field_types = new List(orig_fields.Count); - foreach (class_field cf in orig_fields) - { - _all_field_types.Add(generic_convertions.determine_type(cf.type, this.instance_params, false)); - } - return _all_field_types; - } - } - } - - //Класс для запрещения создания в одной области видимости generic-классов с одинаковым именем. - public class generic_indicator : definition_node, SemanticTree.ILocated - { - private common_type_node _generic; - - public common_type_node generic - { - get - { - return _generic; - } - } - - public generic_indicator(common_type_node generic_type) - { - _generic = generic_type; - } - - public SemanticTree.ILocation Location - { - get - { - return _generic.Location; - } - } - - public location loc - { - get - { - return _generic.loc; - } - } - - public override general_node_type general_node_type - { - get - { - return TreeRealization.general_node_type.generic_indicator; - } - } - - public override semantic_node_type semantic_node_type - { - get - { - return semantic_node_type.generic_indicator; - } - } - } - - public class GenericParameterAbilities - { - public bool useful_for_pointers = false; - public bool useful_for_binary_files = false; - public bool useful_for_typed_files = false; - } - - public class generic_method_instance_node : common_method_node, SemanticTree.IGenericFunctionInstance - { - protected List _instance_params; - - public List instance_params - { - get - { - return _instance_params; - } - } - - protected List _generic_parameters = null; - - public List generic_parameters - { - get - { - if (_generic_parameters == null) - { - _generic_parameters = new List(); - foreach (type_node t in _instance_params) - { - _generic_parameters.Add(t); - } - } - return _generic_parameters; - } - } - - protected function_node _original_function; - - SemanticTree.IFunctionNode SemanticTree.IGenericFunctionInstance.original_function - { - get - { - return _original_function; - } - } - - public override function_node original_function - { - get - { - return _original_function; - } - } - - public override bool is_generic_function_instance - { - get - { - return true; - } - } - - public override SemanticTree.ITypeNode comperehensive_type - { - get - { - return (_original_function as SemanticTree.IClassMemberNode).comperehensive_type; - } - } - - public generic_method_instance_node(function_node original_generic_function, List instance_parameters) - : base( - generic_convertions.MakePseudoInstanceName(original_generic_function.name, instance_parameters, false), - null, null) - { - _original_function = original_generic_function; - _instance_params = instance_parameters; - - this.field_access_level = original_generic_function.field_access_level; - this.is_final = original_generic_function.is_final; - this.is_overload = true; - this.polymorphic_state = original_generic_function.polymorphic_state; - this.return_value_type = generic_convertions.determine_type(original_generic_function.return_value_type, instance_parameters, true); - - foreach (parameter par in original_generic_function.parameters) - { - common_parameter cpar = new common_parameter(par.name, - generic_convertions.determine_type(par.type, _instance_params, true), - par.parameter_type, this, - (par.parameter_type == SemanticTree.parameter_type.var) ? concrete_parameter_type.cpt_var : concrete_parameter_type.cpt_none, - par.default_value, null); - cpar.inital_value = par.inital_value; - cpar.default_value = par.default_value; - cpar.intrenal_is_params = par.is_params; - cpar.is_ret_value = par.is_ret_value; - cpar.is_special_name = par.is_special_name; - parameters.AddElement(cpar); - } - } - - public override List get_generic_params_list() - { - return instance_params; - } - } - - public class generic_namespace_function_instance_node: common_namespace_function_node, SemanticTree.IGenericFunctionInstance - { - protected List _instance_params; - - public List instance_params - { - get - { - return _instance_params; - } - } - - protected List _generic_parameters = null; - - public List generic_parameters - { - get - { - if (_generic_parameters == null) - { - _generic_parameters = new List(); - foreach (type_node t in _instance_params) - { - _generic_parameters.Add(t); - } - } - return _generic_parameters; - } - } - - protected common_namespace_function_node _original_function; - - SemanticTree.IFunctionNode SemanticTree.IGenericFunctionInstance.original_function - { - get - { - return _original_function; - } - } - - public override function_node original_function - { - get - { - return _original_function; - } - } - - public override bool is_generic_function_instance - { - get - { - return true; - } - } - - public generic_namespace_function_instance_node(common_namespace_function_node original_generic_function, List instance_parameters) - : base( - generic_convertions.MakePseudoInstanceName(original_generic_function.name, instance_parameters, false), - null, original_generic_function.namespace_node, null) - { - _original_function = original_generic_function; - _instance_params = instance_parameters; - - this.field_access_level = original_generic_function.field_access_level; - this.is_final = original_generic_function.is_final; - this.is_overload = true; - this.polymorphic_state = original_generic_function.polymorphic_state; - - this.return_value_type = generic_convertions.determine_type(original_generic_function.return_value_type, instance_parameters, true); - - foreach (parameter par in original_generic_function.parameters) - { - common_parameter cpar = new common_parameter(par.name, - generic_convertions.determine_type(par.type, _instance_params, true), - par.parameter_type, this, - (par.parameter_type == SemanticTree.parameter_type.var) ? concrete_parameter_type.cpt_var : concrete_parameter_type.cpt_none, - par.default_value, null); - cpar.inital_value = par.inital_value; - cpar.default_value = par.default_value; - cpar.intrenal_is_params = par.is_params; - cpar.is_ret_value = par.is_ret_value; - cpar.is_special_name = par.is_special_name; - parameters.AddElement(cpar); - } - } - - public override List get_generic_params_list() - { - return instance_params; - } - } - - public class default_operator_node : expression_node, SemanticTree.IDefaultOperatorNode - { - public default_operator_node(type_node tn, location loc) - : base(tn, loc) - { - } - - public override semantic_node_type semantic_node_type - { - get - { - return semantic_node_type.default_operator; - } - } - - /// - /// Метод для обхода дерева посетителем. - /// - /// Класс - посетитель дерева. - public override void visit(SemanticTree.ISemanticVisitor visitor) - { - visitor.visit(this); - } - - } -} + } + // 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 = _original_generic.find_first_in_type(name, true); + AddMember(si1.sym_info, temp_names[base_func_num].sym_info); + } + + public void conform_basic_functions() + { + conform_basic_function(compiler_string_consts.assign_name, 0); + conform_basic_function(compiler_string_consts.eq_name, 1); + conform_basic_function(compiler_string_consts.noteq_name, 2); + temp_names = null; + } + + public virtual List all_methods + { + get + { + return null; + } + } + + public virtual List all_field_types + { + get + { + return null; + } + } + + public override generic_instance_type_node base_generic_instance + { + get + { + return this; + } + } + + public override bool depended_from_indefinite + { + get + { + if (_instance_params == null) + { + return false; + } + foreach (type_node tn in _instance_params) + { + if (tn.depended_from_indefinite) + { + return true; + } + } + return false; + } + } + + } + + //Класс, характеризующий одну псевдоинстанцию generic-типа + public class compiled_generic_instance_type_node : generic_instance_type_node, SemanticTree.ICompiledGenericTypeInstance + { + public compiled_type_node compiled_original_generic + { + get + { + return _original_generic as compiled_type_node; + } + } + + public override string BaseFullName + { + get + { + return compiled_original_generic.BaseFullName; + } + } + + public compiled_generic_instance_type_node(compiled_type_node generic_definition, + List param_types, + type_node base_type, string name, + SemanticTree.type_access_level type_access_level, + common_namespace_node comprehensive_namespace, + location loc) + : + base(generic_definition, param_types, base_type, name, type_access_level, comprehensive_namespace, + loc) + { + } + + private List _all_methods = null; + + public override List all_methods + { + get + { + if (_all_methods != null) return _all_methods; + _all_methods = new List(); + System.Reflection.MemberInfo[] orig_members = compiled_original_generic.compiled_type.GetMembers(); + foreach (System.Reflection.MemberInfo mi in orig_members) + { + if (mi.MemberType == System.Reflection.MemberTypes.Method) + { + compiled_function_node cmeth = compiled_function_node.get_compiled_method((System.Reflection.MethodInfo)mi); + _all_methods.Add(ConvertMember(cmeth) as function_node); + } + } + return _all_methods; + } + } + + private List _all_field_types = null; + public override List all_field_types + { + get + { + if (_all_field_types != null) return _all_field_types; + System.Reflection.FieldInfo[] fields = compiled_original_generic.compiled_type.GetFields(); + _all_field_types = new List(); + foreach (System.Reflection.FieldInfo fi in fields) + { + if (!fi.IsStatic) + { + _all_field_types.Add(generic_convertions.determine_type(compiled_type_node.get_type_node(fi.FieldType), instance_params, false)); + } + } + return _all_field_types; + } + } + } + + //Класс, характеризующий одну псевдоинстанцию generic-типа + public class common_generic_instance_type_node : generic_instance_type_node, SemanticTree.ICommonGenericTypeInstance + { + public common_type_node common_original_generic + { + get + { + return _original_generic as common_type_node; + } + } + + public common_generic_instance_type_node(common_type_node generic_definition, + List param_types, + type_node base_type, string name, + SemanticTree.type_access_level type_access_level, + common_namespace_node comprehensive_namespace, + location loc) + : + base(generic_definition, param_types, base_type, name, type_access_level, comprehensive_namespace, + loc) + { + } + + private List _all_methods = null; + public override List all_methods + { + get + { + if (_all_methods != null) return _all_methods; + common_method_node_list orig_meths = common_original_generic.methods; + _all_methods = new List(orig_meths.Count); + foreach (common_method_node cnode in orig_meths) + { + _all_methods.Add(ConvertMember(cnode) as function_node); + } + return _all_methods; + } + } + + private List _all_field_types = null; + public override List all_field_types + { + get + { + if (_all_field_types != null) return _all_field_types; + class_field_list orig_fields = common_original_generic.fields; + _all_field_types = new List(orig_fields.Count); + foreach (class_field cf in orig_fields) + { + _all_field_types.Add(generic_convertions.determine_type(cf.type, this.instance_params, false)); + } + return _all_field_types; + } + } + } + + //Класс для запрещения создания в одной области видимости generic-классов с одинаковым именем. + public class generic_indicator : definition_node, SemanticTree.ILocated + { + private common_type_node _generic; + + public common_type_node generic + { + get + { + return _generic; + } + } + + public generic_indicator(common_type_node generic_type) + { + _generic = generic_type; + } + + public SemanticTree.ILocation Location + { + get + { + return _generic.Location; + } + } + + public location loc + { + get + { + return _generic.loc; + } + } + + public override general_node_type general_node_type + { + get + { + return TreeRealization.general_node_type.generic_indicator; + } + } + + public override semantic_node_type semantic_node_type + { + get + { + return semantic_node_type.generic_indicator; + } + } + } + + public class GenericParameterAbilities + { + public bool useful_for_pointers = false; + public bool useful_for_binary_files = false; + public bool useful_for_typed_files = false; + } + + public class generic_method_instance_node : common_method_node, SemanticTree.IGenericFunctionInstance + { + protected List _instance_params; + + public List instance_params + { + get + { + return _instance_params; + } + } + + protected List _generic_parameters = null; + + public List generic_parameters + { + get + { + if (_generic_parameters == null) + { + _generic_parameters = new List(); + foreach (type_node t in _instance_params) + { + _generic_parameters.Add(t); + } + } + return _generic_parameters; + } + } + + protected function_node _original_function; + + SemanticTree.IFunctionNode SemanticTree.IGenericFunctionInstance.original_function + { + get + { + return _original_function; + } + } + + public override function_node original_function + { + get + { + return _original_function; + } + } + + public override bool is_generic_function_instance + { + get + { + return true; + } + } + + public override SemanticTree.ITypeNode comperehensive_type + { + get + { + return (_original_function as SemanticTree.IClassMemberNode).comperehensive_type; + } + } + + public generic_method_instance_node(function_node original_generic_function, List instance_parameters) + : base( + generic_convertions.MakePseudoInstanceName(original_generic_function.name, instance_parameters, false), + null, null) + { + _original_function = original_generic_function; + _instance_params = instance_parameters; + + this.field_access_level = original_generic_function.field_access_level; + this.is_final = original_generic_function.is_final; + this.is_overload = true; + this.polymorphic_state = original_generic_function.polymorphic_state; + this.return_value_type = generic_convertions.determine_type(original_generic_function.return_value_type, instance_parameters, true); + + foreach (parameter par in original_generic_function.parameters) + { + common_parameter cpar = new common_parameter(par.name, + generic_convertions.determine_type(par.type, _instance_params, true), + par.parameter_type, this, + (par.parameter_type == SemanticTree.parameter_type.var) ? concrete_parameter_type.cpt_var : concrete_parameter_type.cpt_none, + par.default_value, null); + cpar.inital_value = par.inital_value; + cpar.default_value = par.default_value; + cpar.intrenal_is_params = par.is_params; + cpar.is_ret_value = par.is_ret_value; + cpar.is_special_name = par.is_special_name; + parameters.AddElement(cpar); + } + } + + public override List get_generic_params_list() + { + return instance_params; + } + } + + public class generic_namespace_function_instance_node: common_namespace_function_node, SemanticTree.IGenericFunctionInstance + { + protected List _instance_params; + + public List instance_params + { + get + { + return _instance_params; + } + } + + protected List _generic_parameters = null; + + public List generic_parameters + { + get + { + if (_generic_parameters == null) + { + _generic_parameters = new List(); + foreach (type_node t in _instance_params) + { + _generic_parameters.Add(t); + } + } + return _generic_parameters; + } + } + + protected common_namespace_function_node _original_function; + + SemanticTree.IFunctionNode SemanticTree.IGenericFunctionInstance.original_function + { + get + { + return _original_function; + } + } + + public override function_node original_function + { + get + { + return _original_function; + } + } + + public override bool is_generic_function_instance + { + get + { + return true; + } + } + + public generic_namespace_function_instance_node(common_namespace_function_node original_generic_function, List instance_parameters) + : base( + generic_convertions.MakePseudoInstanceName(original_generic_function.name, instance_parameters, false), + null, original_generic_function.namespace_node, null) + { + _original_function = original_generic_function; + _instance_params = instance_parameters; + + this.field_access_level = original_generic_function.field_access_level; + this.is_final = original_generic_function.is_final; + this.is_overload = true; + this.polymorphic_state = original_generic_function.polymorphic_state; + + this.return_value_type = generic_convertions.determine_type(original_generic_function.return_value_type, instance_parameters, true); + + foreach (parameter par in original_generic_function.parameters) + { + common_parameter cpar = new common_parameter(par.name, + generic_convertions.determine_type(par.type, _instance_params, true), + par.parameter_type, this, + (par.parameter_type == SemanticTree.parameter_type.var) ? concrete_parameter_type.cpt_var : concrete_parameter_type.cpt_none, + par.default_value, null); + cpar.inital_value = par.inital_value; + cpar.default_value = par.default_value; + cpar.intrenal_is_params = par.is_params; + cpar.is_ret_value = par.is_ret_value; + cpar.is_special_name = par.is_special_name; + parameters.AddElement(cpar); + } + } + + public override List get_generic_params_list() + { + return instance_params; + } + } + + public class default_operator_node : expression_node, SemanticTree.IDefaultOperatorNode + { + public default_operator_node(type_node tn, location loc) + : base(tn, loc) + { + } + + public override semantic_node_type semantic_node_type + { + get + { + return semantic_node_type.default_operator; + } + } + + /// + /// Метод для обхода дерева посетителем. + /// + /// Класс - посетитель дерева. + public override void visit(SemanticTree.ISemanticVisitor visitor) + { + visitor.visit(this); + } + + } +}