From 04ae33af4ac421085f235fdcaddb177263d6043b Mon Sep 17 00:00:00 2001 From: Sun Serega Date: Thu, 6 Oct 2022 11:06:27 +0300 Subject: [PATCH] Lazy generic_instance_type_node.ImplementingInterfaces --- NETGenerator/NETGenerator.cs | 7 ++-- SemanticTree/SemanticTree.cs | 4 +++ .../TreeConversion/syntax_tree_visitor.cs | 4 +++ TreeConverter/TreeRealization/generics.cs | 32 ++++++++++++++++++- TreeConverter/TreeRealization/types.cs | 11 +++++-- 5 files changed, 53 insertions(+), 5 deletions(-) diff --git a/NETGenerator/NETGenerator.cs b/NETGenerator/NETGenerator.cs index dace46506..3f9bceaf7 100644 --- a/NETGenerator/NETGenerator.cs +++ b/NETGenerator/NETGenerator.cs @@ -1,4 +1,4 @@ -// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt) +// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; using System.Linq; @@ -1523,7 +1523,10 @@ namespace PascalABCCompiler.NETGenerator { AddTypeWithoutConvert(t); } - foreach (ITypeNode interf in t.ImplementingInterfaces) + // ImplementingInterfacesOrEmpty, потому что если интерфейсы небыли лениво-посчитаны семантикой + // То и тут их обходить нет смысла + // А в ошибочных ситуациях (как err0303.pas) может ещё и зациклится + foreach (ITypeNode interf in t.ImplementingInterfacesOrEmpty) if (!(interf is ICompiledTypeNode)) ConvertTypeHeaderInSpecialOrder((ICommonTypeNode)interf); if (t.base_type != null && !(t.base_type is ICompiledTypeNode)) diff --git a/SemanticTree/SemanticTree.cs b/SemanticTree/SemanticTree.cs index a567a3d71..0979f92ee 100644 --- a/SemanticTree/SemanticTree.cs +++ b/SemanticTree/SemanticTree.cs @@ -211,6 +211,10 @@ namespace PascalABCCompiler.SemanticTree } List ImplementingInterfaces + { + get; + } + List ImplementingInterfacesOrEmpty { get; } diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index 92fa93fa7..ccbb79e99 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -3872,9 +3872,13 @@ namespace PascalABCCompiler.TreeConverter // "t1 = class(i1)" => "t1" реализует "i1" а не "i1" gti.pseudo_instance.SetBaseType(generic_convertions.determine_type(converted_type.base_type, gti.param_types, false)); + // Сбрасываем на null, чтобы их вычислило заново, если понадобится + gti.pseudo_instance.SetImplementingInterfaces(null); + /** gti.pseudo_instance.ImplementingInterfaces.Clear(); foreach (type_node t in converted_type.ImplementingInterfaces) gti.pseudo_instance.ImplementingInterfaces.Add(generic_convertions.determine_type(t, gti.param_types, false)); + /**/ } diff --git a/TreeConverter/TreeRealization/generics.cs b/TreeConverter/TreeRealization/generics.cs index e39cbd9c3..e37fbb45f 100644 --- a/TreeConverter/TreeRealization/generics.cs +++ b/TreeConverter/TreeRealization/generics.cs @@ -316,8 +316,11 @@ namespace PascalABCCompiler.TreeRealization return null; } - public static void init_generic_instance(type_node original, generic_instance_type_node instance, /*SymbolTable.ClassScope instance_scope,*/ List param_types) + public static void init_generic_instance(generic_instance_type_node instance/*, SymbolTable.ClassScope instance_scope*/) { + var original = instance.original_generic; + var param_types = instance.instance_params; + instance.IsInterface = original.IsInterface; instance.is_class = original.is_class; instance.internal_is_value = original.is_value; @@ -334,12 +337,15 @@ namespace PascalABCCompiler.TreeRealization //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(); @@ -1577,6 +1583,7 @@ namespace PascalABCCompiler.TreeRealization { _original_generic = original_generic_type; _instance_params = param_types; + SetImplementingInterfaces(null); } public List generic_parameters @@ -1595,6 +1602,29 @@ namespace PascalABCCompiler.TreeRealization } } + public override List ImplementingInterfaces + { + get + { + var res = base.ImplementingInterfaces; + if (res==null) + { + res = new List(); + foreach (type_node interf in original_generic.ImplementingInterfaces) + res.Add(generic_convertions.determine_type(interf, this.instance_params, false)); + SetImplementingInterfaces(res); + } + return res; + } + } + public override List ImplementingInterfacesOrEmpty + { + get + { + return base.ImplementingInterfaces ?? new List(); + } + } + private List temp_names = new List(3); public override void add_name(string name, SymbolInfo si) diff --git a/TreeConverter/TreeRealization/types.cs b/TreeConverter/TreeRealization/types.cs index 669432b23..252eb2fbb 100644 --- a/TreeConverter/TreeRealization/types.cs +++ b/TreeConverter/TreeRealization/types.cs @@ -219,6 +219,13 @@ namespace PascalABCCompiler.TreeRealization return null; } } + public virtual List ImplementingInterfacesOrEmpty + { + get + { + return ImplementingInterfaces; + } + } //true, если на данный момент имеется только предописание класса public virtual bool ForwardDeclarationOnly @@ -2601,7 +2608,7 @@ namespace PascalABCCompiler.TreeRealization generic_convertions.MakePseudoInstanceName(name, param_types, true), SemanticTree.type_access_level.tal_public, null, this.loc); _generic_instances.Add(new generic_type_instance_info(param_types, ctnode)); - generic_convertions.init_generic_instance(this, ctnode, param_types); + generic_convertions.init_generic_instance(ctnode); return ctnode; } @@ -3175,7 +3182,7 @@ namespace PascalABCCompiler.TreeRealization generic_convertions.MakePseudoInstanceName(name, param_types, true), SemanticTree.type_access_level.tal_public, null, /*ct_scope,*/ this.loc); _generic_instances.Add(new generic_type_instance_info(param_types, ctnode)); - generic_convertions.init_generic_instance(this, ctnode, /*ct_scope,*/ param_types); + generic_convertions.init_generic_instance(ctnode/*, ct_scope*/); return ctnode; } //\ssyy