diff --git a/PascalABCNET.sln b/PascalABCNET.sln index 937da7b6a..016b25a57 100644 --- a/PascalABCNET.sln +++ b/PascalABCNET.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "VisualPascalABCNET", "VisualPascalABCNET", "{26843C5D-9D7E-4C2C-AC14-2D227FA5592E}" EndProject @@ -95,6 +95,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntaxTreeConverters", "SyntaxTreeConverters\SyntaxTreeConverters.csproj", "{F10A5330-DCF4-4533-877C-7B1B1BE23884}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YieldHelpers", "Yield\YieldHelpers\YieldHelpers.csproj", "{CE5C55C2-A11C-4E94-A9FA-3FC6CA3E4C09}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntaxVisitors", "Yield\SyntaxVisitors\SyntaxVisitors.csproj", "{A9AB4282-83B4-41A7-86C3-E5BF6A45E7E2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YieldConversionSyntax", "Yield\YieldConversionSyntax\YieldConversionSyntax.csproj", "{276EE073-60F6-46D2-8811-1B8026BCAADA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -417,6 +423,36 @@ Global {F10A5330-DCF4-4533-877C-7B1B1BE23884}.Release|Mixed Platforms.Build.0 = Release|Any CPU {F10A5330-DCF4-4533-877C-7B1B1BE23884}.Release|x86.ActiveCfg = Release|Any CPU {F10A5330-DCF4-4533-877C-7B1B1BE23884}.Release|x86.Build.0 = Release|Any CPU + {CE5C55C2-A11C-4E94-A9FA-3FC6CA3E4C09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE5C55C2-A11C-4E94-A9FA-3FC6CA3E4C09}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE5C55C2-A11C-4E94-A9FA-3FC6CA3E4C09}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {CE5C55C2-A11C-4E94-A9FA-3FC6CA3E4C09}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {CE5C55C2-A11C-4E94-A9FA-3FC6CA3E4C09}.Debug|x86.ActiveCfg = Debug|Any CPU + {CE5C55C2-A11C-4E94-A9FA-3FC6CA3E4C09}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CE5C55C2-A11C-4E94-A9FA-3FC6CA3E4C09}.Release|Any CPU.Build.0 = Release|Any CPU + {CE5C55C2-A11C-4E94-A9FA-3FC6CA3E4C09}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {CE5C55C2-A11C-4E94-A9FA-3FC6CA3E4C09}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {CE5C55C2-A11C-4E94-A9FA-3FC6CA3E4C09}.Release|x86.ActiveCfg = Release|Any CPU + {A9AB4282-83B4-41A7-86C3-E5BF6A45E7E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A9AB4282-83B4-41A7-86C3-E5BF6A45E7E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A9AB4282-83B4-41A7-86C3-E5BF6A45E7E2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A9AB4282-83B4-41A7-86C3-E5BF6A45E7E2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A9AB4282-83B4-41A7-86C3-E5BF6A45E7E2}.Debug|x86.ActiveCfg = Debug|Any CPU + {A9AB4282-83B4-41A7-86C3-E5BF6A45E7E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A9AB4282-83B4-41A7-86C3-E5BF6A45E7E2}.Release|Any CPU.Build.0 = Release|Any CPU + {A9AB4282-83B4-41A7-86C3-E5BF6A45E7E2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A9AB4282-83B4-41A7-86C3-E5BF6A45E7E2}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A9AB4282-83B4-41A7-86C3-E5BF6A45E7E2}.Release|x86.ActiveCfg = Release|Any CPU + {276EE073-60F6-46D2-8811-1B8026BCAADA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {276EE073-60F6-46D2-8811-1B8026BCAADA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {276EE073-60F6-46D2-8811-1B8026BCAADA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {276EE073-60F6-46D2-8811-1B8026BCAADA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {276EE073-60F6-46D2-8811-1B8026BCAADA}.Debug|x86.ActiveCfg = Debug|Any CPU + {276EE073-60F6-46D2-8811-1B8026BCAADA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {276EE073-60F6-46D2-8811-1B8026BCAADA}.Release|Any CPU.Build.0 = Release|Any CPU + {276EE073-60F6-46D2-8811-1B8026BCAADA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {276EE073-60F6-46D2-8811-1B8026BCAADA}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {276EE073-60F6-46D2-8811-1B8026BCAADA}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -425,6 +461,7 @@ Global {CFC683F8-0165-4A9F-9C3F-BB8C5BAB507F} = {26843C5D-9D7E-4C2C-AC14-2D227FA5592E} {BC35F816-54EE-47E0-89FC-1C66EAC155A9} = {26843C5D-9D7E-4C2C-AC14-2D227FA5592E} {EC68A3D8-6D63-4A79-ABA6-BF8E9D7756D7} = {26843C5D-9D7E-4C2C-AC14-2D227FA5592E} + {A5A3667E-8A3B-4569-BA0E-AD49E12D07E7} = {26843C5D-9D7E-4C2C-AC14-2D227FA5592E} {DBE875B5-6187-45D8-8B75-2E43CC513A60} = {EC68A3D8-6D63-4A79-ABA6-BF8E9D7756D7} {43879684-ADBE-470A-AAC6-2ACA36603971} = {EC68A3D8-6D63-4A79-ABA6-BF8E9D7756D7} {3F74B986-7711-42B1-93D7-51952A71FF2E} = {EC68A3D8-6D63-4A79-ABA6-BF8E9D7756D7} @@ -444,17 +481,19 @@ Global {10679470-FE1B-4193-A203-D940CF0AEA54} = {F8CE2712-826B-450B-A72F-D32D80C99858} {1AB15F6E-C22E-499A-A7ED-54BA7DE5CFA6} = {F8CE2712-826B-450B-A72F-D32D80C99858} {BB6973BA-B3A2-4B31-A986-7CB008F22C4F} = {F8CE2712-826B-450B-A72F-D32D80C99858} - {1D51D03C-FB74-4AB2-84B4-09EB077BEAFE} = {BB6973BA-B3A2-4B31-A986-7CB008F22C4F} {94EED2FF-0641-4562-8167-CBC280A733AF} = {F8CE2712-826B-450B-A72F-D32D80C99858} + {146083AD-6684-4EBC-A539-AAD749A16364} = {F8CE2712-826B-450B-A72F-D32D80C99858} + {F10A5330-DCF4-4533-877C-7B1B1BE23884} = {F8CE2712-826B-450B-A72F-D32D80C99858} + {CE5C55C2-A11C-4E94-A9FA-3FC6CA3E4C09} = {F8CE2712-826B-450B-A72F-D32D80C99858} + {A9AB4282-83B4-41A7-86C3-E5BF6A45E7E2} = {F8CE2712-826B-450B-A72F-D32D80C99858} + {276EE073-60F6-46D2-8811-1B8026BCAADA} = {F8CE2712-826B-450B-A72F-D32D80C99858} + {1D51D03C-FB74-4AB2-84B4-09EB077BEAFE} = {BB6973BA-B3A2-4B31-A986-7CB008F22C4F} + {1443F539-DCC7-4491-B4FD-B716C739DB3C} = {BB6973BA-B3A2-4B31-A986-7CB008F22C4F} {C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A} = {94EED2FF-0641-4562-8167-CBC280A733AF} {613E0DDA-AA8A-437C-AC45-507B47429FF9} = {94EED2FF-0641-4562-8167-CBC280A733AF} - {A5A3667E-8A3B-4569-BA0E-AD49E12D07E7} = {26843C5D-9D7E-4C2C-AC14-2D227FA5592E} {2748AD25-9C63-4E12-877B-4DCE96FBED54} = {A5A3667E-8A3B-4569-BA0E-AD49E12D07E7} {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C} = {A5A3667E-8A3B-4569-BA0E-AD49E12D07E7} {7E4A7172-7FF5-48D0-B719-7CD959DD1AC9} = {A5A3667E-8A3B-4569-BA0E-AD49E12D07E7} {857CA1A3-FC88-4BE0-AB6A-D1EE772AB288} = {A5A3667E-8A3B-4569-BA0E-AD49E12D07E7} - {146083AD-6684-4EBC-A539-AAD749A16364} = {F8CE2712-826B-450B-A72F-D32D80C99858} - {1443F539-DCC7-4491-B4FD-B716C739DB3C} = {BB6973BA-B3A2-4B31-A986-7CB008F22C4F} - {F10A5330-DCF4-4533-877C-7B1B1BE23884} = {F8CE2712-826B-450B-A72F-D32D80C99858} EndGlobalSection EndGlobal diff --git a/SyntaxTree/tree/AbstractVisitor.cs b/SyntaxTree/tree/AbstractVisitor.cs index 6c3b040c4..dfbc582e0 100644 --- a/SyntaxTree/tree/AbstractVisitor.cs +++ b/SyntaxTree/tree/AbstractVisitor.cs @@ -1067,6 +1067,26 @@ namespace PascalABCCompiler.SyntaxTree { DefaultVisit(_no_type); } + + public virtual void visit(yield_unknown_ident _yield_unknown_ident) + { + DefaultVisit(_yield_unknown_ident); + } + + public virtual void visit(yield_unknown_expression_type _yield_unknown_expression_type) + { + DefaultVisit(_yield_unknown_expression_type); + } + + public virtual void visit(yield_var_def_statement_with_unknown_type _yield_var_def_statement_with_unknown_type) + { + DefaultVisit(_yield_var_def_statement_with_unknown_type); + } + + public virtual void visit(yield_variable_definitions_with_unknown_type _yield_variable_definitions_with_unknown_type) + { + DefaultVisit(_yield_variable_definitions_with_unknown_type); + } } diff --git a/SyntaxTree/tree/HierarchyVisitor.cs b/SyntaxTree/tree/HierarchyVisitor.cs index 5a7215478..5ef69e400 100644 --- a/SyntaxTree/tree/HierarchyVisitor.cs +++ b/SyntaxTree/tree/HierarchyVisitor.cs @@ -1701,6 +1701,38 @@ namespace PascalABCCompiler.SyntaxTree { } + public virtual void pre_do_visit(yield_unknown_ident _yield_unknown_ident) + { + } + + public virtual void post_do_visit(yield_unknown_ident _yield_unknown_ident) + { + } + + public virtual void pre_do_visit(yield_unknown_expression_type _yield_unknown_expression_type) + { + } + + public virtual void post_do_visit(yield_unknown_expression_type _yield_unknown_expression_type) + { + } + + public virtual void pre_do_visit(yield_var_def_statement_with_unknown_type _yield_var_def_statement_with_unknown_type) + { + } + + public virtual void post_do_visit(yield_var_def_statement_with_unknown_type _yield_var_def_statement_with_unknown_type) + { + } + + public virtual void pre_do_visit(yield_variable_definitions_with_unknown_type _yield_variable_definitions_with_unknown_type) + { + } + + public virtual void post_do_visit(yield_variable_definitions_with_unknown_type _yield_variable_definitions_with_unknown_type) + { + } + public override void visit(syntax_tree_node _syntax_tree_node) { DefaultVisit(_syntax_tree_node); @@ -3523,6 +3555,39 @@ namespace PascalABCCompiler.SyntaxTree pre_do_visit(_no_type); post_do_visit(_no_type); } + + public override void visit(yield_unknown_ident _yield_unknown_ident) + { + DefaultVisit(_yield_unknown_ident); + pre_do_visit(_yield_unknown_ident); + visit(yield_unknown_ident.UnknownID); + visit(yield_unknown_ident.ClassName); + post_do_visit(_yield_unknown_ident); + } + + public override void visit(yield_unknown_expression_type _yield_unknown_expression_type) + { + DefaultVisit(_yield_unknown_expression_type); + pre_do_visit(_yield_unknown_expression_type); + visit(yield_unknown_expression_type.Vds); + post_do_visit(_yield_unknown_expression_type); + } + + public override void visit(yield_var_def_statement_with_unknown_type _yield_var_def_statement_with_unknown_type) + { + DefaultVisit(_yield_var_def_statement_with_unknown_type); + pre_do_visit(_yield_var_def_statement_with_unknown_type); + visit(yield_var_def_statement_with_unknown_type.vars); + post_do_visit(_yield_var_def_statement_with_unknown_type); + } + + public override void visit(yield_variable_definitions_with_unknown_type _yield_variable_definitions_with_unknown_type) + { + DefaultVisit(_yield_variable_definitions_with_unknown_type); + pre_do_visit(_yield_variable_definitions_with_unknown_type); + visit(yield_variable_definitions_with_unknown_type.vars); + post_do_visit(_yield_variable_definitions_with_unknown_type); + } } diff --git a/SyntaxTree/tree/NodesBuilder.cs b/SyntaxTree/tree/NodesBuilder.cs index 21a466df2..7dc038d1a 100644 --- a/SyntaxTree/tree/NodesBuilder.cs +++ b/SyntaxTree/tree/NodesBuilder.cs @@ -115,6 +115,18 @@ namespace PascalABCCompiler.SyntaxTree return cd; } + // frninja 23/04/16 - для шаблонных классов в yield + public static class_definition BuildClassDefinition(named_type_reference_list parents, ident_list template_args, params class_members[] cms) + { + var cb = new class_body(); + foreach (var cm in cms) + cb.Add(cm); + + var cd = new class_definition(parents, cb, class_keyword.Class, template_args, null, class_attribute.None, false, null); + return cd; + } + // end frninja + // names и types передаю во внешний мир на предмет анализа того, что они не указатели. Снаружи они инициализируются пустыми списками public static void AddMembersForAutoClass(class_definition cd, ref List names, ref List types) // SSM 24.03.14 { diff --git a/SyntaxTree/tree/SyntaxTreeStreamReader.cs b/SyntaxTree/tree/SyntaxTreeStreamReader.cs index ad6697922..5e4f36c75 100644 --- a/SyntaxTree/tree/SyntaxTreeStreamReader.cs +++ b/SyntaxTree/tree/SyntaxTreeStreamReader.cs @@ -444,6 +444,14 @@ namespace PascalABCCompiler.SyntaxTree return new slice_expr(); case 211: return new no_type(); + case 212: + return new yield_unknown_ident(); + case 213: + return new yield_unknown_expression_type(); + case 214: + return new yield_var_def_statement_with_unknown_type(); + case 215: + return new yield_variable_definitions_with_unknown_type(); } return null; } @@ -3765,6 +3773,55 @@ namespace PascalABCCompiler.SyntaxTree read_type_definition(_no_type); } + + public void visit(yield_unknown_ident _yield_unknown_ident) + { + read_yield_unknown_ident(_yield_unknown_ident); + } + + public void read_yield_unknown_ident(yield_unknown_ident _yield_unknown_ident) + { + read_ident(_yield_unknown_ident); + _yield_unknown_ident.UnknownID = _read_node() as ident; + _yield_unknown_ident.ClassName = _read_node() as ident; + } + + + public void visit(yield_unknown_expression_type _yield_unknown_expression_type) + { + read_yield_unknown_expression_type(_yield_unknown_expression_type); + } + + public void read_yield_unknown_expression_type(yield_unknown_expression_type _yield_unknown_expression_type) + { + read_type_definition(_yield_unknown_expression_type); + _yield_unknown_expression_type.Vds = _read_node() as var_def_statement; + } + + + public void visit(yield_var_def_statement_with_unknown_type _yield_var_def_statement_with_unknown_type) + { + read_yield_var_def_statement_with_unknown_type(_yield_var_def_statement_with_unknown_type); + } + + public void read_yield_var_def_statement_with_unknown_type(yield_var_def_statement_with_unknown_type _yield_var_def_statement_with_unknown_type) + { + read_statement(_yield_var_def_statement_with_unknown_type); + _yield_var_def_statement_with_unknown_type.vars = _read_node() as var_def_statement; + } + + + public void visit(yield_variable_definitions_with_unknown_type _yield_variable_definitions_with_unknown_type) + { + read_yield_variable_definitions_with_unknown_type(_yield_variable_definitions_with_unknown_type); + } + + public void read_yield_variable_definitions_with_unknown_type(yield_variable_definitions_with_unknown_type _yield_variable_definitions_with_unknown_type) + { + read_declaration(_yield_variable_definitions_with_unknown_type); + _yield_variable_definitions_with_unknown_type.vars = _read_node() as variable_definitions; + } + } diff --git a/SyntaxTree/tree/SyntaxTreeStreamWriter.cs b/SyntaxTree/tree/SyntaxTreeStreamWriter.cs index 542ffde9e..4b0eaeccf 100644 --- a/SyntaxTree/tree/SyntaxTreeStreamWriter.cs +++ b/SyntaxTree/tree/SyntaxTreeStreamWriter.cs @@ -5922,6 +5922,99 @@ namespace PascalABCCompiler.SyntaxTree write_type_definition(_no_type); } + + public void visit(yield_unknown_ident _yield_unknown_ident) + { + bw.Write((Int16)212); + write_yield_unknown_ident(_yield_unknown_ident); + } + + public void write_yield_unknown_ident(yield_unknown_ident _yield_unknown_ident) + { + write_ident(_yield_unknown_ident); + if (_yield_unknown_ident.UnknownID == null) + { + bw.Write((byte)0); + } + else + { + bw.Write((byte)1); + _yield_unknown_ident.UnknownID.visit(this); + } + if (_yield_unknown_ident.ClassName == null) + { + bw.Write((byte)0); + } + else + { + bw.Write((byte)1); + _yield_unknown_ident.ClassName.visit(this); + } + } + + + public void visit(yield_unknown_expression_type _yield_unknown_expression_type) + { + bw.Write((Int16)213); + write_yield_unknown_expression_type(_yield_unknown_expression_type); + } + + public void write_yield_unknown_expression_type(yield_unknown_expression_type _yield_unknown_expression_type) + { + write_type_definition(_yield_unknown_expression_type); + if (_yield_unknown_expression_type.Vds == null) + { + bw.Write((byte)0); + } + else + { + bw.Write((byte)1); + _yield_unknown_expression_type.Vds.visit(this); + } + } + + + public void visit(yield_var_def_statement_with_unknown_type _yield_var_def_statement_with_unknown_type) + { + bw.Write((Int16)214); + write_yield_var_def_statement_with_unknown_type(_yield_var_def_statement_with_unknown_type); + } + + public void write_yield_var_def_statement_with_unknown_type(yield_var_def_statement_with_unknown_type _yield_var_def_statement_with_unknown_type) + { + write_statement(_yield_var_def_statement_with_unknown_type); + if (_yield_var_def_statement_with_unknown_type.vars == null) + { + bw.Write((byte)0); + } + else + { + bw.Write((byte)1); + _yield_var_def_statement_with_unknown_type.vars.visit(this); + } + } + + + public void visit(yield_variable_definitions_with_unknown_type _yield_variable_definitions_with_unknown_type) + { + bw.Write((Int16)215); + write_yield_variable_definitions_with_unknown_type(_yield_variable_definitions_with_unknown_type); + } + + public void write_yield_variable_definitions_with_unknown_type(yield_variable_definitions_with_unknown_type _yield_variable_definitions_with_unknown_type) + { + write_declaration(_yield_variable_definitions_with_unknown_type); + if (_yield_variable_definitions_with_unknown_type.vars == null) + { + bw.Write((byte)0); + } + else + { + bw.Write((byte)1); + _yield_variable_definitions_with_unknown_type.vars.visit(this); + } + } + } diff --git a/SyntaxTree/tree/Tree.cs b/SyntaxTree/tree/Tree.cs index 39b41f627..f167e6421 100644 --- a/SyntaxTree/tree/Tree.cs +++ b/SyntaxTree/tree/Tree.cs @@ -31312,6 +31312,518 @@ namespace PascalABCCompiler.SyntaxTree } + /// + ///Неопознанный идентификатор. Откладывает определение необходимости захвата имени как поля класса до этапа семантики. + /// + [Serializable] + public partial class yield_unknown_ident : ident + { + + /// + ///Конструктор без параметров. + /// + public yield_unknown_ident() + { + + } + + /// + ///Конструктор с параметрами. + /// + public yield_unknown_ident(ident _UnknownID,ident _ClassName) + { + this._UnknownID=_UnknownID; + this._ClassName=_ClassName; + } + + /// + ///Конструктор с параметрами. + /// + public yield_unknown_ident(ident _UnknownID,ident _ClassName,SourceContext sc) + { + this._UnknownID=_UnknownID; + this._ClassName=_ClassName; + source_context = sc; + } + + /// + ///Конструктор с параметрами. + /// + public yield_unknown_ident(string _name,ident _UnknownID,ident _ClassName) + { + this._name=_name; + this._UnknownID=_UnknownID; + this._ClassName=_ClassName; + } + + /// + ///Конструктор с параметрами. + /// + public yield_unknown_ident(string _name,ident _UnknownID,ident _ClassName,SourceContext sc) + { + this._name=_name; + this._UnknownID=_UnknownID; + this._ClassName=_ClassName; + source_context = sc; + } + + protected ident _UnknownID; + protected ident _ClassName; + + /// + /// + /// + public ident UnknownID + { + get + { + return _UnknownID; + } + set + { + _UnknownID=value; + } + } + + /// + /// + /// + public ident ClassName + { + get + { + return _ClassName; + } + set + { + _ClassName=value; + } + } + + + /// + ///Свойство для получения количества всех подузлов без элементов поля типа List + /// + public override Int32 subnodes_without_list_elements_count + { + get + { + return 2; + } + } + /// + ///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List + /// + public override Int32 subnodes_count + { + get + { + return 2; + } + } + /// + ///Индексатор для получения всех подузлов + /// + public override syntax_tree_node this[Int32 ind] + { + get + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + return UnknownID; + case 1: + return ClassName; + } + return null; + } + set + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + UnknownID = (ident)value; + break; + case 1: + ClassName = (ident)value; + break; + } + } + } + /// + ///Метод для обхода дерева посетителем + /// + ///Объект-посетитель. + ///Return value is void + public override void visit(IVisitor visitor) + { + visitor.visit(this); + } + + } + + + /// + ///Узел для вычисления типа выражения используемого в теле функции-итератора (с yield) + /// + [Serializable] + public partial class yield_unknown_expression_type : type_definition + { + + /// + ///Конструктор без параметров. + /// + public yield_unknown_expression_type() + { + + } + + /// + ///Конструктор с параметрами. + /// + public yield_unknown_expression_type(var_def_statement _Vds) + { + this._Vds=_Vds; + } + + /// + ///Конструктор с параметрами. + /// + public yield_unknown_expression_type(var_def_statement _Vds,SourceContext sc) + { + this._Vds=_Vds; + source_context = sc; + } + + /// + ///Конструктор с параметрами. + /// + public yield_unknown_expression_type(type_definition_attr_list _attr_list,var_def_statement _Vds) + { + this._attr_list=_attr_list; + this._Vds=_Vds; + } + + /// + ///Конструктор с параметрами. + /// + public yield_unknown_expression_type(type_definition_attr_list _attr_list,var_def_statement _Vds,SourceContext sc) + { + this._attr_list=_attr_list; + this._Vds=_Vds; + source_context = sc; + } + + protected var_def_statement _Vds; + + /// + /// + /// + public var_def_statement Vds + { + get + { + return _Vds; + } + set + { + _Vds=value; + } + } + + + /// + ///Свойство для получения количества всех подузлов без элементов поля типа List + /// + public override Int32 subnodes_without_list_elements_count + { + get + { + return 2; + } + } + /// + ///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List + /// + public override Int32 subnodes_count + { + get + { + return 2; + } + } + /// + ///Индексатор для получения всех подузлов + /// + public override syntax_tree_node this[Int32 ind] + { + get + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + return attr_list; + case 1: + return Vds; + } + return null; + } + set + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + attr_list = (type_definition_attr_list)value; + break; + case 1: + Vds = (var_def_statement)value; + break; + } + } + } + /// + ///Метод для обхода дерева посетителем + /// + ///Объект-посетитель. + ///Return value is void + public override void visit(IVisitor visitor) + { + visitor.visit(this); + } + + } + + + /// + ///Узел-обертка для yield для определения типов локальных переменных в var_def_statement + /// + [Serializable] + public partial class yield_var_def_statement_with_unknown_type : statement + { + + /// + ///Конструктор без параметров. + /// + public yield_var_def_statement_with_unknown_type() + { + + } + + /// + ///Конструктор с параметрами. + /// + public yield_var_def_statement_with_unknown_type(var_def_statement _vars) + { + this._vars=_vars; + } + + /// + ///Конструктор с параметрами. + /// + public yield_var_def_statement_with_unknown_type(var_def_statement _vars,SourceContext sc) + { + this._vars=_vars; + source_context = sc; + } + + protected var_def_statement _vars; + + /// + /// + /// + public var_def_statement vars + { + get + { + return _vars; + } + set + { + _vars=value; + } + } + + + /// + ///Свойство для получения количества всех подузлов без элементов поля типа List + /// + public override Int32 subnodes_without_list_elements_count + { + get + { + return 1; + } + } + /// + ///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List + /// + public override Int32 subnodes_count + { + get + { + return 1; + } + } + /// + ///Индексатор для получения всех подузлов + /// + public override syntax_tree_node this[Int32 ind] + { + get + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + return vars; + } + return null; + } + set + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + vars = (var_def_statement)value; + break; + } + } + } + /// + ///Метод для обхода дерева посетителем + /// + ///Объект-посетитель. + ///Return value is void + public override void visit(IVisitor visitor) + { + visitor.visit(this); + } + + } + + + /// + ///Узел-обертка для yield для определения типов локальных переменных в variable_definitions + /// + [Serializable] + public partial class yield_variable_definitions_with_unknown_type : declaration + { + + /// + ///Конструктор без параметров. + /// + public yield_variable_definitions_with_unknown_type() + { + + } + + /// + ///Конструктор с параметрами. + /// + public yield_variable_definitions_with_unknown_type(variable_definitions _vars) + { + this._vars=_vars; + } + + /// + ///Конструктор с параметрами. + /// + public yield_variable_definitions_with_unknown_type(variable_definitions _vars,SourceContext sc) + { + this._vars=_vars; + source_context = sc; + } + + protected variable_definitions _vars; + + /// + /// + /// + public variable_definitions vars + { + get + { + return _vars; + } + set + { + _vars=value; + } + } + + + /// + ///Свойство для получения количества всех подузлов без элементов поля типа List + /// + public override Int32 subnodes_without_list_elements_count + { + get + { + return 1; + } + } + /// + ///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List + /// + public override Int32 subnodes_count + { + get + { + return 1; + } + } + /// + ///Индексатор для получения всех подузлов + /// + public override syntax_tree_node this[Int32 ind] + { + get + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + return vars; + } + return null; + } + set + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + vars = (variable_definitions)value; + break; + } + } + } + /// + ///Метод для обхода дерева посетителем + /// + ///Объект-посетитель. + ///Return value is void + public override void visit(IVisitor visitor) + { + visitor.visit(this); + } + + } + + } diff --git a/SyntaxTree/tree/TreeHelper.cs b/SyntaxTree/tree/TreeHelper.cs index a58fcf414..eee5185b9 100644 --- a/SyntaxTree/tree/TreeHelper.cs +++ b/SyntaxTree/tree/TreeHelper.cs @@ -1214,6 +1214,55 @@ namespace PascalABCCompiler.SyntaxTree } + // frninja 12/05/16 - хелпер для yield. Хранит типы локальных переменных метода-итератора + [Serializable] + public class yield_locals_type_map_helper + { + public Dictionary vars_type_map { get; private set; } + + public yield_locals_type_map_helper() + { + vars_type_map = new Dictionary(); + } + } + // end frninja + + // frninja 12/05/16 - хелперы для yield + public partial class yield_unknown_expression_type : type_definition + { + public yield_locals_type_map_helper MapHelper { get; private set; } + + public yield_unknown_expression_type(var_def_statement vds, yield_locals_type_map_helper map_helper) + { + this.Vds = vds; + this.MapHelper = map_helper; + } + } + + public partial class yield_var_def_statement_with_unknown_type : statement + { + public yield_locals_type_map_helper map_helper { get; private set; } + + public yield_var_def_statement_with_unknown_type(var_def_statement vds, yield_locals_type_map_helper map_helper) + { + this.vars = vds; + this.map_helper = map_helper; + } + } + + public partial class yield_variable_definitions_with_unknown_type : declaration + { + public yield_locals_type_map_helper map_helper { get; private set; } + + public yield_variable_definitions_with_unknown_type(variable_definitions vd, yield_locals_type_map_helper map_helper) + { + this.vars = vd; + this.map_helper = map_helper; + } + } + + // end frninja + } diff --git a/SyntaxTree/tree/Visitor.cs b/SyntaxTree/tree/Visitor.cs index 42a9fe2a4..c93943052 100644 --- a/SyntaxTree/tree/Visitor.cs +++ b/SyntaxTree/tree/Visitor.cs @@ -1276,6 +1276,30 @@ namespace PascalABCCompiler.SyntaxTree ///Node to visit /// Return value is void void visit(no_type _no_type); + /// + ///Method to visit yield_unknown_ident. + /// + ///Node to visit + /// Return value is void + void visit(yield_unknown_ident _yield_unknown_ident); + /// + ///Method to visit yield_unknown_expression_type. + /// + ///Node to visit + /// Return value is void + void visit(yield_unknown_expression_type _yield_unknown_expression_type); + /// + ///Method to visit yield_var_def_statement_with_unknown_type. + /// + ///Node to visit + /// Return value is void + void visit(yield_var_def_statement_with_unknown_type _yield_var_def_statement_with_unknown_type); + /// + ///Method to visit yield_variable_definitions_with_unknown_type. + /// + ///Node to visit + /// Return value is void + void visit(yield_variable_definitions_with_unknown_type _yield_variable_definitions_with_unknown_type); } diff --git a/SyntaxTree/tree/tree.nin b/SyntaxTree/tree/tree.nin index 62257a7a6..ad805259c 100644 Binary files a/SyntaxTree/tree/tree.nin and b/SyntaxTree/tree/tree.nin differ diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index d70a41e96..3c2b23f8a 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -4649,6 +4649,15 @@ namespace PascalABCCompiler.TreeConverter internal void visit_method_call(SyntaxTree.method_call _method_call) { + // frninja 01/03/16 - for iterator capturing (yield) + if (_method_call.dereferencing_value is yield_unknown_ident) + { + var nodeToVisit = new method_call(ProcessUnknownIdent(_method_call.dereferencing_value as yield_unknown_ident), _method_call.parameters); + visit(nodeToVisit); + return; + } + // end frninja + //lroman if (_method_call.dereferencing_value is closure_substituting_node) { @@ -9634,6 +9643,16 @@ namespace PascalABCCompiler.TreeConverter hard_node_test_and_visit(_program_module.program_block); context.check_labels(context.converted_namespace.labels); + // frninja 28/04/16 - режем мусорные методы хелперы yield + { + var toRemove = cnsn.functions.Where(m => m.name.StartsWith(YieldHelpers.YieldConsts.YieldHelperMethodPrefix)).ToArray(); + foreach (var m in toRemove) + { + cnsn.functions.remove(m); + } + } + // end frninja + common_namespace_function_node main_function = new common_namespace_function_node(compiler_string_consts.temp_main_function_name, null, null, cnsn, null); main_function.function_code = context.code; @@ -10323,6 +10342,17 @@ namespace PascalABCCompiler.TreeConverter CheckWaitedRefTypes(ctn); is_direct_type_decl = true; hard_node_test_and_visit(_type_declaration.type_def); + + // frninja 28/04/16 - режем мусорные методы хелперы yield + { + var toRemove = ctn.methods.Where(m => m.name.StartsWith(YieldHelpers.YieldConsts.YieldHelperMethodPrefix)).ToArray(); + foreach (var m in toRemove) + { + ctn.methods.remove(m); + } + } + // end frninja + is_direct_type_decl = false; if (_type_declaration.attributes != null) { @@ -18723,6 +18753,111 @@ namespace PascalABCCompiler.TreeConverter visit(mc); } + // frninja 04/03/16 - для yield + + private bool CheckUnknownIdentNeedsClassCapture(SyntaxTree.yield_unknown_ident _unk) + { + string Consts__Self = YieldHelpers.YieldConsts.Self; + + // Find semantic class containing iterator (yield-method) with unknown ident + var iteratorContainingClass = context._ctn.fields.Where(f => f.name == Consts__Self).First().type; + //var iteratorContainingClass = context._cmn.types.Where(t => t.name == _unk.ClassName.name).First(); + + if (iteratorContainingClass != null) + { + // Search for unknown ident in class + var found = iteratorContainingClass.find(_unk.UnknownID.name); + if ((object)found != null) + { + // class_field - поле класса + // common_method_node - метод класса + // common_property_node - свойство класса + + // че там с .NET как базовым? + // compiled_function_node - метод базового .NET класса + // compiled_property_node - свойство базового .NET класса + + // че с классом из другого модуля? + // то же что и с классом из этого же + if (found.sym_info is class_field + || found.sym_info is common_method_node + || found.sym_info is common_property_node + || found.sym_info is compiled_function_node + || found.sym_info is compiled_property_node) + { + if (found.access_level != access_level.al_private) + { + return true; + } + } + + // common_namespace_function_node - глобальный метод + + } + } + + return false; + } + + private dot_node CaptureUnknownIdent(yield_unknown_ident unk) + { + string Consts__Self = YieldHelpers.YieldConsts.Self; + + return new dot_node(new dot_node(new ident("self"), new ident(Consts__Self)), unk.UnknownID); + } + + private SyntaxTree.addressed_value_funcname ProcessUnknownIdent(yield_unknown_ident unk) + { + if (CheckUnknownIdentNeedsClassCapture(unk)) + { + return CaptureUnknownIdent(unk); + } + else + { + return unk.UnknownID; + } + } + + // frninja - захват полей класса для yield + public override void visit(SyntaxTree.yield_unknown_ident _unk) + { + ProcessUnknownIdent(_unk).visit(this); + } + + public override void visit(SyntaxTree.yield_unknown_expression_type _unk_expr) + { + _unk_expr.MapHelper.vars_type_map[_unk_expr.Vds].visit(this); + } + + // frninja - заполнение хелпера типов локальных переменных для yield + public override void visit(SyntaxTree.yield_var_def_statement_with_unknown_type _vars) + { + if ((object)_vars.vars.vars_type != null) + return; + var t = convert_strong(_vars.vars.inital_value); + _vars.map_helper.vars_type_map[_vars.vars] = new SyntaxTree.semantic_type_node(t.type); + + // Visit stored vars + _vars.vars.visit(this); + } + + // frninja - заполнение хелпера типов локальных переменных для yield// frninja - заполнение хелпера типов локальных переменных для yield + public override void visit(SyntaxTree.yield_variable_definitions_with_unknown_type _vars) + { + foreach (var vd in _vars.vars.list) + { + if ((object)vd.vars_type != null) + continue; + var t = convert_strong(vd.inital_value); + _vars.map_helper.vars_type_map[vd] = new SyntaxTree.semantic_type_node(t.type); + } + + // Visit stored vars + _vars.vars.visit(this); + } + + // end frninja + /*public SyntaxTree.question_colon_expression ConvertToQCE(dot_question_node dqn) { // Неверно работает. Пока не используется. Доделать diff --git a/TreeConverter/TreeConverter.csproj b/TreeConverter/TreeConverter.csproj index 08b41c48c..8652fae31 100644 --- a/TreeConverter/TreeConverter.csproj +++ b/TreeConverter/TreeConverter.csproj @@ -258,6 +258,10 @@ + + {ce5c55c2-a11c-4e94-a9fa-3fc6ca3e4c09} + YieldHelpers + diff --git a/VisualPascalABCNET/VisualPascalABCNET.csproj b/VisualPascalABCNET/VisualPascalABCNET.csproj index 0babcaf44..e64024a3d 100644 --- a/VisualPascalABCNET/VisualPascalABCNET.csproj +++ b/VisualPascalABCNET/VisualPascalABCNET.csproj @@ -791,6 +791,10 @@ {1C9C945A-586D-42A2-A06B-65D84FA7FF78} TreeConverter + + {a9ab4282-83b4-41a7-86c3-e5bf6a45e7e2} + SyntaxVisitors + {2748AD25-9C63-4E12-877B-4DCE96FBED54} ICSharpCode.SharpDevelop diff --git a/Yield/ParsePABC1/.gitignore b/Yield/ParsePABC1/.gitignore new file mode 100644 index 000000000..893c20ff6 --- /dev/null +++ b/Yield/ParsePABC1/.gitignore @@ -0,0 +1,167 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates +.vs/ + +# Build results +[Bb]inaries/ +[Dd]ebug/ +[Rr]elease/ +x64/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# NuGet restore semaphore +build/ToolsetPackages/toolsetpackages.semaphore + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* +UnitTestResults.html + +# NuGet V3 artifacts +*-packages.config +*.nuget.props +*.nuget.targets + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.wrn +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual Studio cache files +*.sln.ide/ + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# NuGet Packages Directory +packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store diff --git a/Yield/ParsePABC1/App.config b/Yield/ParsePABC1/App.config new file mode 100644 index 000000000..74ade9db5 --- /dev/null +++ b/Yield/ParsePABC1/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Yield/ParsePABC1/ProgramOld.cs b/Yield/ParsePABC1/ProgramOld.cs new file mode 100644 index 000000000..075db366c --- /dev/null +++ b/Yield/ParsePABC1/ProgramOld.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler.Errors; +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; +using PascalABCCompiler.ParserTools; + +using SyntaxVisitors; + +namespace ParsePABC1 +{ + class Program + { + // PascalABCSaushkinParser reference needed!!! DO NOT REMOVE!!! + + static syntax_tree_node ParseFile(string fname) + { + Compiler c = new Compiler(); + // c.SyntaxTreeChanger = new YieldDesugarSyntaxTreeConverter(); + var opts = new CompilerOptions(fname, CompilerOptions.OutputType.ConsoleApplicaton); + + var res = c.Compile(opts); + + var err = new List(); + + var txt = System.IO.File.ReadAllText(fname); + + var cu = c.ParsersController.Compile(fname, txt, err, PascalABCCompiler.Parsers.ParseMode.Normal); + + if (cu == null) + { + Console.WriteLine("Не распарсилось"); + } + return cu; + } + + static void Main(string[] args) + { + var cu = ParseFile(@"C:\Users\Oleg\Documents\Visual Studio 2015\Projects\C#\Compilers\PascalABC.NET_Diplom\Yield\tests\template\yieldSimpleTemplateWithField.pas"); + if (cu == null) + return; + + var yieldVis = new ProcessYieldCapturedVarsVisitor(); + cu.visit(yieldVis); + + + cu.visit(new SimplePrettyPrinterVisitor()); + + Console.ReadKey(); + } + } +} diff --git a/Yield/ParsePABC1/Properties/AssemblyInfo.cs b/Yield/ParsePABC1/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..75b69173e --- /dev/null +++ b/Yield/ParsePABC1/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Управление общими сведениями о сборке осуществляется с помощью +// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, +// связанные со сборкой. +[assembly: AssemblyTitle("ParsePABC")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Hewlett-Packard")] +[assembly: AssemblyProduct("ParsePABC")] +[assembly: AssemblyCopyright("Copyright © Hewlett-Packard 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми +// для COM-компонентов. Если требуется обратиться к типу в этой сборке через +// COM, задайте атрибуту ComVisible значение TRUE для этого типа. +[assembly: ComVisible(false)] + +// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM +[assembly: Guid("d1b107ed-e2bb-4d21-98d0-a2f99c08d2b0")] + +// Сведения о версии сборки состоят из следующих четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер сборки +// Редакция +// +// Можно задать все значения или принять номера сборки и редакции по умолчанию +// используя "*", как показано ниже: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Yield/ParsePABC1/YieldTest.csproj b/Yield/ParsePABC1/YieldTest.csproj new file mode 100644 index 000000000..517adea6a --- /dev/null +++ b/Yield/ParsePABC1/YieldTest.csproj @@ -0,0 +1,111 @@ + + + + + Debug + AnyCPU + {D1B107ED-E2BB-4D21-98D0-A2F99C08D2B0} + Exe + Properties + ParsePABC + ParsePABC + v4.0 + 512 + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\pascalabcnet\_ParsePABC1\dlls\ICSharpCode.NRefactory.dll + + + False + ..\..\pascalabcnet\_ParsePABC1\dlls\Localization.dll + + + + + + + + + + + + + + + + + + + + {a25d26fb-3043-4bcf-833e-e3f4c3be795e} + CompilerTools + + + {1e42361a-eda3-4872-88af-a3aaf600d36d} + Compiler + + + {44a01f9e-dce7-470c-aae5-c3de0ccbee3b} + Errors + + + {1443f539-dcc7-4491-b4fd-b716c739db3c} + PascalABCSaushkinParser + + + {af2efd7b-69dd-4b43-af65-b59b29349c23} + ParserTools + + + {f10a5330-dcf4-4533-877c-7b1b1be23884} + SyntaxTreeConverters + + + {c2cac65a-b2ae-4ccc-b067-e6b8e75df73a} + SyntaxTree + + + {a9ab4282-83b4-41a7-86c3-e5bf6a45e7e2} + SyntaxVisitors + + + {276ee073-60f6-46d2-8811-1b8026bcaada} + YieldConversionSyntax + + + {ce5c55c2-a11c-4e94-a9fa-3fc6ca3e4c09} + YieldHelpers + + + + + \ No newline at end of file diff --git a/Yield/SyntaxVisitors/.gitignore b/Yield/SyntaxVisitors/.gitignore new file mode 100644 index 000000000..893c20ff6 --- /dev/null +++ b/Yield/SyntaxVisitors/.gitignore @@ -0,0 +1,167 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates +.vs/ + +# Build results +[Bb]inaries/ +[Dd]ebug/ +[Rr]elease/ +x64/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# NuGet restore semaphore +build/ToolsetPackages/toolsetpackages.semaphore + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* +UnitTestResults.html + +# NuGet V3 artifacts +*-packages.config +*.nuget.props +*.nuget.targets + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.wrn +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual Studio cache files +*.sln.ide/ + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# NuGet Packages Directory +packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store diff --git a/Yield/SyntaxVisitors/AllVarsInProcYieldsProba.cs b/Yield/SyntaxVisitors/AllVarsInProcYieldsProba.cs new file mode 100644 index 000000000..0cd12274d --- /dev/null +++ b/Yield/SyntaxVisitors/AllVarsInProcYieldsProba.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class AllVarsInProcYields : CollectUpperNamespacesVisitor + { + public FindMainIdentsVisitor mids = new FindMainIdentsVisitor(); + + public Dictionary> d = new Dictionary>(); + + public int countNodesVisited; + + public AllVarsInProcYields() + { + PrintInfo = false; + } + + public override void Enter(syntax_tree_node st) + { + base.Enter(st); + countNodesVisited++; + if (st is procedure_definition) + { + // пока вложенные процедуры не анализируются, хотя надо + mids.vars.Clear(); + } + + // сокращение обходимых узлов. Как сделать фильтр по тем узлам, которые необходимо обходить? Например, все операторы (без выражений и описаний), все описания (без операторов) + if (st is assign || st is var_def_statement || st is procedure_call || st is procedure_header || st is expression) + { + visitNode = false; + } + } + public override void Exit(syntax_tree_node st) + { + if (st is procedure_definition) + { + if (mids.vars.Count>0) + { + d[st as procedure_definition] = new HashSet(mids.vars); + } + var fld = new FindLocalDefsVisitor(); + st.visit(fld); + fld.Print(); + var t = fld.ids.Intersect(mids.vars); // идентификаторы, захваченные из локального контекста + + } + base.Exit(st); + } + public override void visit(yield_node yn) + { + yn.visit(mids); + // mids.vars - надо установить, какие из них - локальные, какие - из этого класса, какие - являются параметрами функции, а какие - глобальные (все остальные) + // те, которые являются параметрами, надо скопировать в локальные переменные и переименовать использование везде по ходу данной функции + // самое сложное - переменные-поля этого класса - они требуют в создаваемом классе, реализующем итератор, хранить Self текущего класса и добавлять это Self везде по ходу алгоритма + // вначале будем считать, что переменные-поля этого класса и переменные-параметры не захватываются yield + //base.visit(yn); + } + + public void PrintDict() + { + foreach (var a in d) + { + Console.Write("{0}: {1} ", a.Key.proc_header.name.meth_name, a.Value.Count); + foreach (var v in a.Value) + Console.Write("{0}, ", v); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("countNodesVisited={0}", countNodesVisited); + } + + } + } +} diff --git a/Yield/SyntaxVisitors/BaseVisitors/BaseChangeVisitor.cs b/Yield/SyntaxVisitors/BaseVisitors/BaseChangeVisitor.cs new file mode 100644 index 000000000..d37666097 --- /dev/null +++ b/Yield/SyntaxVisitors/BaseVisitors/BaseChangeVisitor.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class BaseChangeVisitor : CollectUpperNodesVisitor + { + private bool _rootAdded = false; + public override void DefaultVisit(syntax_tree_node n) + { + // frninja 07/12/15 + if (!_rootAdded) + { + _rootAdded = true; + ProcessNode(n); + } + + // Элементы списков - с конца в начало чтобы можно было эти элементы изменять по ходу (удалять/вставлять/заменять один несколькими) + var Сount = n.subnodes_count; + var СountWithoutListElements = n.subnodes_without_list_elements_count; + + for (var i = 0; i < СountWithoutListElements; i++) + ProcessNode(n[i]); + + for (var i = Сount - 1; i >= СountWithoutListElements; i--) // в обратном порядке + ProcessNode(n[i]); + } + + public void Replace(syntax_tree_node from, syntax_tree_node to) + { + var upper = UpperNode(); + if (upper == null) + throw new Exception("У корневого элемента нельзя получить UpperNode"); + upper.Replace(from, to); + } + + public T UpperNodeAs(int up = 1) where T : syntax_tree_node + { + var stl = UpperNode(up) as T; + if (stl == null) + throw new Exception("Элемент вложен не в " + typeof(T)); + return stl; + } + + public T UpperTo() where T : syntax_tree_node + { + syntax_tree_node upperNode = null; + + int up = 1; + + do + { + upperNode = UpperNode(up); + ++up; + } + while ((object)upperNode != null && !(upperNode is T)); + + return (object)upperNode != null ? upperNode as T : null; + } + + public bool DeleteInIdentList(ident id) + { + var idl = UpperNodeAs(); + return idl.Remove(id); + } + + public bool DeleteInStatementList(statement st) + { + var stl = UpperNodeAs(); + return stl.Remove(st); + } + + public static IEnumerable SeqStatements(params statement[] seq) + { + var l = new List(); + foreach (var st in seq) + if (st is statement_list) + l.AddRange((st as statement_list).list); + else l.Add(st); + return l; + } + + public void ReplaceStatement(statement from, statement to) + { + var stl = UpperNodeAs(); + stl.Replace(from, to); + } + + public void ReplaceStatement(statement from, IEnumerable to) + { + var stl = UpperNodeAs(); + stl.Replace(from, to); + } + } + +} diff --git a/Yield/SyntaxVisitors/BaseVisitors/BaseEnterExitVisitor.cs b/Yield/SyntaxVisitors/BaseVisitors/BaseEnterExitVisitor.cs new file mode 100644 index 000000000..946de80a7 --- /dev/null +++ b/Yield/SyntaxVisitors/BaseVisitors/BaseEnterExitVisitor.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class BaseEnterExitVisitor : WalkingVisitorNew + { + public BaseEnterExitVisitor() + { + OnEnter = Enter; + OnLeave = Exit; + } + + public virtual void Enter(syntax_tree_node st) + { + } + public virtual void Exit(syntax_tree_node st) + { + } + } +} diff --git a/Yield/SyntaxVisitors/BaseVisitors/CollectNamespaces.cs b/Yield/SyntaxVisitors/BaseVisitors/CollectNamespaces.cs new file mode 100644 index 000000000..d9147f283 --- /dev/null +++ b/Yield/SyntaxVisitors/BaseVisitors/CollectNamespaces.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class CollectUpperNamespacesVisitor : CollectUpperNodesVisitor + { + protected List list = new List(); + + public bool PrintInfo = true; + + public override void Enter(syntax_tree_node st) + { + base.Enter(st); + if (st is procedure_definition || st is class_definition) + { + list.Add(st as declaration); + if (PrintInfo) + Console.Write("+: "+st.GetType().Name); + } + } + public override void Exit(syntax_tree_node st) + { + if (st is procedure_definition || st is class_definition) + { + if (PrintInfo) + Console.WriteLine("-: " + st.GetType().Name); + list.RemoveAt(list.Count - 1); + } + base.Exit(st); + } + + public override void visit(procedure_definition p) + { + if (PrintInfo) + Console.WriteLine(" " + p.proc_header.name.meth_name); + + var ld = new FindLocalDefsVisitor(); + p.visit(ld); + + base.visit(p); + } + public override void visit(class_definition cl) + { + type_declarations tds = UpperNode(2) as type_declarations; + if (PrintInfo) + { + var f = tds.types_decl.Find(td => td.type_def == cl); + Console.WriteLine(" " + f.type_name); + } + base.visit(cl); + } + } + +} diff --git a/Yield/SyntaxVisitors/BaseVisitors/CollectUpperNodesVisitor.cs b/Yield/SyntaxVisitors/BaseVisitors/CollectUpperNodesVisitor.cs new file mode 100644 index 000000000..cffd70f88 --- /dev/null +++ b/Yield/SyntaxVisitors/BaseVisitors/CollectUpperNodesVisitor.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class CollectUpperNodesVisitor : BaseEnterExitVisitor + { + protected List listNodes = new List(); + + public syntax_tree_node CurrentNode + { + get + { + return listNodes[listNodes.Count - 1]; + } + } + + public syntax_tree_node UpperNode(int up = 1) + { + if (listNodes.Count - 1 - up < 0) + return null; + return listNodes[listNodes.Count - 1 - up]; + } + + public override void Enter(syntax_tree_node st) + { + listNodes.Add(st); + } + public override void Exit(syntax_tree_node st) + { + listNodes.RemoveAt(listNodes.Count - 1); + } + } + +} diff --git a/Yield/SyntaxVisitors/BaseVisitors/HasStatementVisitor.cs b/Yield/SyntaxVisitors/BaseVisitors/HasStatementVisitor.cs new file mode 100644 index 000000000..67574f984 --- /dev/null +++ b/Yield/SyntaxVisitors/BaseVisitors/HasStatementVisitor.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + + +namespace SyntaxVisitors +{ + public class HasStatementVisitor : WalkingVisitorNew + where T : statement + { + private bool foundT = false; + + public static bool Has(syntax_tree_node node) + { + HasStatementVisitor vis = new HasStatementVisitor(); + + vis.ProcessNode(node); + + return vis.foundT; + } + + public override void DefaultVisit(syntax_tree_node node) + { + if (node is T) + foundT = true; + else + base.DefaultVisit(node); + } + } +} diff --git a/Yield/SyntaxVisitors/BaseVisitors/SmallHelperVisitors.cs b/Yield/SyntaxVisitors/BaseVisitors/SmallHelperVisitors.cs new file mode 100644 index 000000000..5d156fe63 --- /dev/null +++ b/Yield/SyntaxVisitors/BaseVisitors/SmallHelperVisitors.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class FindLocalDefsVisitor : WalkingVisitorNew // Запускать только для подпрограмм + { + public ISet ids = new HashSet(); + private bool indef = false; + public override void visit(ident id) + { + if (indef) + ids.Add(id.name); + } + public override void visit(var_def_statement defs) + { + indef = true; + ProcessNode(defs.vars); // исключаем типы - просматриваем только имена переменных + indef = false; + } + + public void Print() + { + foreach (var x in ids) + Console.Write(x + ", "); + Console.WriteLine(); + } + } + + public class FindMainIdentsVisitor : WalkingVisitorNew // в выражении yield это надо будет. + { + public HashSet vars = new HashSet(); + public override void visit(ident id) + { + vars.Add(id.name); + } + public override void visit(dot_node dn) + { + ProcessNode(dn.left); + if (dn.right.GetType() != typeof(ident)) + ProcessNode(dn.right); + } + } +} diff --git a/Yield/SyntaxVisitors/ChangeWhileVisitor.cs b/Yield/SyntaxVisitors/ChangeWhileVisitor.cs new file mode 100644 index 000000000..6a27d6276 --- /dev/null +++ b/Yield/SyntaxVisitors/ChangeWhileVisitor.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler.Errors; +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class ChangeWhileVisitor : BaseChangeVisitor + { + int lbnum = 0; + + public static ChangeWhileVisitor New + { + get { return new ChangeWhileVisitor(); } + } + + public string newLabelName() + { + lbnum++; + return "lb#" + lbnum.ToString(); + } + public override void visit(while_node wn) + { + ProcessNode(wn.statements); + var gt1 = new goto_statement(newLabelName()); + var gt2 = new goto_statement(newLabelName()); + var gt3 = new goto_statement(newLabelName()); + + var if0 = new if_node(wn.expr, gt1, null); + var lb3 = new labeled_statement(gt3.label, if0); + var lb1 = new labeled_statement(gt1.label, wn.statements); + var lb2 = new labeled_statement(gt2.label, new empty_statement()); + + var stl = new statement_list(lb3, gt2, lb1, gt3, lb2); + + Replace(wn, stl); + // в declarations ближайшего блока добавить описание labels + block bl = listNodes.FindLast(x => x is block) as block; + + var ld = new label_definitions(gt1.label, gt2.label, gt3.label); + bl.defs.Add(ld); + } + + } + +} diff --git a/Yield/SyntaxVisitors/ObjectCopier.cs b/Yield/SyntaxVisitors/ObjectCopier.cs new file mode 100644 index 000000000..822ad3bfc --- /dev/null +++ b/Yield/SyntaxVisitors/ObjectCopier.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SyntaxVisitors +{ + using System; + using System.IO; + using System.Runtime.Serialization; + using System.Runtime.Serialization.Formatters.Binary; + + /// + /// Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx + /// Provides a method for performing a deep copy of an object. + /// Binary Serialization is used to perform the copy. + /// + public static class ObjectCopier + { + /// + /// Perform a deep Copy of the object. + /// + /// The type of object being copied. + /// The object instance to copy. + /// The copied object. + public static T Clone(T source) + { + if (!typeof(T).IsSerializable) + { + throw new ArgumentException("The type must be serializable.", "source"); + } + + // Don't serialize a null object, simply return the default for that object + if (Object.ReferenceEquals(source, null)) + { + return default(T); + } + + IFormatter formatter = new BinaryFormatter(); + Stream stream = new MemoryStream(); + using (stream) + { + formatter.Serialize(stream, source); + stream.Seek(0, SeekOrigin.Begin); + return (T)formatter.Deserialize(stream); + } + } + } +} diff --git a/Yield/SyntaxVisitors/Optimization/CalcConstExprs.cs b/Yield/SyntaxVisitors/Optimization/CalcConstExprs.cs new file mode 100644 index 000000000..a1d77a645 --- /dev/null +++ b/Yield/SyntaxVisitors/Optimization/CalcConstExprs.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class CalcConstExprs : BaseChangeVisitor // вычисление целых и вещественных константных выражений на этапе парсинга + { + public override void Exit(syntax_tree_node st) + { + bracket_expr bre = st as bracket_expr; + if (bre != null) + { + if (bre.expr is int32_const) + Replace(st, bre.expr); + } + + bin_expr vs = st as bin_expr; + if (vs != null) + { + if (vs.left is int32_const && vs.right is int32_const) + { + var a = vs.left as int32_const; + var b = vs.right as int32_const; + var op = vs.operation_type; + + syntax_tree_node res; + switch (op) + { + case Operators.Plus: + res = new int32_const(a.val + b.val); + break; + case Operators.Minus: + res = new int32_const(a.val - b.val); + break; + case Operators.Multiplication: + res = new int32_const(a.val * b.val); + break; + case Operators.Division: + res = new double_const((double)a.val / b.val); + break; + case Operators.Greater: + res = new bool_const(a.val > b.val); + break; + case Operators.Less: + res = new bool_const(a.val < b.val); + break; + case Operators.GreaterEqual: + res = new bool_const(a.val >= b.val); + break; + case Operators.LessEqual: + res = new bool_const(a.val <= b.val); + break; + default: + res = vs; + break; + } + + Replace(vs, res); + } + if (vs.left is int32_const && vs.right is double_const || vs.right is int32_const && vs.left is double_const || vs.left is double_const && vs.right is double_const) + { + double x,y; + if (vs.left is int32_const) + x = (vs.left as int32_const).val; + else + x = (vs.left as double_const).val; + if (vs.right is int32_const) + y = (vs.right as int32_const).val; + else + y = (vs.right as double_const).val; + + var op = vs.operation_type; + + syntax_tree_node res; + switch (op) + { + case Operators.Plus: + res = new double_const(x + y); + break; + case Operators.Minus: + res = new double_const(x - y); + break; + case Operators.Multiplication: + res = new double_const(x * y); + break; + case Operators.Division: + res = new double_const(x / y); + break; + case Operators.Greater: + res = new bool_const(x > y); + break; + case Operators.Less: + res = new bool_const(x < y); + break; + case Operators.GreaterEqual: + res = new bool_const(x >= y); + break; + case Operators.LessEqual: + res = new bool_const(x <= y); + break; + default: + res = vs; + break; + } + + Replace(vs, res); + } + + } + + base.Exit(st); // это обязательно! + } + } +} diff --git a/Yield/SyntaxVisitors/Properties/AssemblyInfo.cs b/Yield/SyntaxVisitors/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..df5892e25 --- /dev/null +++ b/Yield/SyntaxVisitors/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Управление общими сведениями о сборке осуществляется с помощью +// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, +// связанные со сборкой. +[assembly: AssemblyTitle("SyntaxVisitors")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Hewlett-Packard")] +[assembly: AssemblyProduct("SyntaxVisitors")] +[assembly: AssemblyCopyright("Copyright © Hewlett-Packard 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми +// для COM-компонентов. Если требуется обратиться к типу в этой сборке через +// COM, задайте атрибуту ComVisible значение TRUE для этого типа. +[assembly: ComVisible(false)] + +// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM +[assembly: Guid("a9ab4282-83b4-41a7-86c3-e5bf6a45e7e2")] + +// Сведения о версии сборки состоят из следующих четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер сборки +// Редакция +// +// Можно задать все значения или принять номера сборки и редакции по умолчанию +// используя "*", как показано ниже: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Yield/SyntaxVisitors/SyntaxVisitors.csproj b/Yield/SyntaxVisitors/SyntaxVisitors.csproj new file mode 100644 index 000000000..01fe4108f --- /dev/null +++ b/Yield/SyntaxVisitors/SyntaxVisitors.csproj @@ -0,0 +1,107 @@ + + + + + Debug + AnyCPU + {A9AB4282-83B4-41A7-86C3-E5BF6A45E7E2} + Library + Properties + SyntaxVisitors + SyntaxVisitors + v4.0 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {1e42361a-eda3-4872-88af-a3aaf600d36d} + Compiler + + + {44a01f9e-dce7-470c-aae5-c3de0ccbee3b} + Errors + + + {af2efd7b-69dd-4b43-af65-b59b29349c23} + ParserTools + + + {c2cac65a-b2ae-4ccc-b067-e6b8e75df73a} + SyntaxTree + + + {ce5c55c2-a11c-4e94-a9fa-3fc6ca3e4c09} + YieldHelpers + + + + + \ No newline at end of file diff --git a/Yield/SyntaxVisitors/UniversalVisitors/CountNodesVisitor.cs b/Yield/SyntaxVisitors/UniversalVisitors/CountNodesVisitor.cs new file mode 100644 index 000000000..926290f80 --- /dev/null +++ b/Yield/SyntaxVisitors/UniversalVisitors/CountNodesVisitor.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class CountNodesVisitor : BaseEnterExitVisitor + { + public Dictionary d = new Dictionary(); + + public int exprcount,statcount; + public override void Enter(syntax_tree_node st) + { + if (d.ContainsKey(st.GetType())) + d[st.GetType()] += 1; + else d[st.GetType()] = 1; + if (st is expression) + exprcount++; + if (st is statement) + statcount++; + } + + public void PrintSortedByValue() + { + var q = d.Select(x => new { x.Key, x.Value }).OrderByDescending(y => y.Value); + foreach (var a in q) + Console.WriteLine("{0}: {1} ", a.Key.Name, a.Value); + Console.WriteLine(); + Console.WriteLine("Expressions Count: {0}", exprcount); + Console.WriteLine("Statements Count: {0}", statcount); + } + + public void Print() + { + foreach (var a in d) + Console.WriteLine("{0}: {1} ", a.Key.Name, a.Value); + } + } +} diff --git a/Yield/SyntaxVisitors/UniversalVisitors/DeleteRedundantBeginEnds.cs b/Yield/SyntaxVisitors/UniversalVisitors/DeleteRedundantBeginEnds.cs new file mode 100644 index 000000000..f77116c23 --- /dev/null +++ b/Yield/SyntaxVisitors/UniversalVisitors/DeleteRedundantBeginEnds.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler.Errors; +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class DeleteRedundantBeginEnds : BaseChangeVisitor + { + public override void Exit(syntax_tree_node st) + { + var stl = st as statement_list; + if (stl != null && UpperNode() is statement_list) + ReplaceStatement(stl, stl.subnodes); + + var lst = st as labeled_statement; + if (lst != null) + { + var sttl = lst.to_statement as statement_list; + if (sttl != null) + { + sttl.subnodes[0] = new labeled_statement(lst.label_name, sttl.subnodes[0]); // а если [0] элемента вообще нет? + ReplaceStatement(lst,sttl.subnodes); + } + } + + base.Exit(st); + } + + } +} diff --git a/Yield/SyntaxVisitors/UniversalVisitors/SimplePrettyPrinterVisitor.cs b/Yield/SyntaxVisitors/UniversalVisitors/SimplePrettyPrinterVisitor.cs new file mode 100644 index 000000000..dfab440f9 --- /dev/null +++ b/Yield/SyntaxVisitors/UniversalVisitors/SimplePrettyPrinterVisitor.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler.Errors; +using PascalABCCompiler.PCU; +using PascalABCCompiler.SemanticTreeConverters; +using System.CodeDom.Compiler; +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + + +namespace SyntaxVisitors +{ + public class SimplePrettyPrinterVisitor : WalkingVisitorNew + { + int off = 0; + + bool printNodeType = false; + + public static SimplePrettyPrinterVisitor New + { + get { return new SimplePrettyPrinterVisitor(); } + } + + public SimplePrettyPrinterVisitor() + { + OnEnter = Enter; + OnLeave = Exit; + } + + public void Println(string s) + { + Console.Write(new string(' ', off)); + Console.WriteLine(s); + } + public void Print(string s) + { + Console.Write(new string(' ', off)); + Console.Write(s); + } + public void PrintNoOffset(string s) + { + Console.Write(s); + } + public void PrintlnNoOffset(string s) + { + Console.WriteLine(s); + } + + public void PrintlnNode(syntax_tree_node st) + { + if (printNodeType) + Console.Write(st.GetType().Name + ": "); + Console.WriteLine(new string(' ', off)+st); + } + public virtual void Enter(syntax_tree_node st) + { + if (st is statement_list) + { + Println("begin"); + off += 2; + } + else if (st is type_declarations) // надо в visit и самому всё обрабатывать + { + var tds = st is type_declarations; + Println("type "); + off += 2; + } + else if (st is case_variant) + { + var td = st as case_variant; + Println(td.conditions.ToString()+": "); + off += 2; + //ProcessNode(td.type_def); + //visitNode = false; + } + else if (st is type_declaration) + { + var td = st as type_declaration; + Print(td.type_name + " = "); + ProcessNode(td.type_def); + visitNode = false; + } + else if (st is class_definition) + { + var cd = st as class_definition; + PrintNoOffset("class"); + if (cd.class_parents != null && cd.class_parents.types.Count > 0) + { + PrintlnNoOffset("(" + cd.class_parents.ToString() + ")"); + } + else + PrintlnNoOffset(""); + off += 2; + ProcessNode(cd.body); + visitNode = false; + } + else if (st is access_modifer_node) + { + var am = st as access_modifer_node; + Println(am.access_level.ToString()); + + } + else if (st is variable_definitions) + { + var vds = st as variable_definitions; + Println("var"); + off += 2; + } + else if (st is var_def_statement) + { + var vds = st as var_def_statement; + Println(vds.ToString()); + } + else if (st is empty_statement || st is declarations || st is block || st is class_body || st is class_members || st is case_variants || st is program_module) + { + } + else if (st is if_node) + { + var ifn = st as if_node; + + Println("if " + ifn.condition.ToString() + " then"); + off += 2; + ProcessNode(ifn.then_body); + if (ifn.else_body == null) + { + visitNode = false; + return; + } + off -= 2; + Println("else "); + off += 2; + ProcessNode(ifn.else_body); + visitNode = false; + } + else if (st is while_node) + { + var wn = st as while_node; + + Println("while " + wn.expr.ToString() + " do"); + off += 2; + } + else if (st is case_node) + { + var cn = st as case_node; + + Println("case " + cn.param.ToString() + " of"); + off += 2; + } + else if (st is labeled_statement) + { + var lst = st as labeled_statement; + + Println(lst.label_name.name + ": "); + ProcessNode(lst.to_statement); + visitNode = false; + } + else if (st is var_statement || st is procedure_header) + { + Println(st.ToString()); + visitNode = false; + } + else if (st is procedure_definition) + { + Println(""); + } + else if (st is statement || st is variable_definitions || st is label_definitions) + { + PrintlnNode(st); + if (st is labeled_statement) + visitNode = false; + } + else if (st is token_info) + { + var s = st.ToString(); + if (s == "begin" || s == "end") + return; + PrintlnNode(st); + } + else + { + var q = st.GetType().GetMethod("ToString", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly); + if (q == null) + Println(st.GetType().Name); + } + } + public virtual void Exit(syntax_tree_node st) + { + if (st is statement_list) + { + off -= 2; + Println("end"); + } + else if (st is while_node || st is if_node || st is type_declarations || st is variable_definitions || st is case_variant) + { + off -= 2; + } + else if (st is class_definition || st is case_node) + { + off -= 2; + Println("end;"); + } + } + + } +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/CheckVariablesRedefenitionVisitor.cs b/Yield/SyntaxVisitors/YieldVisitors/CheckVariablesRedefenitionVisitor.cs new file mode 100644 index 000000000..e6dc96bf0 --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/CheckVariablesRedefenitionVisitor.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class CheckVariablesRedefenitionVisitor : WalkingVisitorNew + { + private ISet UpperBlockNames { get; set; } + + // Map :: CurrentLevel -> { BlockNames } + private List> BlockNamesStack { get; set; } + + private int CurrentLevel = -1; + + public CheckVariablesRedefenitionVisitor(ISet upperBlockNames) + { + //this.UpperBlockNames = upperBlockNames; + this.UpperBlockNames = new HashSet(); + this.BlockNamesStack = new List>(10); + } + + + public override void visit(formal_parameters fp) + { + foreach (var id in fp.params_list.SelectMany(tp => tp.idents.idents)) + { + CheckVariableAlreadyDefined(id); + UpperBlockNames.Add(id.name); + } + } + + public override void visit(variable_definitions vd) + { + foreach (var id in vd.var_definitions.SelectMany(vds => vds.vars.idents)) + { + CheckVariableAlreadyDefined(id); + UpperBlockNames.Add(id.name); + } + + base.visit(vd); + } + + /* + * // Scope Level 0 + * begin + * var x = value; // Name in Scope Level 0 + * // Scope Level 1 + * begin + * var x = value; // Name in Scope Level 1 <-- REDEFENITION ERROR, x defined at Level 0 + * + * var y = value; + * var y = value2; // Name in Scope Level 1 <-- REDEFINITION ERROR, y defined at Level 1 + * + * // Scope Level 2 + * begin + * var z = y; // Name in Scope Level 2 + * end + * // Scope Level 2 + * begin + * var z = value; // Name in Scope Level 2 + * end + * end + * + * end + */ + + public override void visit(statement_list stlist) + { + ++CurrentLevel; + + if (BlockNamesStack.Count <= CurrentLevel) + { + // Создаем множество имен для текущего уровня вложенности мини-пространства имен + BlockNamesStack.Add(new HashSet()); + } + + + base.visit(stlist); + //for (var i = 0; i < stlist.list.Count; ++i) + // ProcessNode(stlist.list[i]); + + BlockNamesStack.RemoveAt(BlockNamesStack.Count - 1); + + --CurrentLevel; + } + + public override void visit(var_statement vs) + { + foreach (var id in vs.var_def.vars.idents) + { + // Проверяем есть ли такое имя выше? + CheckVariableAlreadyDefined(id); + + BlockNamesStack[CurrentLevel].Add(id.name); + } + + base.visit(vs); + } + + + + public override void visit(for_node fn) + { + if (fn.create_loop_variable) + { + CheckVariableAlreadyDefined(fn.loop_variable); + } + base.visit(fn); + } + + private bool IsVariableAlreadyDefined(string name) + { + if (UpperBlockNames.Contains(name)) + return true; + for (int i = 0; i <= CurrentLevel; ++i) + { + if (BlockNamesStack[i].Contains(name)) + return true; + } + return false; + } + + private void CheckVariableAlreadyDefined(ident id) + { + string name = id.name; + + if (IsVariableAlreadyDefined(name)) + { + throw new PascalABCCompiler.Errors.SyntaxError(string.Format("Var {0} is already defined", name), "", id.source_context, id); + } + } + + } +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/CollectClassFieldsVisitor.cs b/Yield/SyntaxVisitors/YieldVisitors/CollectClassFieldsVisitor.cs new file mode 100644 index 000000000..aa0082543 --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/CollectClassFieldsVisitor.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class CollectClassFieldsVisitor : CollectUpperNodesVisitor + { + private ident _className; + + public ISet CollectedFields { get; private set; } + + public CollectClassFieldsVisitor(ident className) + { + CollectedFields = new HashSet(); + + _className = className; + } + + public override void visit(class_definition cd) + { + type_declaration td = UpperNode(1) as type_declaration; + + if ((object)td == null) + { + // Something went wrong + return; + } + + if (td.type_name.name != _className.name) + { + // Not the class we search for + // Yoda + return; + } + + var fields = cd.body.class_def_blocks.SelectMany(cm => cm.members.Where(decl => decl is var_def_statement) + .Select(decl1 => (decl1 as var_def_statement).vars.idents) + .SelectMany(ids => ids.Select(id => id))); + + + CollectedFields.UnionWith(fields); + + /*foreach (var defs in cd.body.class_def_blocks) + { + // Class members + foreach (var decl in defs.members) + { + // Declaration: fields + procedure defs + headers + etc + // Need vars + if (decl is var_def_statement) + { + var vars = (decl as var_def_statement).vars; + // Fields + foreach (var field in vars.idents) + { + CollectedFields.Add(field); + } + } + } + }*/ + } + + } +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/CollectClassMethodsVisitor.cs b/Yield/SyntaxVisitors/YieldVisitors/CollectClassMethodsVisitor.cs new file mode 100644 index 000000000..74b438013 --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/CollectClassMethodsVisitor.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class CollectClassMethodsVisitor : CollectUpperNodesVisitor + { + private ident _className; + + public ISet CollectedMethods { get; private set; } + + public CollectClassMethodsVisitor(ident className) + { + CollectedMethods = new HashSet(); + _className = className; + } + + public override void visit(class_definition cd) + { + type_declaration td = UpperNode(1) as type_declaration; + + if ((object)td == null) + { + // Something went wrong + return; + } + + if (td.type_name.name != _className.name) + { + // Not the class we search for + // Yoda + return; + } + + var methods = cd.body.class_def_blocks.SelectMany(cm => cm.members.Select(decl1 => + { + if (decl1 is procedure_header) + return (decl1 as procedure_header).name.meth_name; + else if (decl1 is procedure_definition) + return (decl1 as procedure_definition).proc_header.name.meth_name; + return null; + }).Where(name => (object)name != null)); + + CollectedMethods.UnionWith(methods); + } + + } +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/CollectClassPropertiesVisitor.cs b/Yield/SyntaxVisitors/YieldVisitors/CollectClassPropertiesVisitor.cs new file mode 100644 index 000000000..d0fa3288a --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/CollectClassPropertiesVisitor.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class CollectClassPropertiesVisitor : CollectUpperNodesVisitor + { + private ident _className; + + public ISet CollectedProperties { get; private set; } + + public CollectClassPropertiesVisitor(ident className) + { + CollectedProperties = new HashSet(); + _className = className; + } + + public override void visit(class_definition cd) + { + type_declaration td = UpperNode(1) as type_declaration; + + if ((object)td == null) + { + // Something went wrong + return; + } + + if (td.type_name.name != _className.name) + { + // Not the class we search for + // Yoda + return; + } + + var properties = cd.body.class_def_blocks.SelectMany(cm => cm.members.Select(decl => decl as simple_property) + .Where(name => (object)name != null) + .Select(sp => sp.property_name)); + + CollectedProperties.UnionWith(properties); + } + } +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/CollectUnitGlobalsVisitor.cs b/Yield/SyntaxVisitors/YieldVisitors/CollectUnitGlobalsVisitor.cs new file mode 100644 index 000000000..bb4cd6888 --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/CollectUnitGlobalsVisitor.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class CollectUnitGlobalsVisitor : CollectUpperNodesVisitor + { + public ISet CollectedGlobals { get; private set; } + + public CollectUnitGlobalsVisitor() + { + CollectedGlobals = new HashSet(); + } + + /*public override void visit(interface_node node) + { + var globals = node.interface_definitions.defs + .Select(def => def as variable_definitions) + .Where(varDefsObj => (object)varDefsObj != null) + .SelectMany(varDefs => varDefs.var_definitions) + .SelectMany(v => v.vars.idents); + + CollectedGlobals.UnionWith(globals); + }*/ + + public override void visit(declarations node) + { + var globals = node.defs + .Select(def => def as variable_definitions) + .Where(varDefsObj => (object)varDefsObj != null) + .SelectMany(varDefs => varDefs.var_definitions) + .SelectMany(v => v.vars.idents); + + CollectedGlobals.UnionWith(globals); + } + } +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/DeleteAllLocalDefs.cs b/Yield/SyntaxVisitors/YieldVisitors/DeleteAllLocalDefs.cs new file mode 100644 index 000000000..53307378e --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/DeleteAllLocalDefs.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class DeleteAllLocalDefs : BaseChangeVisitor + { + + private List LocalDeletedVD = new List(); // все локальные описания + + private List LocalDeletedVS = new List(); // var_statement's, потом объединим с LocalDeletedVD для верного порядка + + public ISet LocalDeletedDefsNames = new HashSet(); // их имена - для быстрого поиска + + public ISet CollectedLocals = new HashSet(); + + public IEnumerable LocalDeletedDefs + { + get + { + return new List(LocalDeletedVD.Union(LocalDeletedVS)); + } + } + + public DeleteAllLocalDefs() // надо запускать этот визитор начиная с корня подпрограммы + { + } + + public override void visit(var_statement vs) // локальные описания внутри процедуры + { + LocalDeletedVS.Insert(0, vs.var_def); + //DeleteInStatementList(vs); + + // frninja 02/03/16 - fix capturing unknown idents -> replace delete with assign + if ((object)vs.var_def.inital_value == null) + { + DeleteInStatementList(vs); + } + else + { + ReplaceStatement(vs, SeqStatements(vs.var_def.vars.idents.Select(id => new assign(id, vs.var_def.inital_value)).ToArray())); + } + + LocalDeletedDefsNames.UnionWith(vs.var_def.vars.idents.Select(id => id.name)); + CollectedLocals.UnionWith(vs.var_def.vars.idents); + } + + public override void visit(variable_definitions vd) + { + foreach (var v in vd.list) + { + LocalDeletedVD.Insert(0, v); //.Add(v); + LocalDeletedDefsNames.UnionWith(v.vars.idents.Select(id => id.name)); + } + var d = UpperNodeAs(); + d.defs.Remove(vd); // может ли остаться список declarations пустым? + + // frninja 03/03/16 - переносим объявления переменных c initial_value в тело метода для дальнейшей обработки + var methodBody = UpperTo().program_code; + + methodBody.list.InsertRange(0, vd.list + .Where(vds => (object)vds.inital_value != null) + .SelectMany(vdsInit => vdsInit.vars.list.Select(id => new assign(id, vdsInit.inital_value)))); + + // еще - не заходить в лямбды + } + } +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/DeleteLocalDefs.cs b/Yield/SyntaxVisitors/YieldVisitors/DeleteLocalDefs.cs new file mode 100644 index 000000000..7bf83b84b --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/DeleteLocalDefs.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class DeleteLocalDefs : BaseChangeVisitor + { + public List LocalDeletedIds = new List(); + public List BlockDeletedIds = new List(); + public HashSet idsToDelete; + public HashSet deletedIdsToDeleteInLocalScope = new HashSet(); // одно множество и на Local и на Block + + public DeleteLocalDefs(HashSet ids) // надо запускать этот визитор начиная с корня подпрограммы + { + idsToDelete = ids; + } + public override void visit(var_statement vs) + { + var idents = vs.var_def.vars.idents; + + var IdentsToDeleteInVarDef = idents.FindAll(id => idsToDelete.Contains(id.name)); // найти в операторе все идентификаторы для удаления + if (IdentsToDeleteInVarDef.Count != 0) + { + deletedIdsToDeleteInLocalScope.UnionWith(IdentsToDeleteInVarDef.Select(id => id.name)); // добавить те идентификаторы, которые мы удаляем из данного описания + + LocalDeletedIds.Add(new var_def_statement(new ident_list(IdentsToDeleteInVarDef), vs.var_def.vars_type, vs.var_def.inital_value)); // добавить описание из удаленных в данном разделе описаний идентификаторов + idents.RemoveAll(id => idsToDelete.Contains(id.name)); // удалить в операторе все идентификаторы для удаления + + idsToDelete.ExceptWith(deletedIdsToDeleteInLocalScope); + + if (idents.Count == 0) // то и весь var_statement надо убить + this.DeleteInStatementList(vs); + } + // Здесь мы не обрабатываем вложенный var_def_statement, поэтому когда мы будем обрабатывать его в другом visit, то это будут переменные до beginа подпрограммы или основной программы + } + public override void visit(var_def_statement vd) + { + var idents = vd.vars.idents; + + var IdentsToDeleteInVarDef = idents.FindAll(id => idsToDelete.Contains(id.name)); // найти в операторе все идентификаторы для удаления + if (IdentsToDeleteInVarDef.Count != 0) + { + deletedIdsToDeleteInLocalScope.UnionWith(IdentsToDeleteInVarDef.Select(id => id.name)); // добавить те идентификаторы, которые мы удаляем из данного описания + + BlockDeletedIds.Add(new var_def_statement(new ident_list(IdentsToDeleteInVarDef), vd.vars_type, vd.inital_value)); // добавить описание из удаленных в данном разделе описаний идентификаторов + idents.RemoveAll(id => idsToDelete.Contains(id.name)); // удалить в операторе все идентификаторы для удаления + + if (idents.Count == 0) + { + // Выше - variable_definitions, еще выше - declarations + var uvdsl = UpperNodeAs(); + uvdsl.var_definitions.Remove(vd); + if (uvdsl.var_definitions.Count == 0) + { + var d = UpperNodeAs(2); + d.defs.Remove(uvdsl); + } + } + } + } + public void AfterProcTraverse() + { + idsToDelete.ExceptWith(deletedIdsToDeleteInLocalScope); // исключаем из множества удаляемых идентификаторов те, которые мы нашли и удалили в секции var_statement. Это надо делать не для каждого описания, а в конце подпрограммы после удаления из всех секций var_statement + } + } +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/JustTestVisitor.cs b/Yield/SyntaxVisitors/YieldVisitors/JustTestVisitor.cs new file mode 100644 index 000000000..0de936dc1 --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/JustTestVisitor.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class JustTestVisitor : BaseChangeVisitor + { + private void CollectFormalParams(procedure_definition pd, ISet collectedFormalParams) + { + if ((object)pd.proc_header.parameters != null) + collectedFormalParams.UnionWith(pd.proc_header.parameters.params_list.Select(tp => new var_def_statement(tp.idents, tp.vars_type))); + } + + private void CollectFormalParamsNames(procedure_definition pd, ISet collectedFormalParamsNames) + { + if ((object)pd.proc_header.parameters != null) + collectedFormalParamsNames.UnionWith(pd.proc_header.parameters.params_list.SelectMany(tp => tp.idents.idents).Select(id => id.name)); + } + + private void CollectClassFieldsNames(procedure_definition pd, ISet collectedFields, out bool isInClassMethod) + { + isInClassMethod = false; + + ident className = null; + if ((object)pd.proc_header.name.class_name != null) + { + // Объявление вне класса его метода + className = pd.proc_header.name.class_name; + } + else + { + // Объявление функции в классе? + var classDef = UpperNode(3) as class_definition; + if ((object)(UpperNode(3) as class_definition) != null) + { + var td = UpperNode(4) as type_declaration; + if ((object)td != null) + { + className = td.type_name; + } + } + } + + if ((object)className != null) + { + isInClassMethod = true; + + CollectClassFieldsVisitor fieldsVis = new CollectClassFieldsVisitor(className); + var cu = UpperTo(); + if ((object)cu != null) + { + cu.visit(fieldsVis); + // Collect + collectedFields.UnionWith(fieldsVis.CollectedFields.Select(id => id.name)); + } + } + } + + private void CollectUnitGlobalsNames(procedure_definition pd, ISet collectedUnitGlobalsName) + { + var cu = UpperTo(); + if ((object)cu != null) + { + var ugVis = new CollectUnitGlobalsVisitor(); + cu.visit(ugVis); + // Collect + collectedUnitGlobalsName.UnionWith(ugVis.CollectedGlobals.Select(id => id.name)); + } + } + + private void CreateCapturedLocalsNamesMap(ISet localsNames, IDictionary capturedLocalsNamesMap) + { + foreach (var localName in localsNames) + { + capturedLocalsNamesMap.Add(localName, CapturedNamesHelper.MakeCapturedLocalName(localName)); + } + } + + private void CreateCapturedFormalParamsNamesMap(ISet formalParamsNames, IDictionary captueedFormalParamsNamesMap) + { + foreach (var formalParamName in formalParamsNames) + { + captueedFormalParamsNamesMap.Add(formalParamName, CapturedNamesHelper.MakeCapturedFormalParameterName(formalParamName)); + } + } + + public override void visit(procedure_definition pd) + { + // frninja + + // Classification + ISet CollectedLocalsNames = new HashSet(); + ISet CollectedFormalParamsNames = new HashSet(); + ISet CollectedClassFieldsNames = new HashSet(); + ISet CollectedUnitGlobalsNames = new HashSet(); + + ISet CollectedLocals = new HashSet(); + ISet CollectedFormalParams = new HashSet(); + + // Map from ident idName -> captured ident idName + IDictionary CapturedLocalsNamesMap = new Dictionary(); + IDictionary CapturedFormalParamsNamesMap = new Dictionary(); + + var dld = new DeleteAllLocalDefs(); // mids.vars - все захваченные переменные + pd.visit(dld); // Удалить в локальных и блочных описаниях этой процедуры все переменные и вынести их в отдельный список var_def_statement + + // frninja 08/12/15 + bool isInClassMethod; + + // Collect locals + CollectedLocals.UnionWith(dld.LocalDeletedDefs); + CollectedLocalsNames.UnionWith(dld.LocalDeletedDefs.SelectMany(vds => vds.vars.idents).Select(id => id.name)); + // Collect formal params + CollectFormalParams(pd, CollectedFormalParams); + CollectFormalParamsNames(pd, CollectedFormalParamsNames); + // Collect class fields + CollectClassFieldsNames(pd, CollectedClassFieldsNames, out isInClassMethod); + + // Collect unit globals + CollectUnitGlobalsNames(pd, CollectedUnitGlobalsNames); + + // Create maps :: idName -> captureName + CreateCapturedLocalsNamesMap(CollectedLocalsNames, CapturedLocalsNamesMap); + CreateCapturedFormalParamsNamesMap(CollectedFormalParamsNames, CapturedFormalParamsNamesMap); + + // AHAHA test! + ReplaceCapturedVariablesVisitor rcapVis = new ReplaceCapturedVariablesVisitor( + CollectedLocalsNames, + CollectedFormalParamsNames, + CollectedClassFieldsNames, + new HashSet(), + new HashSet(), + CollectedUnitGlobalsNames, + CapturedLocalsNamesMap, + CapturedFormalParamsNamesMap, + isInClassMethod + ); + // Replace + (pd.proc_body as block).program_code.visit(rcapVis); + } + } +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/LocalVariablesTypeDetectorHelperVisior.cs b/Yield/SyntaxVisitors/YieldVisitors/LocalVariablesTypeDetectorHelperVisior.cs new file mode 100644 index 000000000..ca077c176 --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/LocalVariablesTypeDetectorHelperVisior.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class LocalVariablesTypeDetectorHelperVisior : BaseChangeVisitor + { + public List LocalDeletedDefs = new List(); // все локальные описания + + public List LocalDeletedVS = new List(); // var_statement's, потом объединим с LocalDeletedVD для верного порядка + + public yield_locals_type_map_helper VarTypeMap { get; private set; } + + public LocalVariablesTypeDetectorHelperVisior(yield_locals_type_map_helper varTypeMap) + { + this.VarTypeMap = varTypeMap; + } + + public override void visit(yield_variable_definitions_with_unknown_type yvds) + { + // Empty + } + + public override void visit(var_statement vs) // локальные описания внутри процедуры + { + + LocalDeletedVS.Insert(0, vs.var_def); + + ReplaceStatement(vs, new yield_var_def_statement_with_unknown_type(vs.var_def, this.VarTypeMap)); + } + + public override void visit(variable_definitions vd) + { + foreach (var v in vd.list) + { + LocalDeletedDefs.Insert(0, v); + } + + Replace(vd, new yield_variable_definitions_with_unknown_type(vd, VarTypeMap)); + + // еще - не заходить в лямбды + } + } +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/LoweringVisitor.cs b/Yield/SyntaxVisitors/YieldVisitors/LoweringVisitor.cs new file mode 100644 index 000000000..2dc4cfadc --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/LoweringVisitor.cs @@ -0,0 +1,204 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler.Errors; +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class VarNames + { + public string VarName { get; set; } + public string VarEndName { get; set; } + + public VarNames() + { + } + + public VarNames(string varName, string varEndName) + { + VarName = varName; + VarEndName = varEndName; + } + } + + public class LoweringVisitor : BaseChangeVisitor + { + public static LoweringVisitor New + { + get { return new LoweringVisitor(); } + } + + private int _varnum = 0; + + private string newVarName() + { + _varnum++; + return "<>varLV" + _varnum.ToString(); + } + + private VarNames NewVarNames(ident name) + { + _varnum++; + return new VarNames() + { + VarName = "$" + name.name + _varnum, + VarEndName = "<>varLV" + _varnum + }; + } + + public static void Accept(procedure_definition pd) + { + New.ProcessNode(pd); + } + + public override void Enter(syntax_tree_node st) + { + base.Enter(st); + if (!(st is procedure_definition || st is block || st is statement_list || st is case_node || st is for_node || st is foreach_stmt || st is if_node || st is repeat_node || st is while_node || st is with_statement || st is try_stmt || st is lock_stmt)) + { + //visitNode = false; + } + } + + public override void visit(if_node ifn) + { + ProcessNode(ifn.then_body); + ProcessNode(ifn.else_body); + + var b = HasStatementVisitor.Has(ifn); + if (!b) + return; + + var gtAfter = goto_statement.New; + var lbAfter = new labeled_statement(gtAfter.label); + + if ((object)ifn.else_body == null) + { + var if0 = new if_node(un_expr.Not(ifn.condition), gtAfter); + //Replace(ifn, SeqStatements(if0, ifn.then_body, lbAfter)); + ReplaceStatement(ifn, SeqStatements(if0, ifn.then_body, lbAfter)); + + // в declarations ближайшего блока добавить описание labels + block bl = listNodes.FindLast(x => x is block) as block; + + bl.defs.Add(new label_definitions(gtAfter.label)); + } + else + { + var gtAlt = goto_statement.New; + var lbAlt = new labeled_statement(gtAlt.label, ifn.else_body); + + var if0 = new if_node(un_expr.Not(ifn.condition), gtAlt); + + ReplaceStatement(ifn, SeqStatements(if0, ifn.then_body, gtAfter, lbAlt, lbAfter)); + + // в declarations ближайшего блока добавить описание labels + block bl = listNodes.FindLast(x => x is block) as block; + + bl.defs.Add(new label_definitions(gtAfter.label, gtAlt.label)); + } + } + + public override void visit(repeat_node rn) + { + ProcessNode(rn.statements); + + var b = HasStatementVisitor.Has(rn); + if (!b) + return; + + var gtContinue = goto_statement.New; + var gtBreak = goto_statement.New; + + var lbContinue = new labeled_statement(gtContinue.label, rn.statements); + var lbBreak = new labeled_statement(gtBreak.label); + + var if0 = new if_node(un_expr.Not(rn.expr), gtContinue); + + + ReplaceStatement(rn, SeqStatements(lbContinue, if0, lbBreak)); + + // в declarations ближайшего блока добавить описание labels + block bl = listNodes.FindLast(x => x is block) as block; + + bl.defs.Add(new label_definitions(gtContinue.label, gtBreak.label)); + + } + + public override void visit(while_node wn) + { + ProcessNode(wn.statements); + + var b = HasStatementVisitor.Has(wn); + if (!b) + return; + + var gt1 = goto_statement.New; + var gt2 = goto_statement.New; + + var if0 = new if_node(un_expr.Not(wn.expr), gt1); + var lb2 = new labeled_statement(gt2.label, if0); // continue + var lb1 = new labeled_statement(gt1.label); // break + + ReplaceStatement(wn, SeqStatements(lb2, wn.statements, gt2, lb1)); + + // в declarations ближайшего блока добавить описание labels + block bl = listNodes.FindLast(x => x is block) as block; + + bl.defs.Add(new label_definitions(gt1.label, gt2.label)); + } + + public override void visit(for_node fn) + { + ProcessNode(fn.statements); + + var b = HasStatementVisitor.Has(fn); + if (!b) + return; + + var gt1 = goto_statement.New; + var gt2 = goto_statement.New; + + var newNames = this.NewVarNames(fn.loop_variable); + + var newLoopVar = fn.create_loop_variable ? new ident(newNames.VarName) : fn.loop_variable; + + // Нужно заменить fn.loop_variable -> newLoopVar в теле цикла + var replacerVis = new ReplaceForVariableVisitor(fn.loop_variable, newLoopVar); + fn.visit(replacerVis); + + fn.loop_variable = newLoopVar; + + var endtemp = new ident(newNames.VarEndName); //new ident(newVarName()); + + //var ass1 = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value); + var ass1 = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value); + //var ass2 = new var_statement(endtemp, fn.type_name, fn.finish_value); + + + + var if0 = new if_node((fn.cycle_type == for_cycle_type.to) ? + bin_expr.Greater(fn.loop_variable, fn.finish_value) : + bin_expr.Less(fn.loop_variable, fn.finish_value), gt1); + + var lb2 = new labeled_statement(gt2.label, if0); + var lb1 = new labeled_statement(gt1.label); + var Inc = new procedure_call(new method_call((fn.cycle_type == for_cycle_type.to) ? + new ident("Inc") : + new ident("Dec"), new expression_list(fn.loop_variable))); + + ReplaceStatement(fn, SeqStatements(ass1, /*ass2,*/ lb2, fn.statements, Inc, gt2, lb1)); + + // в declarations ближайшего блока добавить описание labels + block bl = listNodes.FindLast(x => x is block) as block; + + bl.defs.Add(new label_definitions(gt1.label, gt2.label)); + } + } + +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/MarkMethodHasYieldVisitor.cs b/Yield/SyntaxVisitors/YieldVisitors/MarkMethodHasYieldVisitor.cs new file mode 100644 index 000000000..f2ba5abc4 --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/MarkMethodHasYieldVisitor.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +using PascalABCCompiler.Errors; + +namespace SyntaxVisitors +{ + public class MarkMethodHasYieldVisitor : WalkingVisitorNew + { + private bool HasYields = false; + private procedure_definition CurrentMethod = null; + + public override void visit(procedure_definition pd) + { + this.CurrentMethod = pd; + + base.visit(pd); + pd.has_yield = HasYields; + + this.CurrentMethod = null; + } + + public override void visit(yield_node yn) + { + var pd = CurrentMethod; + + var fh = (pd.proc_header as function_header); + if (fh == null) + throw new SyntaxError("Only functions can contain yields", "", pd.proc_header.source_context, pd.proc_header); + var seqt = fh.return_type as sequence_type; + if (seqt == null) + throw new SyntaxError("Functions with yields must return sequences", "", fh.return_type.source_context, fh.return_type); + + var pars = fh.parameters; + if (pars != null) + foreach (var ps in pars.params_list) + { + if (ps.param_kind != parametr_kind.none) + throw new SyntaxError("Parameters of functions with yields must not have 'var', 'const' or 'params' modifier", "", pars.source_context, pars); + if (ps.inital_value != null) + throw new SyntaxError("Parameters of functions with yields must not have initial values", "", pars.source_context, pars); + } + + HasYields = true; + } + } +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/ProcessYieldsCapturedVars.cs b/Yield/SyntaxVisitors/YieldVisitors/ProcessYieldsCapturedVars.cs new file mode 100644 index 000000000..3e0e270f3 --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/ProcessYieldsCapturedVars.cs @@ -0,0 +1,884 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +using PascalABCCompiler.ParserTools; +using PascalABCCompiler.Errors; + +using PascalABCCompiler.YieldHelpers; + +namespace SyntaxVisitors +{ + + public static class CapturedNamesHelper + { + public static int CurrentLocalVariableNum = 0; + + public static string MakeCapturedFormalParameterName(string formalParamName) + { + return string.Format("<>{0}__{1}", YieldConsts.ReservedNum.MethodFormalParam, formalParamName); + } + + public static string MakeCapturedLocalName(string localName) + { + return string.Format("<{0}>{1}__{2}", localName, YieldConsts.ReservedNum.MethodLocalVariable, ++CurrentLocalVariableNum); + } + } + + public class ProcessYieldCapturedVarsVisitor : BaseChangeVisitor + { + int clnum = 0; + + public string NewYieldClassName() + { + clnum++; + return "clyield#" + clnum.ToString(); + } + + public FindMainIdentsVisitor mids; // захваченные переменные процедуры по всем её yield + + public int countNodesVisited; + + public bool hasYields = false; + + public static ProcessYieldCapturedVarsVisitor New + { + get { return new ProcessYieldCapturedVarsVisitor(); } + } + + public ProcessYieldCapturedVarsVisitor() + { + //PrintInfo = false; + } + + public override void Enter(syntax_tree_node st) + { + base.Enter(st); + countNodesVisited++; + + // сокращение обходимых узлов. Как сделать фильтр по тем узлам, которые необходимо обходить? Например, все операторы (без выражений и описаний), все описания (без операторов) + if (st is assign || st is var_def_statement || st is procedure_call || st is procedure_header || st is expression) + { + visitNode = false; // фильтр - куда не заходить + } + } + + /*public override void visit(class_members cm) + { + foreach (var decl in cm.members) + { + if (decl is procedure_header || decl is procedure_definition) + decl.visit(this); + } + base.visit(cm); + }*/ + + type_declarations GenClassesForYield(procedure_definition pd, + IEnumerable fields, // локальные переменные + IDictionary localsMap, // отображение для захваченных имен локальных переменных + IDictionary formalParamsMap, // отображение для захваченных имен формальных параметров + IDictionary localsCloneMap, // отображение для оберток локальных переменных + yield_locals_type_map_helper localTypeMapHelper) // вспомогательный узел для типов локальных переменных + { + var fh = (pd.proc_header as function_header); + if (fh == null) + throw new SyntaxError("Only functions can contain yields", "", pd.proc_header.source_context, pd.proc_header); + var seqt = fh.return_type as sequence_type; + if (seqt == null) + throw new SyntaxError("Functions with yields must return sequences", "", fh.return_type.source_context, fh.return_type); + + // Теперь на месте функции генерируем класс + + // Захваченные локальные переменные + var cm = class_members.Public; + var capturedFields = fields.Select(vds => + { + ident_list ids = new ident_list(vds.vars.idents.Select(id => new ident(localsMap[id.name])).ToArray()); + if (vds.vars_type == null) //&& vds.inital_value != null) + { + if (vds.inital_value != null) + { + //return new var_def_statement(ids, new yield_unknown_expression_type(localsCloneMap[vds], varsTypeDetectorHelper), null); + return new var_def_statement(ids, new yield_unknown_expression_type(localsCloneMap[vds], localTypeMapHelper), null); + } + else + { + throw new Exception("Variable defenition without type and value!"); + } + } + else + { + return new var_def_statement(ids, vds.vars_type, null); + } + + //return new var_def_statement(ids, vds.vars_type, vds.inital_value); + }); + + foreach (var m in capturedFields) + cm.Add(m); + + // Параметры функции + List lid = new List(); + var pars = fh.parameters; + if (pars != null) + foreach (var ps in pars.params_list) + { + if (ps.param_kind != parametr_kind.none) + throw new SyntaxError("Parameters of functions with yields must not have 'var', 'const' or 'params' modifier", "", pars.source_context, pars); + if (ps.inital_value != null) + throw new SyntaxError("Parameters of functions with yields must not have initial values", "", pars.source_context, pars); + //var_def_statement vds = new var_def_statement(ps.idents, ps.vars_type); + ident_list ids = new ident_list(ps.idents.list.Select(id => new ident(formalParamsMap[id.name])).ToArray()); + var_def_statement vds = new var_def_statement(ids, ps.vars_type); + cm.Add(vds); // все параметры функции делаем полями класса + //lid.AddRange(vds.vars.idents); + lid.AddRange(ps.idents.list); + } + + var stels = seqt.elements_type; + + var iteratorClassName = GetClassName(pd); + + // frninja 08/18/15 - Для захвата self + if (iteratorClassName != null) + { + // frninja 20/04/16 - поддержка шаблонных классов + var iteratorClassRef = CreateClassReference(iteratorClassName); + + cm.Add(new var_def_statement(YieldConsts.Self, iteratorClassRef)); + } + + // Системные поля и методы для реализации интерфейса IEnumerable + cm.Add(new var_def_statement(YieldConsts.State, "integer"), + new var_def_statement(YieldConsts.Current, stels), + procedure_definition.EmptyDefaultConstructor, + new procedure_definition("Reset"), + new procedure_definition("MoveNext", "boolean", pd.proc_body), + new procedure_definition("System.Collections.IEnumerator.get_Current", "object", new assign("Result", YieldConsts.Current)), + new procedure_definition("System.Collections.IEnumerable.GetEnumerator", "System.Collections.IEnumerator", new assign("Result", "Self")) + ); + + + + + // frninja 20/04/16 - поддержка шаблонных классов + var yieldClassName = NewYieldClassName(); + var yieldClassHelperName = yieldClassName + "Helper"; + + var className = this.CreateHelperClassName(yieldClassName, iteratorClassName, pd); + var classNameHelper = this.CreateHelperClassName(yieldClassHelperName, iteratorClassName, pd); + + + var interfaces = new named_type_reference_list("System.Collections.IEnumerator", "System.Collections.IEnumerable"); + + // frninja 24/04/16 - поддержка шаблонных классов + //var td = new type_declaration(classNameHelper, this.CreateHelperClassDefinition(classNameHelper, pd, interfaces, cm)); + //SyntaxTreeBuilder.BuildClassDefinition(interfaces, cm)); + + // Изменение тела процедуры + + + // frninja 20/04/16 - поддержка шаблонных классов + var stl = new statement_list(new var_statement("res", new new_expr(this.CreateClassReference(className), new expression_list()))); + + + //stl.AddMany(lid.Select(id => new assign(new dot_node("res", id), id))); + stl.AddMany(lid.Select(id => new assign(new dot_node("res", new ident(formalParamsMap[id.name])), id))); + + // frninja 08/12/15 - захват self + if (iteratorClassName != null) + { + stl.Add(new assign(new dot_node("res", YieldConsts.Self), new ident("self"))); + } + + stl.Add(new assign("Result", "res")); + + // New body + pd.proc_body = new block(stl); + + if (iteratorClassName != null) + { + var cd = UpperTo(); + if (cd != null) + { + // Если метод описан в классе + // frninja 10/12/15 - заменить на function_header и перенести описание тела в declarations + Replace(pd, fh); + var decls = UpperTo(); + if (decls != null) + { + // frninja 12/05/16 - забыли копировать return + function_header nfh = ObjectCopier.Clone(fh); + //function_header nfh = new function_header(); + //nfh.name = new method_name(fh.name.meth_name.name); + + // Set className + nfh.name.class_name = iteratorClassName; + //nfh.parameters = fh.parameters; + //nfh.proc_attributes = fh.proc_attributes; + //nfh.return_type = fh.return_type; + + procedure_definition npd = new procedure_definition(nfh, new block(stl)); + + // Update header + //pd.proc_header.className.class_name = GetClassName(pd); + // Add to decls + decls.Add(npd); + } + } + } + + // Второй класс + + var tpl = new template_param_list(stels); + + var IEnumeratorT = new template_type_reference("System.Collections.Generic.IEnumerator", tpl); + + var cm1 = cm.Add( //class_members.Public.Add( + //procedure_definition.EmptyDefaultConstructor, + new procedure_definition(new function_header("get_Current", stels), new assign("Result", YieldConsts.Current)), + new procedure_definition(new function_header("GetEnumerator", IEnumeratorT), new assign("Result", "Self")), + new procedure_definition("Dispose") + ); + + + // frninja 20/04/16 - поддержка шаблонных классов + var interfaces1 = new named_type_reference_list(/*this.CreateClassReference(classNameHelper) as named_type_reference*/); + var IEnumerableT = new template_type_reference("System.Collections.Generic.IEnumerable", tpl); + + interfaces1.Add(IEnumerableT).Add(IEnumeratorT); + + // frninja 24/04/16 - поддержка шаблонных классов + var td1 = new type_declaration(className, this.CreateHelperClassDefinition(className, pd, interfaces1, cm1)); + //SyntaxTreeBuilder.BuildClassDefinition(interfaces1, cm1)); + + var cct = new type_declarations(/*td*/); + cct.Add(td1); + + return cct; + } + + private void CollectFormalParams(procedure_definition pd, ISet collectedFormalParams) + { + if (pd.proc_header.parameters != null) + collectedFormalParams.UnionWith(pd.proc_header.parameters.params_list.Select(tp => new var_def_statement(tp.idents, tp.vars_type))); + } + + private void CollectFormalParamsNames(procedure_definition pd, ISet collectedFormalParamsNames) + { + if (pd.proc_header.parameters != null) + collectedFormalParamsNames.UnionWith(pd.proc_header.parameters.params_list.SelectMany(tp => tp.idents.idents).Select(id => id.name)); + } + + + /// + /// Создает обращение к имени класса по имени класса + /// + /// Имя класса + /// + private type_definition CreateClassReference(ident className) + { + if (className is template_type_name) + { + return new template_type_reference( + new named_type_reference(className), + new template_param_list(string.Join(",", (className as template_type_name).template_args.idents.Select(id => id.name))) + ); + } + return new named_type_reference(className); + } + + + /// + /// Создает имя вспомогательного класса + /// + /// Имя вспомогательного класса + /// Имя класса + /// + private ident CreateHelperClassName(string helperName, ident className, procedure_definition pd) + { + if (className is template_type_name) + { + return new template_type_name(helperName, (className as template_type_name).template_args); + } + else if (pd.proc_header.template_args != null) + { + return new template_type_name(helperName, pd.proc_header.template_args); + } + return new ident(helperName); + } + + private class_definition CreateHelperClassDefinition(ident className, procedure_definition pd, named_type_reference_list parents, params class_members[] cms) + { + if (className is template_type_name) + { + return SyntaxTreeBuilder.BuildClassDefinition(parents, (className as template_type_name).template_args , cms); + } + else if (pd.proc_header.template_args != null) + { + return SyntaxTreeBuilder.BuildClassDefinition(parents, pd.proc_header.template_args, cms); + } + return SyntaxTreeBuilder.BuildClassDefinition(parents, cms); + } + + + /// + /// Получает имя класса, в котором описан метод-итератор + /// + /// + /// + private ident GetClassName(procedure_definition pd) + { + if (pd.proc_header.name.class_name != null) + { + // Объявление вне класса его метода + return pd.proc_header.name.class_name; + } + else + { + // Объявление функции в классе? + var classDef = UpperNode(3) as class_definition; + if ((UpperNode(3) as class_definition) != null) + { + var td = UpperNode(4) as type_declaration; + if (td != null) + { + return td.type_name; + } + } + } + + return null; + } + + /// + /// Определяет описан ли метод-итератор в некотором классе + /// + /// + /// + private bool IsClassMethod(procedure_definition pd) + { + return GetClassName(pd) != null; + } + + private void CollectClassFieldsNames(procedure_definition pd, ISet collectedFields) + { + ident className = GetClassName(pd); + + if (className != null) + { + CollectClassFieldsVisitor fieldsVis = new CollectClassFieldsVisitor(className); + var cu = UpperTo(); + if (cu != null) + { + cu.visit(fieldsVis); + // Collect + collectedFields.UnionWith(fieldsVis.CollectedFields.Select(id => id.name)); + } + } + } + + private void CollectClassMethodsNames(procedure_definition pd, ISet collectedMethods) + { + ident className = GetClassName(pd); + + if (className != null) + { + CollectClassMethodsVisitor methodsVis = new CollectClassMethodsVisitor(className); + var cu = UpperTo(); + if (cu != null) + { + cu.visit(methodsVis); + // Collect + collectedMethods.UnionWith(methodsVis.CollectedMethods.Select(id => id.name)); + } + } + } + + private void CollectClassPropertiesNames(procedure_definition pd, ISet collectedProperties) + { + ident className = GetClassName(pd); + + if (className != null) + { + CollectClassPropertiesVisitor propertiesVis = new CollectClassPropertiesVisitor(className); + var cu = UpperTo(); + if (cu != null) + { + cu.visit(propertiesVis); + // Collect + collectedProperties.UnionWith(propertiesVis.CollectedProperties.Select(id => id.name)); + } + } + } + + private void CollectUnitGlobalsNames(procedure_definition pd, ISet collectedUnitGlobalsName) + { + var cu = UpperTo(); + if (cu != null) + { + var ugVis = new CollectUnitGlobalsVisitor(); + cu.visit(ugVis); + // Collect + collectedUnitGlobalsName.UnionWith(ugVis.CollectedGlobals.Select(id => id.name)); + } + } + + private void CreateCapturedLocalsNamesMap(ISet localsNames, IDictionary capturedLocalsNamesMap) + { + foreach (var localName in localsNames) + { + capturedLocalsNamesMap.Add(localName, CapturedNamesHelper.MakeCapturedLocalName(localName)); + } + } + + private void CreateCapturedFormalParamsNamesMap(ISet formalParamsNames, IDictionary captueedFormalParamsNamesMap) + { + foreach (var formalParamName in formalParamsNames) + { + captueedFormalParamsNamesMap.Add(formalParamName, CapturedNamesHelper.MakeCapturedFormalParameterName(formalParamName)); + } + } + + /// + /// Обработка локальных переменных метода и их типов для корректного захвата + /// + /// Объявление метода + /// Коллекция посещенных локальных переменных + private void CreateLocalVariablesTypeProxies(procedure_definition pd, out IEnumerable localsClonesCollection, out yield_locals_type_map_helper localsTypeMapHelper) + { + // Выполняем определение типов локальных переменных с автовыводом типов + + // Клонируем исходный метод для вставки оберток-хелперов для локальных переменных и дальнейшей обработки на семантике + var pdCloned = ObjectCopier.Clone(pd); + pdCloned.has_yield = false; + + // Заменяем локальные переменные с неизвестным типом на обертки-хелперы (откладываем до семантики) + localsTypeMapHelper = new yield_locals_type_map_helper(); + LocalVariablesTypeDetectorHelperVisior localsTypeDetectorHelperVisitor = new LocalVariablesTypeDetectorHelperVisior(localsTypeMapHelper); + pdCloned.visit(localsTypeDetectorHelperVisitor); + + // frninja 16/03/16 - строим список локальных переменных в правильном порядке + localsTypeDetectorHelperVisitor.LocalDeletedDefs.AddRange(localsTypeDetectorHelperVisitor.LocalDeletedVS); + localsTypeDetectorHelperVisitor.LocalDeletedVS.Clear(); + + localsClonesCollection = localsTypeDetectorHelperVisitor.LocalDeletedDefs.ToArray(); + + // Добавляем в класс метод с обертками для локальных переменных + pdCloned.proc_header.name.meth_name = new ident(YieldConsts.YieldHelperMethodPrefix+ "_locals_type_detector>" + pd.proc_header.name.meth_name.name); // = new method_name("" + pd.proc_header.className.meth_name.className); + if (IsClassMethod(pd)) + { + var cd = UpperTo(); + if (cd != null) + { + // Метод класса описан в классе + var classMembers = UpperTo(); + classMembers.Add(pdCloned); + } + else + { + // Метод класса описан вне класса + + var decls = UpperTo(); + var classMembers = decls.list + .Select(decl => decl as type_declarations) + .Where(tdecls => tdecls != null) + .SelectMany(tdecls => tdecls.types_decl) + .Where(td => td.type_name.name == GetClassName(pd).name) + .Select(td => td.type_def as class_definition) + .Where(_cd => _cd != null) + .SelectMany(_cd => _cd.body.class_def_blocks); + + + // Вставляем предописание метода-хелпера + var helperPredefHeader = ObjectCopier.Clone(pdCloned.proc_header); + helperPredefHeader.name.class_name = null; + classMembers.First().members.Insert(0, helperPredefHeader); + + // Вставляем тело метода-хелпера + UpperTo().InsertBefore(pd, pdCloned); + } + } + else + { + UpperTo().InsertBefore(pd, pdCloned); + } + } + + /// + /// Отображение локальных в клонированные локальные + /// + /// Откуда + /// Куда + /// Отображение + private Dictionary CreateLocalsClonesMap(IEnumerable from, IEnumerable to) + { + // Нужно тк клонировали метод для создания хелпера-определителя типов локальных переменных - Eq не будет работать + + // Строим отображение из локальных переменных клона оригинального метода в локальные переменные основного метода + Dictionary localsClonesMap = new Dictionary(); + + var localsArr = from.ToArray(); + var localsClonesArr = to.ToArray(); + + // Create map :: locals -> cloned locals + for (int i = 0; i < localsArr.Length; ++i) + { + localsClonesMap.Add(localsArr[i], localsClonesArr[i]); + } + + return localsClonesMap; + } + + /// + /// Вставляем описание классов-хелперов для yield перед методом-итератором в зависимости от его описания + /// + /// Метод-итератор + /// Описание классов-хелперов для yield + private void InsertYieldHelpers(procedure_definition pd, type_declarations cct) + { + if (IsClassMethod(pd)) + { + var cd = UpperTo(); + if (cd != null) + { + // Если метод класса описан в классе + var td = UpperTo(); + + // frninja 20/04/16 - выпилено + + //foreach (var helperName in cct.types_decl.Select(ttd => ttd.type_name)) + //{ + // var helperPredef = new type_declaration(helperName, new class_definition()); + //td.types_decl.Insert(0, helperPredef); + //} + + // Insert class predefenition! + //var iteratorClassPredef = new type_declaration(GetClassName(pd), new class_definition(null)); + //td.types_decl.Insert(0, iteratorClassPredef); + + foreach (var helper in cct.types_decl) + { + td.types_decl.Add(helper); + } + + } + else + { + // Метод класса описан вне класса + UpperTo().InsertBefore(pd, cct); + } + } + else + { + UpperTo().InsertBefore(pd, cct); + } + } + + /// + /// Захватываем имена в методе + /// + /// Метод-итератор + /// Коллекция удаленных локальных переменных + /// Построенное отображение имен локальных переменных в захваченные имена + /// Построенное отображение имен формальных параметров в захваченные имена + private void ReplaceCapturedVariables(procedure_definition pd, + IEnumerable deletedLocals, + out IDictionary capturedLocalsNamesMap, + out IDictionary capturedFormalParamsNamesMap) + { + // Структуры данных под классификацию имен в методе + + // Classification + ISet CollectedLocalsNames = new HashSet(); + ISet CollectedFormalParamsNames = new HashSet(); + ISet CollectedClassFieldsNames = new HashSet(); + ISet CollectedClassMethodsNames = new HashSet(); + ISet CollectedClassPropertiesNames = new HashSet(); + ISet CollectedUnitGlobalsNames = new HashSet(); + + ISet CollectedLocals = new HashSet(); + ISet CollectedFormalParams = new HashSet(); + + // Map from ident idName -> captured ident idName + capturedLocalsNamesMap = new Dictionary(); + capturedFormalParamsNamesMap = new Dictionary(); + + // Собираем инфу о именах + + // Collect locals + CollectedLocals.UnionWith(deletedLocals); + CollectedLocalsNames.UnionWith(deletedLocals.SelectMany(vds => vds.vars.idents).Select(id => id.name)); + // Collect formal params + CollectFormalParams(pd, CollectedFormalParams); + CollectFormalParamsNames(pd, CollectedFormalParamsNames); + // Collect class fields + CollectClassFieldsNames(pd, CollectedClassFieldsNames); + // Collect class methods + CollectClassMethodsNames(pd, CollectedClassMethodsNames); + // Collect class properties + CollectClassPropertiesNames(pd, CollectedClassPropertiesNames); + // Collect unit globals + CollectUnitGlobalsNames(pd, CollectedUnitGlobalsNames); + + // Строим отображения для имён захваченных локальных переменных и формальных параметров + + // Create maps :: idName -> captureName + CreateCapturedLocalsNamesMap(CollectedLocalsNames, capturedLocalsNamesMap); + CreateCapturedFormalParamsNamesMap(CollectedFormalParamsNames, capturedFormalParamsNamesMap); + + // Выполняем замену захват имён в теле метода + // AHAHA test! + ReplaceCapturedVariablesVisitor rcapVis = new ReplaceCapturedVariablesVisitor( + CollectedLocalsNames, + CollectedFormalParamsNames, + CollectedClassFieldsNames, + CollectedClassMethodsNames, + CollectedClassPropertiesNames, + CollectedUnitGlobalsNames, + capturedLocalsNamesMap, + capturedFormalParamsNamesMap, + IsClassMethod(pd), + GetClassName(pd) + ); + // Replace + (pd.proc_body as block).program_code.visit(rcapVis); + } + + private bool IsExtensionMethod(procedure_definition pd) + { + var tdecls = UpperTo().defs.OfType().SelectMany(tds => tds.types_decl); + + var isExtension = pd.proc_header.proc_attributes.proc_attributes.Any(attr => attr.name == "extensionmethod"); + + if (isExtension) + { + // Метод объявлен как extensionmethod + + // !!!!!!!! TODO: Проверить что имя класса не находится в этом модуле. + + // Убираем за ненадобностью имя класса ибо оно указано как тип обязательного параметра self + + pd.proc_header.name.class_name = null; + return true; + } + else + { + // Если не похоже на метод-расширение или объявление вне класса + if (pd.proc_header.name.class_name == null) + return false; + + + // Разрешаем только имена типов из этого модуля (не расширения) + if (!tdecls.Any(td => td.type_name.name == pd.proc_header.name.class_name.name)) + { + // Имя в модуле не найдено -> метод расширение описанный без extensionmethod. Ругаемся!!! + throw new SyntaxError("Possible extension-method definintion without extensionmethod keyword. Please use extensionmethod syntax", + "", + pd.proc_header.source_context, + pd.proc_header); + } + + } + + return false; + } + + public override void visit(procedure_definition pd) + { + if (!pd.has_yield) + return; + + /*if (pd != null && pd.proc_header != null && pd.proc_header.name != null && pd.proc_header.name.meth_name != null && pd.proc_header.name.meth_name.name != null) + if (pd.proc_header.name.meth_name.name.StartsWith(YieldConsts.YieldHelperMethodPrefix)) + return; + */ + + //var isExtension = IsExtensionMethod(pd); + + //hasYields = false; + //if (pd.proc_header is function_header) + // mids = new FindMainIdentsVisitor(); + + //base.visit(pd); + + //if (!hasYields) // т.е. мы разобрали функцию и уже выходим. Это значит, что пока yield будет обрабатываться только в функциях. Так это и надо. + // return; + + // Проверяем проблемы имен для for + CheckVariablesRedefenitionVisitor checkVarRedefVisitor = new CheckVariablesRedefenitionVisitor( + new HashSet( + pd.proc_header.parameters != null + ? + pd.proc_header.parameters.params_list.SelectMany(fp => fp.idents.idents.Select(id => id.name)) + : + Enumerable.Empty())); + pd.visit(checkVarRedefVisitor); + + // Переименовываем одинаковые имена в мини-ПИ + RenameSameBlockLocalVarsVisitor renameLocalsVisitor = new RenameSameBlockLocalVarsVisitor(); + pd.visit(renameLocalsVisitor); + + // Теперь lowering + LoweringVisitor.Accept(pd); + + // frninja 13/04/16 - убираем лишние begin..end + DeleteRedundantBeginEnds deleteBeginEndVisitor = new DeleteRedundantBeginEnds(); + pd.visit(deleteBeginEndVisitor); + + // Обработка метода для корректного захвата локальных переменных и их типов + yield_locals_type_map_helper localsTypeMapHelper; + IEnumerable localsClonesCollection; + CreateLocalVariablesTypeProxies(pd, out localsClonesCollection, out localsTypeMapHelper); + + + // frninja 16/11/15: перенес ниже чтобы работал захват для lowered for + + var dld = new DeleteAllLocalDefs(); // mids.vars - все захваченные переменные + pd.visit(dld); // Удалить в локальных и блочных описаниях этой процедуры все переменные и вынести их в отдельный список var_def_statement + + // Строим отображение из локальных переменных клона оригинального метода в локальные переменные основного метода + Dictionary localsCloneMap = CreateLocalsClonesMap(dld.LocalDeletedDefs, localsClonesCollection); + + // frninja 08/12/15 + + // Выполняем захват имён + IDictionary CapturedLocalsNamesMap; + IDictionary CapturedFormalParamsNamesMap; + ReplaceCapturedVariables(pd, dld.LocalDeletedDefs, out CapturedLocalsNamesMap, out CapturedFormalParamsNamesMap); + + + //mids.vars.Except(dld.LocalDeletedDefsNames); // параметры остались. Их тоже надо исключать - они и так будут обработаны + // В результате работы в mids.vars что-то осталось. Это не локальные переменные и с ними непонятно что делать + + // Обработать параметры! + // Как? Ищем в mids formal_parametrs, но надо выделить именно обращение к параметрам - не полям класса, не глобальным переменным + + var cfa = new ConstructFiniteAutomata((pd.proc_body as block).program_code); + cfa.Transform(); + + (pd.proc_body as block).program_code = cfa.res; + + // Конструируем определение класса + var cct = GenClassesForYield(pd, dld.LocalDeletedDefs, CapturedLocalsNamesMap, CapturedFormalParamsNamesMap, localsCloneMap, localsTypeMapHelper); // все удаленные описания переменных делаем описанием класса + + // Вставляем классы-хелперы + InsertYieldHelpers(pd, cct); + + + + //mids = null; // вдруг мы выйдем из процедуры, не зайдем в другую, а там - оператор! Такого конечно не может быть + } + + public override void visit(yield_node yn) + { + //hasYields = true; + //if (mids != null) // если мы - внутри процедуры + // yn.visit(mids); + //else throw new SyntaxError("Yield must be in functions only", "", yn.source_context, yn); + // mids.vars - надо установить, какие из них - локальные, какие - из этого класса, какие - являются параметрами функции, а какие - глобальные (все остальные) + // те, которые являются параметрами, надо скопировать в локальные переменные и переименовать использование везде по ходу данной функции + // самое сложное - переменные-поля этого класса - они требуют в создаваемом классе, реализующем итератор, хранить Self текущего класса и добавлять это Self везде по ходу алгоритма + // вначале будем считать, что переменные-поля этого класса и переменные-параметры не захватываются yield + //base.visit(yn); + + + } + } + + class ConstructFiniteAutomata + { + public statement_list res = new statement_list(); + statement_list stl; + int curState = 0; + + statement_list curStatList; + statement_list StatListAfterCase = new statement_list(); + + case_node cas; // формируемый case + + //private Dictionary> dispatches = new Dictionary>(); + + private labeled_statement OuterLabeledStatement; + private Dictionary Dispatches = new Dictionary(); + + public ConstructFiniteAutomata(statement_list stl) + { + this.stl = stl; + } + + private void AddState(out int stateNumber, out ident resumeLabel) + { + stateNumber = curState++; + resumeLabel = null; + } + + public void Process(statement st) + { + if (!(st is yield_node || st is labeled_statement)) + { + curStatList.Add(st); + } + if (st is yield_node) + { + + var yn = st as yield_node; + curState += 1; + curStatList.AddMany( + new assign(YieldConsts.Current, yn.ex), + new assign(YieldConsts.State, curState), + new assign("Result", true), + new procedure_call("exit") + ); + + curStatList = new statement_list(); + + case_variant cv = new case_variant(new expression_list(new int32_const(curState)), curStatList); + cas.conditions.variants.Add(cv); + } + if (st is labeled_statement) + { + var ls = st as labeled_statement; + + // frninja 13/04/16 - диспетчерезация к следующему состоянию + curStatList.Add(new goto_statement(ls.label_name)); + + curStatList = StatListAfterCase; + curStatList.Add(new labeled_statement(ls.label_name)); + Process(ls.to_statement); + + } + } + + public void Transform() + { + cas = new case_node(new ident(YieldConsts.State)); + + curStatList = new statement_list(); + case_variant cv = new case_variant(new expression_list(new int32_const(curState)), curStatList); + cas.conditions.variants.Add(cv); + + foreach (var st in stl.subnodes) + Process(st); + + + + // frninja 13/04/16 - фикс для зависающего в последнем состоянии + var lastStateCV = cas.conditions.variants.Last().exec_if_true as statement_list; + if (lastStateCV != null) + { + lastStateCV.Add(new procedure_call("exit")); + } + + stl.subnodes = BaseChangeVisitor.SeqStatements(cas, StatListAfterCase).ToList(); + //statement_list res = new statement_list(cas); + res = stl; + } + } + +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/RenameSameBlockLocalVarsVisitor.cs b/Yield/SyntaxVisitors/YieldVisitors/RenameSameBlockLocalVarsVisitor.cs new file mode 100644 index 000000000..06d67e34b --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/RenameSameBlockLocalVarsVisitor.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class RenameSameBlockLocalVarsVisitor : BaseChangeVisitor + { + // Надо хранить принадлежность имени конкретному ПИ на определенном уровне вложенности + // И отображение этого имени в новое + + // Map :: CurrentLevel -> { BlockName -> NewBlockName } + private List> BlockNamesStack { get; set; } + + private Dictionary BlockNamesCounter { get; set; } + + + private int CurrentLevel = -1; + + public RenameSameBlockLocalVarsVisitor() + { + this.BlockNamesStack = new List>(); + this.BlockNamesCounter = new Dictionary(); + } + + public override void visit(declarations decls) + { + // Для обхода в правильном порядке сверху вниз + var vd_s = decls.defs.OfType().ToArray(); + for (int i = 0; i < vd_s.Count(); ++i) + { + ProcessNode(vd_s[i]); + } + } + + public override void visit(procedure_header pd) + { + // DO NOTHING + } + + public override void visit(function_header fh) + { + // DO NOTHING + } + + public override void visit(formal_parameters fp) + { + // DO NOTHING + } + + public override void visit(statement_list stlist) + { + ++CurrentLevel; + + if (BlockNamesStack.Count <= CurrentLevel) + { + // Создаем отображение для имен текущего уровня вложенности мини-пространства имен + BlockNamesStack.Add(new Dictionary()); + } + + //base.visit(stlist); + for (var i = 0; i < stlist.list.Count; ++i) + ProcessNode(stlist.list[i]); + + BlockNamesStack.RemoveAt(BlockNamesStack.Count - 1); + + --CurrentLevel; + } + + public override void visit(var_statement vs) + { + if (vs.var_def.vars.idents.Any(id => id.name.StartsWith("$"))) + return; + + var newLocalNames = vs.var_def.vars.idents.Select(id => + { + var newName = this.CreateNewVariableName(id.name); + BlockNamesStack[CurrentLevel].Add(id.name, newName); + return new ident(newName, id.source_context); + }); + + var newVS = new var_statement(new var_def_statement(new ident_list(newLocalNames.ToArray()), + vs.var_def.vars_type, + vs.var_def.inital_value)); + + Replace(vs, newVS); + + base.visit(newVS); + } + + public override void visit(variable_definitions vd) + { + if (vd.var_definitions.Any(vds => vds.vars.idents.Any(id => id.name.StartsWith("$")))) + return; + + ++CurrentLevel; + + if (BlockNamesStack.Count <= CurrentLevel) + { + // Создаем отображение для имен текущего уровня вложенности мини-пространства имен + BlockNamesStack.Add(new Dictionary()); + } + + var newVD = new variable_definitions( + vd.var_definitions.Select(vds => + { + var newLocalNames = vds.vars.idents.Select(id => + { + var newName = this.CreateNewVariableName(id.name); + BlockNamesStack[CurrentLevel].Add(id.name, newName); + return new ident(newName, id.source_context); + }); + + return new var_def_statement(new ident_list(newLocalNames.ToArray()), vds.vars_type, vds.inital_value); + }).ToList(), + vd.source_context); + + Replace(vd, newVD); + base.visit(newVD); + } + + public override void visit(ident id) + { + var newName = this.GetNewVariableName(id.name); + if ((object)newName != null) + { + Replace(id, new ident(newName, id.source_context)); + } + } + + public override void visit(dot_node dn) + { + ProcessNode(dn.left); + if (dn.right.GetType() != typeof(ident)) + ProcessNode(dn.right); + } + + private string CreateNewVariableName(string name) + { + if (BlockNamesCounter.ContainsKey(name)) + { + ++BlockNamesCounter[name]; + } + else + { + BlockNamesCounter.Add(name, 0); + } + return "$" + name + "__" + BlockNamesCounter[name]; + } + + private string GetNewVariableName(string name) + { + for (int i = CurrentLevel; i >= 0; --i) + { + if (BlockNamesStack[i].ContainsKey(name)) + { + return BlockNamesStack[i][name]; + } + } + return null; + } + } +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/ReplaceCapturedVariablesVisitor.cs b/Yield/SyntaxVisitors/YieldVisitors/ReplaceCapturedVariablesVisitor.cs new file mode 100644 index 000000000..6f6a835de --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/ReplaceCapturedVariablesVisitor.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +using PascalABCCompiler.YieldHelpers; + +namespace SyntaxVisitors +{ + public class ReplaceCapturedVariablesVisitor : BaseChangeVisitor + { + private ISet CollectedLocals = new HashSet(); + private ISet CollectedFormalParams = new HashSet(); + private ISet CollectedClassFields = new HashSet(); + private ISet CollectedUnitGlobals = new HashSet(); + + // Maps :: idName -> capturedName + private IDictionary CapturedLocalsMap = new Dictionary(); + private IDictionary CapturedFormalParamsMap = new Dictionary(); + + private bool IsInClassMethod = true; + + private ident ClassName; + + + public ReplaceCapturedVariablesVisitor(IEnumerable locals, + IEnumerable formalParams, + IEnumerable classFields, + IEnumerable classMethods, + IEnumerable classProperties, + IEnumerable unitGlobals, + IDictionary localsMap, + IDictionary formalParamsMap, + bool isInClassMethod, ident className) + { + CollectedLocals = new HashSet(locals); + CollectedFormalParams = new HashSet(formalParams); + CollectedClassFields = new HashSet(classFields); + CollectedUnitGlobals = new HashSet(unitGlobals); + + CapturedLocalsMap = new Dictionary(localsMap); + CapturedFormalParamsMap = new Dictionary(formalParamsMap); + + IsInClassMethod = isInClassMethod; + ClassName = className; + + // Methods hack + CollectedClassFields.UnionWith(classMethods); + // Properties hack + CollectedClassFields.UnionWith(classProperties); + + } + + public override void visit(labeled_statement ls) + { + ProcessNode(ls.to_statement); + } + + public override void visit(goto_statement gt) + { + // Empty + } + + // frninja 12/05/16 - фикс для yield_unknown_ident + public override void visit(yield_unknown_ident unk) + { + yield_var_def_statement_with_unknown_type x; + // Empty + } + + public override void visit(ident id) + { + // Check dot node + var upper = UpperNode(1); + //if (upper is dot_node) + // return; + + var idName = id.name; + var idSourceContext = id.source_context; + + // frninja 31/03/16 - фикс селфа для extensionmethod + if (idName.ToLower() == "self" && !CollectedFormalParams.Contains(idName)) + { + var newSelf = new dot_node(new ident("self"), new ident(YieldConsts.Self)); + Replace(id, newSelf); + return; + } + + // Detect where is id from + if (CollectedLocals.Contains(idName)) + { + Replace(id, new ident(CapturedLocalsMap[idName], idSourceContext)); + } + else if (CollectedFormalParams.Contains(idName)) + { + Replace(id, new ident(CapturedFormalParamsMap[idName], idSourceContext)); + } + else if (IsInClassMethod) + { + // In class -> check fields + if (CollectedClassFields.Contains(idName)) + { + // Good + // Name in class fields -> capture as class field + + + var capturedId = new dot_node(new dot_node(new ident("self"), new ident(YieldConsts.Self)), id); + Replace(id, capturedId); + } + else + { + // Bad + // At syntax we don't know if the className is class field or not coz of e.g. base .NET classes + // HERE WE SHOULD REPLACE TO yield_unknown_reference -> so decision is passed to semantic + // Check for globals will be processed at semantic, too + + if (!id.name.StartsWith("<")) // Check for already captured + { + Replace(id, new yield_unknown_ident(id, ClassName)); + } + } + } + else + { + // Not in class -> check globals + if (CollectedUnitGlobals.Contains(idName)) + { + // Global -> just do nothing + } + else + { + // What about static classes - search at semantic + // HERE WE SHOULD REPLACE TO yield_unknown_reference -> so decision is passed to semantic + } + } + } + + + /*public override void visit(procedure_call pc) + { + ProcessNode(pc.func_name); + var methCall = pc.func_name as method_call; + if ((object)methCall != null) + { + foreach (var param in methCall.parameters.expressions) + { + param.visit(this); + } + } + }*/ + + public override void visit(dot_node dn) + { + var rid = dn.right as ident; + if ((object)rid != null && rid.name != YieldConsts.Self) + ProcessNode(dn.left); + + // Most nested + // DotNode (DLeft, DRight) -> DotNode(DotNode("self", "<>__self"), DRight) + + + // LEFT self -> captured self (self.captured_self) + /*var id = dn.left as ident; + if ((object)id != null && (id.className == "self" || CollectedClassFields.Contains(id.className))) + { + // Some magic for blocking back-traverse from BaseChangeVisitor redoin' work + //var rid = dn.right as ident; + //if ((object)rid != null && rid.className != Consts.Self) + { + var newDotNode = new dot_node(new dot_node(new ident("self"), new ident(Consts.Self)), dn.right); + // Change right? + //var capturedRight = new dot_node(new ident(Consts.Self), dn.right); + //var newDotNode = new dot_node(dn.left, capturedRight); + Replace(dn, newDotNode); + } + + + // Some magic for blocking back-traverse from BaseChangeVisitor redoin' work + //var rid = dn.right as ident; + //if ((object)rid != null && rid.className != Consts.Self) + // { + // var capturedSelf = new dot_node(new ident("self"), new ident(Consts.Self)); + // Replace(dn.left, capturedSelf); + // } + } + else + { + ProcessNode(dn.left); + }*/ + + //if (dn.right.GetType() != typeof(ident)) + // ProcessNode(dn.right); + } + } +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/ReplaceForVariableVisitor.cs b/Yield/SyntaxVisitors/YieldVisitors/ReplaceForVariableVisitor.cs new file mode 100644 index 000000000..1bb7a69dc --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/ReplaceForVariableVisitor.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class ReplaceForVariableVisitor : BaseChangeVisitor + { + private ident _oldName; + private ident _newName; + + public ReplaceForVariableVisitor(ident oldName, ident newName) + { + _oldName = oldName; + _newName = newName; + } + + public override void visit(ident id) + { + if (id.name != _oldName.name) + { + return; + } + + var upperNode = UpperNode(); + if ( + (object)upperNode != null && (object)(upperNode as dot_node) == null) + { + Replace(id, _newName); + } + } + + // frninja 11/03/16 - оно тут вообще надо??? + public override void visit(dot_node dn) + { + ProcessNode(dn.left); + if (dn.right.GetType() != typeof(ident)) + ProcessNode(dn.right); + } + } +} diff --git a/Yield/SyntaxVisitors/YieldVisitors/ReplaceFormalParametersRefsVisitor.cs b/Yield/SyntaxVisitors/YieldVisitors/ReplaceFormalParametersRefsVisitor.cs new file mode 100644 index 000000000..eb4f40b7f --- /dev/null +++ b/Yield/SyntaxVisitors/YieldVisitors/ReplaceFormalParametersRefsVisitor.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors +{ + public class ReplaceFormalParametersRefsVisitor : BaseChangeVisitor + { + public Dictionary CollectedFormalParameters = new Dictionary(); + + // Типа-стек соответствий paramName -> <>num__paramName для разных уровней вложенности методов + private List> formalParametersStack = new List>(); + + private bool _isClassMethod = false; + + + public ReplaceFormalParametersRefsVisitor() + { + } + + // Лучше запретить yield в вложенных функциях и в функциях со вложенными! + // Запретить-запретить-запретить + + public override void visit(procedure_definition pd) + { + // var u = UpperNode(3); + // В случае отсутствия формальных параметров + if ((object)pd.proc_header.parameters == null) + { + base.visit(pd.proc_body); + return; + } + + formalParametersStack.Add(new Dictionary()); + int currentLevel = formalParametersStack.Count - 1; + + foreach (var plist in pd.proc_header.parameters.params_list) + { + foreach (var id in plist.idents.idents) + { + var paramName = id.name; + var hoistedParamName = CapturedNamesHelper.MakeCapturedFormalParameterName(id.name); + + formalParametersStack[currentLevel].Add(paramName, hoistedParamName); + + // Захват + CollectedFormalParameters.Add(hoistedParamName, plist.vars_type); + } + } + + base.visit(pd.proc_body); + + formalParametersStack.RemoveAt(currentLevel); + } + + + + + public override void visit(ident id) + { + int? paramNameLevel = null; + + var paramName = id.name; + + // Ищем с какого уровня имя + for (int level = formalParametersStack.Count - 1; level >= 0; --level) + { + if (formalParametersStack[level].ContainsKey(paramName)) + { + // Нашли! + paramNameLevel = level; + break; + } + } + + bool isField = false; + + // Локальные параметры обрабатываются в другом визиторе + + // Параметр функции + if ((object)paramNameLevel != null) + { + var upper = UpperNode(); + // Подозреваем обращение к параметру метода + if ((object)upper == null || (object)upper != null && (upper as dot_node) == null) + { + // Это не self.paramName - поле класса и не что-то другое? + // Нашли обращение к параметру? + + var self = new ident("self", id.source_context); + + // Заменяем paramName -> self.hoistedParamName: <>num__paramName + + var hoistedParamName = new ident(formalParametersStack[(int)paramNameLevel][paramName], id.source_context); + + var selfId = new dot_node(self, hoistedParamName); + + Replace(id, selfId); + } + // Иначе проверить что это поле класса! self.paramName или какой-то другой очень извращенный вариант вроде (someMethod: self).paramName + } + + // Поле класса + + // Параметр внешней функции (если наша - вложенная) + + // Глобальная переменная + } + + } +} diff --git a/Yield/YieldConversionSyntax/.gitignore b/Yield/YieldConversionSyntax/.gitignore new file mode 100644 index 000000000..893c20ff6 --- /dev/null +++ b/Yield/YieldConversionSyntax/.gitignore @@ -0,0 +1,167 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates +.vs/ + +# Build results +[Bb]inaries/ +[Dd]ebug/ +[Rr]elease/ +x64/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# NuGet restore semaphore +build/ToolsetPackages/toolsetpackages.semaphore + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* +UnitTestResults.html + +# NuGet V3 artifacts +*-packages.config +*.nuget.props +*.nuget.targets + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.wrn +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual Studio cache files +*.sln.ide/ + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# NuGet Packages Directory +packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store diff --git a/Yield/YieldConversionSyntax/Properties/AssemblyInfo.cs b/Yield/YieldConversionSyntax/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..f5e475ef3 --- /dev/null +++ b/Yield/YieldConversionSyntax/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("YieldConversionSyntax")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Hewlett-Packard")] +[assembly: AssemblyProduct("YieldConversionSyntax")] +[assembly: AssemblyCopyright("Copyright © Hewlett-Packard 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("4517de68-2805-461c-a8ac-5f9684772182")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Yield/YieldConversionSyntax/YieldConversionSyntax.csproj b/Yield/YieldConversionSyntax/YieldConversionSyntax.csproj new file mode 100644 index 000000000..911305df4 --- /dev/null +++ b/Yield/YieldConversionSyntax/YieldConversionSyntax.csproj @@ -0,0 +1,72 @@ + + + + + Debug + AnyCPU + {276EE073-60F6-46D2-8811-1B8026BCAADA} + Library + Properties + YieldConversionSyntax + YieldConversionSyntax + v4.0 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + {1e42361a-eda3-4872-88af-a3aaf600d36d} + Compiler + + + {f10a5330-dcf4-4533-877c-7b1b1be23884} + SyntaxTreeConverters + + + {c2cac65a-b2ae-4ccc-b067-e6b8e75df73a} + SyntaxTree + + + {a9ab4282-83b4-41a7-86c3-e5bf6a45e7e2} + SyntaxVisitors + + + + + \ No newline at end of file diff --git a/Yield/YieldConversionSyntax/YieldDesugarSyntaxTreeConverter.cs b/Yield/YieldConversionSyntax/YieldDesugarSyntaxTreeConverter.cs new file mode 100644 index 000000000..a13f8ef7c --- /dev/null +++ b/Yield/YieldConversionSyntax/YieldDesugarSyntaxTreeConverter.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +using SyntaxVisitors; + +using PascalABCCompiler.SyntaxTreeConverters; + +namespace YieldDesugarSyntaxTreeConverter +{ + public class YieldDesugarSyntaxTreeConverter : ISyntaxTreeConverter + { + public string Name { get; set; } + public string Version { get; set; } + public string Description { get; set; } + public string Copyright { get; set; } + + public ConverterType ConverterType { get; set; } + public ExecutionOrder ExecutionOrder { get; set; } + public syntax_tree_node Convert(syntax_tree_node root) + { + root.visit(new MarkMethodHasYieldVisitor()); + root.visit(new ProcessYieldCapturedVarsVisitor()); + + return root; + } + + /*public void Change(syntax_tree_node sn) + { + //sn.visit(new CalcConstExprs()); + //sn.visit(new LoweringVisitor()); + sn.visit(new ProcessYieldCapturedVarsVisitor()); + + }*/ + + } +} diff --git a/Yield/YieldHelpers/.gitignore b/Yield/YieldHelpers/.gitignore new file mode 100644 index 000000000..893c20ff6 --- /dev/null +++ b/Yield/YieldHelpers/.gitignore @@ -0,0 +1,167 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates +.vs/ + +# Build results +[Bb]inaries/ +[Dd]ebug/ +[Rr]elease/ +x64/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# NuGet restore semaphore +build/ToolsetPackages/toolsetpackages.semaphore + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* +UnitTestResults.html + +# NuGet V3 artifacts +*-packages.config +*.nuget.props +*.nuget.targets + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.wrn +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual Studio cache files +*.sln.ide/ + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# NuGet Packages Directory +packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store diff --git a/Yield/YieldHelpers/Properties/AssemblyInfo.cs b/Yield/YieldHelpers/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..c7bdf8aae --- /dev/null +++ b/Yield/YieldHelpers/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("YieldHelpers")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Hewlett-Packard")] +[assembly: AssemblyProduct("YieldHelpers")] +[assembly: AssemblyCopyright("Copyright © Hewlett-Packard 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("1befc5f9-6102-4f55-b677-5457ebcd6327")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Yield/YieldHelpers/YieldConsts.cs b/Yield/YieldHelpers/YieldConsts.cs new file mode 100644 index 000000000..605870984 --- /dev/null +++ b/Yield/YieldHelpers/YieldConsts.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PascalABCCompiler.YieldHelpers +{ + public static class YieldConsts + { + public static string Current = "<>2__current"; + public static string State = "<>1__state"; + + public static string Self = "<>4__self"; + + public static string YieldHelperMethodPrefix = " + + + + Debug + AnyCPU + {CE5C55C2-A11C-4E94-A9FA-3FC6CA3E4C09} + Library + Properties + YieldHelpers + YieldHelpers + v4.0 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Yield/tests/.gitignore b/Yield/tests/.gitignore new file mode 100644 index 000000000..893c20ff6 --- /dev/null +++ b/Yield/tests/.gitignore @@ -0,0 +1,167 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates +.vs/ + +# Build results +[Bb]inaries/ +[Dd]ebug/ +[Rr]elease/ +x64/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# NuGet restore semaphore +build/ToolsetPackages/toolsetpackages.semaphore + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* +UnitTestResults.html + +# NuGet V3 artifacts +*-packages.config +*.nuget.props +*.nuget.targets + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.wrn +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual Studio cache files +*.sln.ide/ + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# NuGet Packages Directory +packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store diff --git a/Yield/tests/TestClassFieldsCollector.exe b/Yield/tests/TestClassFieldsCollector.exe new file mode 100644 index 000000000..9d323b1b7 Binary files /dev/null and b/Yield/tests/TestClassFieldsCollector.exe differ diff --git a/Yield/tests/TestClassFieldsCollector.pas b/Yield/tests/TestClassFieldsCollector.pas new file mode 100644 index 000000000..1495f77de --- /dev/null +++ b/Yield/tests/TestClassFieldsCollector.pas @@ -0,0 +1,29 @@ +type A = class; + +type A = class + field1: integer; + field2: integer; + + procedure fun1; + begin + field1 += 1; + end; + + procedure fun2; +end; + +type B = class +end; + +procedure A.fun2; +begin + field1 += 1; + field2 += 4; +end; + +procedure fun3; +begin +end; + +begin +end. \ No newline at end of file diff --git a/Yield/tests/TestUnitGlobalsCollector.exe b/Yield/tests/TestUnitGlobalsCollector.exe new file mode 100644 index 000000000..e69de29bb diff --git a/Yield/tests/TestUnitGlobalsCollector.pas b/Yield/tests/TestUnitGlobalsCollector.pas new file mode 100644 index 000000000..4a48196d9 --- /dev/null +++ b/Yield/tests/TestUnitGlobalsCollector.pas @@ -0,0 +1,14 @@ +//unit TestUnitGlobalsCollector; + +//interface +var testGlobal: integer; + +//implementation +//var testGlobalImpl: integer; +type A = class + testField: integer; +end; + +begin + testGlobal := 777; +end. \ No newline at end of file diff --git a/Yield/tests/TestUnitGlobalsCollector.pcu b/Yield/tests/TestUnitGlobalsCollector.pcu new file mode 100644 index 000000000..13b563a63 Binary files /dev/null and b/Yield/tests/TestUnitGlobalsCollector.pcu differ diff --git a/Yield/tests/UnitClass.pas b/Yield/tests/UnitClass.pas new file mode 100644 index 000000000..81f8109dd --- /dev/null +++ b/Yield/tests/UnitClass.pas @@ -0,0 +1,10 @@ +unit UnitClass; + +interface +type UnitClassTest = class + testField: real; +end; + +implementation + +end. \ No newline at end of file diff --git a/Yield/tests/basic/yieldSimpleExternalClassDef.exe b/Yield/tests/basic/yieldSimpleExternalClassDef.exe new file mode 100644 index 000000000..e8e71ca4a Binary files /dev/null and b/Yield/tests/basic/yieldSimpleExternalClassDef.exe differ diff --git a/Yield/tests/basic/yieldSimpleExternalClassDef.pas b/Yield/tests/basic/yieldSimpleExternalClassDef.pas new file mode 100644 index 000000000..fe8fa4741 --- /dev/null +++ b/Yield/tests/basic/yieldSimpleExternalClassDef.pas @@ -0,0 +1,17 @@ +type A = class + testField: real; + + function Gen: sequence of real; + +end; + +function A.Gen: sequence of real; +begin + yield testField; +end; + + +begin + var q := new A(); + q.Gen.Println; +end. \ No newline at end of file diff --git a/Yield/tests/basic/yieldSimpleInClassDef.exe b/Yield/tests/basic/yieldSimpleInClassDef.exe new file mode 100644 index 000000000..a544a6200 Binary files /dev/null and b/Yield/tests/basic/yieldSimpleInClassDef.exe differ diff --git a/Yield/tests/basic/yieldSimpleInClassDef.pas b/Yield/tests/basic/yieldSimpleInClassDef.pas new file mode 100644 index 000000000..d4b4313a4 --- /dev/null +++ b/Yield/tests/basic/yieldSimpleInClassDef.pas @@ -0,0 +1,15 @@ +type A = class + testField: real; + + function Gen: sequence of real; + begin + yield testField; + end; + +end; + + +begin + var q := new A(); + q.Gen.Println; +end. \ No newline at end of file diff --git a/Yield/tests/basic/yieldSimpleMethodDef.exe b/Yield/tests/basic/yieldSimpleMethodDef.exe new file mode 100644 index 000000000..f0e4e97aa Binary files /dev/null and b/Yield/tests/basic/yieldSimpleMethodDef.exe differ diff --git a/Yield/tests/basic/yieldSimpleMethodDef.pas b/Yield/tests/basic/yieldSimpleMethodDef.pas new file mode 100644 index 000000000..e7e7d0173 --- /dev/null +++ b/Yield/tests/basic/yieldSimpleMethodDef.pas @@ -0,0 +1,9 @@ +function Gen: sequence of real; +begin + yield 1; +end; + + +begin + Gen.Println; +end. \ No newline at end of file diff --git a/Yield/tests/basic/yieldSimpleMethodDef2.exe b/Yield/tests/basic/yieldSimpleMethodDef2.exe new file mode 100644 index 000000000..83d38868f Binary files /dev/null and b/Yield/tests/basic/yieldSimpleMethodDef2.exe differ diff --git a/Yield/tests/basic/yieldSimpleMethodDef2.pas b/Yield/tests/basic/yieldSimpleMethodDef2.pas new file mode 100644 index 000000000..5eaacce25 --- /dev/null +++ b/Yield/tests/basic/yieldSimpleMethodDef2.pas @@ -0,0 +1,10 @@ +function Gen: sequence of real; +begin + yield 1; +end; + + +begin + foreach var x in Gen() do + write(x, ' '); +end. \ No newline at end of file diff --git a/Yield/tests/basic/yieldSimpleMethodDef_old.exe b/Yield/tests/basic/yieldSimpleMethodDef_old.exe new file mode 100644 index 000000000..0d2fe24eb Binary files /dev/null and b/Yield/tests/basic/yieldSimpleMethodDef_old.exe differ diff --git a/Yield/tests/template/yieldMethodTemplate.exe b/Yield/tests/template/yieldMethodTemplate.exe new file mode 100644 index 000000000..e69de29bb diff --git a/Yield/tests/template/yieldMethodTemplate.pas b/Yield/tests/template/yieldMethodTemplate.pas new file mode 100644 index 000000000..d8c1d7a8e --- /dev/null +++ b/Yield/tests/template/yieldMethodTemplate.pas @@ -0,0 +1,9 @@ +function Gen: sequence of T; +begin + yield default(T); +end; + + +begin + Gen&.Println; +end. \ No newline at end of file diff --git a/Yield/tests/template/yieldSimpleTemplate.pas b/Yield/tests/template/yieldSimpleTemplate.pas new file mode 100644 index 000000000..3c9103d48 --- /dev/null +++ b/Yield/tests/template/yieldSimpleTemplate.pas @@ -0,0 +1,15 @@ +type A = class + testField: T; + + function Gen: sequence of T; + begin + yield testField; + end; + +end; + + +begin + var q := new A(); + q.Gen.Println; +end. \ No newline at end of file diff --git a/Yield/tests/template/yieldSimpleTemplateWithField.exe b/Yield/tests/template/yieldSimpleTemplateWithField.exe new file mode 100644 index 000000000..5af791822 Binary files /dev/null and b/Yield/tests/template/yieldSimpleTemplateWithField.exe differ diff --git a/Yield/tests/template/yieldSimpleTemplateWithField.pas b/Yield/tests/template/yieldSimpleTemplateWithField.pas new file mode 100644 index 000000000..e8cb28361 --- /dev/null +++ b/Yield/tests/template/yieldSimpleTemplateWithField.pas @@ -0,0 +1,19 @@ +type B = class + testBaseField: T; +end; + +type A = class(B) + testField: T; + + function Gen: sequence of T; + begin + yield testBaseField; + end; + +end; + + +begin + var q := new A(); + q.Gen.Println; +end. \ No newline at end of file diff --git a/Yield/tests/testFor.exe b/Yield/tests/testFor.exe new file mode 100644 index 000000000..e036bded4 Binary files /dev/null and b/Yield/tests/testFor.exe differ diff --git a/Yield/tests/testFor.pas b/Yield/tests/testFor.pas new file mode 100644 index 000000000..ec19893cb --- /dev/null +++ b/Yield/tests/testFor.pas @@ -0,0 +1,27 @@ +var i: integer; + +function Gen: sequence of integer; +begin + for var i := 10 downto 1 do + yield i; + for var i := 2 to 5 do + begin + if (i mod 2 = 0) then + begin + yield i; + end; + end +end; + +(* procedure Gen; +begin + for var i := 10 downto 1 do + writeln(i); +end; *) + +begin + //Gen(); + var q := Gen(); + foreach var e in q do + writeln(e); +end. \ No newline at end of file diff --git a/Yield/tests/testFor2.exe b/Yield/tests/testFor2.exe new file mode 100644 index 000000000..1d0984b66 Binary files /dev/null and b/Yield/tests/testFor2.exe differ diff --git a/Yield/tests/testFor2.pas b/Yield/tests/testFor2.pas new file mode 100644 index 000000000..e07df1be4 --- /dev/null +++ b/Yield/tests/testFor2.pas @@ -0,0 +1,20 @@ +var i: integer; + +procedure Gen; +begin + for var i := 10 downto 1 do + writeln(i); + for var i := 2 to 5 do + begin + if (i mod 2 = 0) then + begin + writeln(i); + end; + end +end; + + +begin + Gen(); + +end. \ No newline at end of file diff --git a/Yield/tests/testFor3.exe b/Yield/tests/testFor3.exe new file mode 100644 index 000000000..3735276c3 Binary files /dev/null and b/Yield/tests/testFor3.exe differ diff --git a/Yield/tests/testFor3.pas b/Yield/tests/testFor3.pas new file mode 100644 index 000000000..53f23c55b --- /dev/null +++ b/Yield/tests/testFor3.pas @@ -0,0 +1,19 @@ +var i: integer; + +function Gen: sequence of integer; +begin + for var i := 2 to 5 do + begin + if (i mod 2 = 0) then + begin + yield i; + end; + end +end; + + +begin + var q := Gen(); + foreach var x in q do + writeln(x); +end. \ No newline at end of file diff --git a/Yield/tests/testIf.exe b/Yield/tests/testIf.exe new file mode 100644 index 000000000..f5f58b1aa Binary files /dev/null and b/Yield/tests/testIf.exe differ diff --git a/Yield/tests/testIf.pas b/Yield/tests/testIf.pas new file mode 100644 index 000000000..ec74af01f --- /dev/null +++ b/Yield/tests/testIf.pas @@ -0,0 +1,25 @@ +function Gen: sequence of integer; +begin + var i := 1; + if (i mod 2 = 0) then + begin + yield i; + end; + i += 1; + if (i mod 2 = 0) then + begin + yield i; + end; + i += 1; + if (i mod 2 = 0) then + begin + yield i; + end; +end; + + +begin + var q := Gen(); + foreach var x in q do + writeln(x); +end. \ No newline at end of file diff --git a/Yield/tests/yield1.exe b/Yield/tests/yield1.exe new file mode 100644 index 000000000..f7e9c0823 Binary files /dev/null and b/Yield/tests/yield1.exe differ diff --git a/Yield/tests/yield1.pas b/Yield/tests/yield1.pas new file mode 100644 index 000000000..18d0c9482 --- /dev/null +++ b/Yield/tests/yield1.pas @@ -0,0 +1,11 @@ +function Gen: sequence of integer; +begin + yield 1; + yield 5; +end; + +begin + var q := Gen(); + foreach var x in q do + Print(x); +end. \ No newline at end of file diff --git a/Yield/tests/yield10.exe b/Yield/tests/yield10.exe new file mode 100644 index 000000000..f4ecaeab4 Binary files /dev/null and b/Yield/tests/yield10.exe differ diff --git a/Yield/tests/yield10.pas b/Yield/tests/yield10.pas new file mode 100644 index 000000000..6efa83473 --- /dev/null +++ b/Yield/tests/yield10.pas @@ -0,0 +1,45 @@ +var aa: real := 555.0; + +function mcos: real; +begin + result := 99.6; +end; + +procedure msin; +begin +end; + +type R = class + testR: real := 77.3; + testI: integer; + + //property sin: real read testR; + +private + function sin(x: real): real; + begin + result := 83.9; + end; +end; + +type A = class(R) + testField: real := 23.3; + + function Gen(n: integer): sequence of real; + var j,k: real; + begin + //yield testField; + //yield testR; + //msin; + //yield mcos; + //yield cos(3.14); + yield sin(3.14); + //yield jgdFail; + end; +end; + +begin + var t := new A(); + foreach var x in t.Gen(5) do + Print(x); +end. \ No newline at end of file diff --git a/Yield/tests/yield11.exe b/Yield/tests/yield11.exe new file mode 100644 index 000000000..828620d0c Binary files /dev/null and b/Yield/tests/yield11.exe differ diff --git a/Yield/tests/yield11.pas b/Yield/tests/yield11.pas new file mode 100644 index 000000000..c294e6728 --- /dev/null +++ b/Yield/tests/yield11.pas @@ -0,0 +1,48 @@ +uses System.IO; + +uses UnitClass; + +var aa: real := 555.0; + + +type R = class + testR: real := 77.3; + testI: integer; + + property sin: real read testR; + + function sin2(x: real): real; + begin + result := 83.9; + end; +private + testRr: real := 23.3; +end; + +type A = class(UnitClassTest) + (*constructor Create; + begin + inherited Create('hz'); + end; + + constructor Create(path: string); + begin + inherited Create(path); + end;*) + + function Gen(n: integer): sequence of real; + var j,k: real; + begin + //var x := BaseStream; + //var x := 56.4; + //var y := x; + yield testField; + //yield Peek(); + end; +end; + +begin + var t := new A(); + foreach var x in t.Gen(5) do + Print(x); +end. \ No newline at end of file diff --git a/Yield/tests/yield12.exe b/Yield/tests/yield12.exe new file mode 100644 index 000000000..0e19fae70 Binary files /dev/null and b/Yield/tests/yield12.exe differ diff --git a/Yield/tests/yield12.pas b/Yield/tests/yield12.pas new file mode 100644 index 000000000..6c72890d3 --- /dev/null +++ b/Yield/tests/yield12.pas @@ -0,0 +1,41 @@ +var aa: real := 555.0; + +function mcos: real; +begin + result := 99.6; +end; + +procedure msin; +begin +end; + +type R = class + testR: real := 77.3; + testI: integer; + + //property sin: real read testR; + +//private + function sin2(x: real): real; + begin + result := 83.9; + end; +end; + +type A = class(R) + testField: real; + + function Gen(n: integer): sequence of real; + var j := n; + begin + yield testField; + yield sin(3.14); + yield j; + end; +end; + +begin + var t := new A(); + foreach var x in t.Gen(5) do + Print(x); +end. \ No newline at end of file diff --git a/Yield/tests/yield14.exe b/Yield/tests/yield14.exe new file mode 100644 index 000000000..ebd681a93 Binary files /dev/null and b/Yield/tests/yield14.exe differ diff --git a/Yield/tests/yield14.pas b/Yield/tests/yield14.pas new file mode 100644 index 000000000..c59e1c9c0 --- /dev/null +++ b/Yield/tests/yield14.pas @@ -0,0 +1,52 @@ +var aa: real := 555.0; + +function mcos: real; +begin + result := 99.6; +end; + +procedure msin; +begin +end; + +type R = class + testR: real := 77.3; + testI: integer; + + function sin2(x: real): real; + begin + result := 83.9; + end; +end; + +type A = class(R) + testField: real; + + function Gen(n: integer): sequence of real; + var j := n; + var jj : real := j; + begin + //begin + var x := 777; + //yield xx; + //end; + //begin + //var x := 89.3; + //begin + // var x := 9; + //end; + yield jj; + for var x := 1 to j do + begin + yield x; + end; + + //end; + end; +end; + +begin + var t := new A(); + foreach var x in t.Gen(5) do + Print(x); +end. \ No newline at end of file diff --git a/Yield/tests/yield15.exe b/Yield/tests/yield15.exe new file mode 100644 index 000000000..180d45a1a Binary files /dev/null and b/Yield/tests/yield15.exe differ diff --git a/Yield/tests/yield15.pas b/Yield/tests/yield15.pas new file mode 100644 index 000000000..9e1a245fa --- /dev/null +++ b/Yield/tests/yield15.pas @@ -0,0 +1,16 @@ +function Gen(n: integer): sequence of real; + var j := n; + var jj : real := j; + begin + var x := 777; + yield jj; + for var x := 1 to j do + begin + yield x; + end; + end; + +begin + foreach var x in Gen(5) do + Print(x); +end. \ No newline at end of file diff --git a/Yield/tests/yield17.exe b/Yield/tests/yield17.exe new file mode 100644 index 000000000..36daf8b4c Binary files /dev/null and b/Yield/tests/yield17.exe differ diff --git a/Yield/tests/yield17.pas b/Yield/tests/yield17.pas new file mode 100644 index 000000000..169e5c92f --- /dev/null +++ b/Yield/tests/yield17.pas @@ -0,0 +1,14 @@ +type A = class + function Gen: sequence of real; +end; + +function A.Gen: sequence of real; +begin + yield 1; +end; + +begin + var t := new A(); + foreach var x in t.Gen do + Print(x); +end. \ No newline at end of file diff --git a/Yield/tests/yield18.exe b/Yield/tests/yield18.exe new file mode 100644 index 000000000..9f124d671 Binary files /dev/null and b/Yield/tests/yield18.exe differ diff --git a/Yield/tests/yield18.pas b/Yield/tests/yield18.pas new file mode 100644 index 000000000..06bf60f08 --- /dev/null +++ b/Yield/tests/yield18.pas @@ -0,0 +1,49 @@ +var aa: real := 555.0; + +function mcos: real; +begin + result := 99.6; +end; + +procedure msin; +begin +end; + +type R = class + testR: real := 77.3; + testI: integer; + + function sin2(x: real): real; + begin + result := 83.9; + end; +end; + +type A = class(R) + testField: real; + + function Gen(n: integer): sequence of real; +private + function Lol: real; +end; + +function A.Lol: real; +begin +end; + +function A.Gen(n: integer): sequence of real; + var j := n; + var jj : real := j; + begin + yield jj; + for var x := 1 to j do + begin + yield x; + end; + end; + +begin + var t := new A(); + foreach var x in t.Gen(5) do + Print(x); +end. \ No newline at end of file diff --git a/Yield/tests/yield19.exe b/Yield/tests/yield19.exe new file mode 100644 index 000000000..11977a6e4 Binary files /dev/null and b/Yield/tests/yield19.exe differ diff --git a/Yield/tests/yield19.pas b/Yield/tests/yield19.pas new file mode 100644 index 000000000..93f6b1e77 --- /dev/null +++ b/Yield/tests/yield19.pas @@ -0,0 +1,24 @@ +type A = class + function Gen(n: integer): sequence of real; + var j,k: real; + var m := j; + begin + var i := 222; + begin + var x := i; + end; + begin + var x := j; + end; + for var nn := 1 to 10 do + begin + yield i; + end; + end; +end; + +begin + var t := new A(); + foreach var x in t.Gen(5) do + Print(x); +end. \ No newline at end of file diff --git a/Yield/tests/yield2.exe b/Yield/tests/yield2.exe new file mode 100644 index 000000000..99b1a55be Binary files /dev/null and b/Yield/tests/yield2.exe differ diff --git a/Yield/tests/yield2.pas b/Yield/tests/yield2.pas new file mode 100644 index 000000000..c03babbbc --- /dev/null +++ b/Yield/tests/yield2.pas @@ -0,0 +1,16 @@ +function Gen(n: integer): sequence of integer; +var j,k: real; +begin + var i := 1; + j := 5; + while i 0) then + begin + if (i mod 3 = 0) then + i *= 4; + yield i * 33; + + if (i mod 3 = 0) then + yield i * 2; + + yield i; + + if (i mod 3 = 0) then + yield i * 2; + end + else yield i * 10; + + if (i mod 12 <> 0) then + begin + i += 1 + end + else + begin + if (i mod 4 = 0) then + yield 888 + else + yield 777 + end; + + + if (i mod 2 = 0) then + begin + for var x := 1 to 10 do + yield x; + end; + i += 1; + if (i mod 5 = 0) then + yield i; +end; + + +begin + var q := Gen(); + q.Println; +end. \ No newline at end of file diff --git a/Yield/tests/yieldDemo.pas b/Yield/tests/yieldDemo.pas new file mode 100644 index 000000000..c5a379d4f --- /dev/null +++ b/Yield/tests/yieldDemo.pas @@ -0,0 +1,40 @@ +type BaseClass = class + testBaseField: real := 77.3; + + function testBaseFunction(x: real): real; + begin + result := 83.9; + end; +end; + +type A = class(BaseClass) + testField: real := 777.7; + + function Gen(testFormalParam: integer): sequence of real; + var testLocalVariable := testFormalParam; + begin + var testLocalVariable_2 : real := testLocalVariable + 33.3; + + yield testLocalVariable; + yield testLocalVariable_2; + + yield testFormalParam; + + yield testField; + yield testBaseField; + yield testBaseFunction(9); + + yield sin(3.14); + + for var x := 1 to testLocalVariable do + begin + yield x; + end; + end; +end; + +begin + var t := new A(); + foreach var x in t.Gen(5) do + Print(x); +end. \ No newline at end of file diff --git a/_RebuildReleaseAndRunTests.bat b/_RebuildReleaseAndRunTests.bat index 51d34224d..f234210cb 100644 --- a/_RebuildReleaseAndRunTests.bat +++ b/_RebuildReleaseAndRunTests.bat @@ -1,4 +1,4 @@ -%windir%\microsoft.net\framework\v4.0.30319\msbuild /t:rebuild /property:Configuration=Release PascalABCNET.sln +%windir%\microsoft.net\framework\v4.0.30319\msbuild /t:rebuild /property:Configuration=Release /p:Platform="Any CPU" PascalABCNET.sln @IF %ERRORLEVEL% NEQ 0 GOTO ERROR cd ReleaseGenerators diff --git a/bin/Lib/PABCRtl.dll b/bin/Lib/PABCRtl.dll index 2890ae344..4b0a92372 100644 Binary files a/bin/Lib/PABCRtl.dll and b/bin/Lib/PABCRtl.dll differ