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