From ec8e54ddafb21167603d3300bf786b3b8a93b109 Mon Sep 17 00:00:00 2001 From: miks1965 Date: Sun, 28 Jun 2015 10:53:10 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B5=D0=BA=D1=82=20=D1=81?= =?UTF-8?q?=20=D0=B2=D0=B8=D0=B7=D0=B8=D1=82=D0=BE=D1=80=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Configuration/GlobalAssemblyInfo.cs | 2 +- Configuration/Version.defs | 2 +- ReleaseGenerators/PascalABCNET_version.nsh | 2 +- _ParsePABC1/ParsePABC1.sln | 34 ++++ .../ParsePABC1/AllVarsInProcYieldsProba.cs | 81 ++++++++ _ParsePABC1/ParsePABC1/App.config | 6 + .../BaseVisitors/BaseChangeVisitor.cs | 72 +++++++ .../BaseVisitors/BaseEnterExitVisitor.cs | 27 +++ .../BaseVisitors/CollectNamespaces.cs | 59 ++++++ .../BaseVisitors/CollectUpperNodesVisitor.cs | 39 ++++ .../BaseVisitors/SmallHelperVisitors.cs | 50 +++++ _ParsePABC1/ParsePABC1/ChangeWhileVisitor.cs | 56 ++++++ _ParsePABC1/ParsePABC1/CountNodesVisitor.cs | 44 +++++ _ParsePABC1/ParsePABC1/DeleteLocalDefs.cs | 87 +++++++++ .../ParsePABC1/DeleteRedundantBeginEnds.cs | 36 ++++ .../ParsePABC1/Optimization/CalcConstExprs.cs | 120 ++++++++++++ _ParsePABC1/ParsePABC1/ParsePABC1.csproj | 103 ++++++++++ .../ParsePABC1/ProcessYieldsCapturedVars.cs | 104 ++++++++++ _ParsePABC1/ParsePABC1/Program.cs | 67 +++++++ _ParsePABC1/ParsePABC1/ProgramOld.cs | 62 ++++++ .../ParsePABC1/Properties/AssemblyInfo.cs | 36 ++++ .../ParsePABC1/SimplePrettyPrinterVisitor.cs | 183 ++++++++++++++++++ ...le_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs | 0 ...le_5937a670-0e60-4077-877b-f7221da3dda1.cs | 0 ...le_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs | 0 bin/Lib/PABCRtl.dll | Bin 479232 -> 479232 bytes 26 files changed, 1269 insertions(+), 3 deletions(-) create mode 100644 _ParsePABC1/ParsePABC1.sln create mode 100644 _ParsePABC1/ParsePABC1/AllVarsInProcYieldsProba.cs create mode 100644 _ParsePABC1/ParsePABC1/App.config create mode 100644 _ParsePABC1/ParsePABC1/BaseVisitors/BaseChangeVisitor.cs create mode 100644 _ParsePABC1/ParsePABC1/BaseVisitors/BaseEnterExitVisitor.cs create mode 100644 _ParsePABC1/ParsePABC1/BaseVisitors/CollectNamespaces.cs create mode 100644 _ParsePABC1/ParsePABC1/BaseVisitors/CollectUpperNodesVisitor.cs create mode 100644 _ParsePABC1/ParsePABC1/BaseVisitors/SmallHelperVisitors.cs create mode 100644 _ParsePABC1/ParsePABC1/ChangeWhileVisitor.cs create mode 100644 _ParsePABC1/ParsePABC1/CountNodesVisitor.cs create mode 100644 _ParsePABC1/ParsePABC1/DeleteLocalDefs.cs create mode 100644 _ParsePABC1/ParsePABC1/DeleteRedundantBeginEnds.cs create mode 100644 _ParsePABC1/ParsePABC1/Optimization/CalcConstExprs.cs create mode 100644 _ParsePABC1/ParsePABC1/ParsePABC1.csproj create mode 100644 _ParsePABC1/ParsePABC1/ProcessYieldsCapturedVars.cs create mode 100644 _ParsePABC1/ParsePABC1/Program.cs create mode 100644 _ParsePABC1/ParsePABC1/ProgramOld.cs create mode 100644 _ParsePABC1/ParsePABC1/Properties/AssemblyInfo.cs create mode 100644 _ParsePABC1/ParsePABC1/SimplePrettyPrinterVisitor.cs create mode 100644 _ParsePABC1/ParsePABC1/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs create mode 100644 _ParsePABC1/ParsePABC1/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs create mode 100644 _ParsePABC1/ParsePABC1/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs diff --git a/Configuration/GlobalAssemblyInfo.cs b/Configuration/GlobalAssemblyInfo.cs index 53c76f753..6f13585a9 100644 --- a/Configuration/GlobalAssemblyInfo.cs +++ b/Configuration/GlobalAssemblyInfo.cs @@ -15,7 +15,7 @@ internal static class RevisionClass public const string Major = "2"; public const string Minor = "2"; public const string Build = "0"; - public const string Revision = "966"; + public const string Revision = "967"; public const string MainVersion = Major + "." + Minor; public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision; diff --git a/Configuration/Version.defs b/Configuration/Version.defs index 254e7f2e2..4e420c509 100644 --- a/Configuration/Version.defs +++ b/Configuration/Version.defs @@ -1,4 +1,4 @@ %MINOR%=2 -%REVISION%=966 +%REVISION%=967 %MAJOR%=2 %COREVERSION%=0 diff --git a/ReleaseGenerators/PascalABCNET_version.nsh b/ReleaseGenerators/PascalABCNET_version.nsh index f8c538b6e..c13c7cd4f 100644 --- a/ReleaseGenerators/PascalABCNET_version.nsh +++ b/ReleaseGenerators/PascalABCNET_version.nsh @@ -1 +1 @@ -!define VERSION '2.2.0.966' \ No newline at end of file +!define VERSION '2.2.0.967' \ No newline at end of file diff --git a/_ParsePABC1/ParsePABC1.sln b/_ParsePABC1/ParsePABC1.sln new file mode 100644 index 000000000..16eaf8ac5 --- /dev/null +++ b/_ParsePABC1/ParsePABC1.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParsePABC1", "ParsePABC1\ParsePABC1.csproj", "{BAA767F1-6544-4A44-BA17-5FBFCF6F2D99}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntaxTree", "..\..\PascalABC.NET\!PABC_Git\SyntaxTree\SyntaxTree.csproj", "{C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCompletion", "..\..\PascalABC.NET\!PABC_Git\CodeCompletion\CodeCompletion.csproj", "{1AB15F6E-C22E-499A-A7ED-54BA7DE5CFA6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BAA767F1-6544-4A44-BA17-5FBFCF6F2D99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BAA767F1-6544-4A44-BA17-5FBFCF6F2D99}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BAA767F1-6544-4A44-BA17-5FBFCF6F2D99}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BAA767F1-6544-4A44-BA17-5FBFCF6F2D99}.Release|Any CPU.Build.0 = Release|Any CPU + {C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A}.Release|Any CPU.Build.0 = Release|Any CPU + {1AB15F6E-C22E-499A-A7ED-54BA7DE5CFA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1AB15F6E-C22E-499A-A7ED-54BA7DE5CFA6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1AB15F6E-C22E-499A-A7ED-54BA7DE5CFA6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1AB15F6E-C22E-499A-A7ED-54BA7DE5CFA6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/_ParsePABC1/ParsePABC1/AllVarsInProcYieldsProba.cs b/_ParsePABC1/ParsePABC1/AllVarsInProcYieldsProba.cs new file mode 100644 index 000000000..8090acc84 --- /dev/null +++ b/_ParsePABC1/ParsePABC1/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 ParsePABC1 +{ + 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/_ParsePABC1/ParsePABC1/App.config b/_ParsePABC1/ParsePABC1/App.config new file mode 100644 index 000000000..8e1564635 --- /dev/null +++ b/_ParsePABC1/ParsePABC1/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/_ParsePABC1/ParsePABC1/BaseVisitors/BaseChangeVisitor.cs b/_ParsePABC1/ParsePABC1/BaseVisitors/BaseChangeVisitor.cs new file mode 100644 index 000000000..dbd479653 --- /dev/null +++ b/_ParsePABC1/ParsePABC1/BaseVisitors/BaseChangeVisitor.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 ParsePABC1 +{ + class BaseChangeVisitor : CollectUpperNodesVisitor + { + public void Replace(syntax_tree_node from, syntax_tree_node to) + { + var upper = UpperNode(); + if (upper == null) + throw new Exception("У корневого элемента нельзя получить UpperNode"); + + int ind = -1; + for (var i = 0; i < upper.subnodes_count; i++) + if (from == upper[i]) + { + ind = i; + break; + } + upper[ind] = to; + } + + public statement_list UpperStatementList() + { + var stl = UpperNode() as statement_list; + if (stl == null) + throw new Exception("оператор вложен не в statement_list"); + return stl; + } + + public bool DeleteInStatementList(statement st) + { + var stl = UpperStatementList(); + bool b = stl.subnodes.Remove(st); + return b; + } + public bool DeleteInIdentList(ident id) + { + var idl = UpperNode() as ident_list; + if (idl==null) + throw new Exception("идентификатор не вложен в id_list"); + var b = idl.idents.Remove(id); + return b; + } + + public void ReplaceStatement(statement from, statement to) + { + var stl = UpperStatementList(); + var ind = stl.subnodes.IndexOf(from); + if (ind == -1) + throw new Exception("оператор from не найден - некорректный вызов ReplaceStatement"); + stl.subnodes[ind] = to; + } + public void ReplaceStatement(statement from, List to) + { + var stl = UpperStatementList(); + var ind = stl.subnodes.IndexOf(from); + if (ind == -1) + throw new Exception("оператор from не найден - некорректный вызов ReplaceStatement"); + stl.subnodes.RemoveAt(ind); + stl.subnodes.InsertRange(ind, to); + } + } + +} diff --git a/_ParsePABC1/ParsePABC1/BaseVisitors/BaseEnterExitVisitor.cs b/_ParsePABC1/ParsePABC1/BaseVisitors/BaseEnterExitVisitor.cs new file mode 100644 index 000000000..f98d2e4e2 --- /dev/null +++ b/_ParsePABC1/ParsePABC1/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 ParsePABC1 +{ + class BaseEnterExitVisitor: WalkingVisitor + { + 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/_ParsePABC1/ParsePABC1/BaseVisitors/CollectNamespaces.cs b/_ParsePABC1/ParsePABC1/BaseVisitors/CollectNamespaces.cs new file mode 100644 index 000000000..dc6e1510a --- /dev/null +++ b/_ParsePABC1/ParsePABC1/BaseVisitors/CollectNamespaces.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace ParsePABC1 +{ + 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; + var f = tds.types_decl.Find(td => td.type_def == cl); + if (PrintInfo) + Console.WriteLine(" " + f.type_name); + base.visit(cl); + } + } + +} diff --git a/_ParsePABC1/ParsePABC1/BaseVisitors/CollectUpperNodesVisitor.cs b/_ParsePABC1/ParsePABC1/BaseVisitors/CollectUpperNodesVisitor.cs new file mode 100644 index 000000000..573285d72 --- /dev/null +++ b/_ParsePABC1/ParsePABC1/BaseVisitors/CollectUpperNodesVisitor.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace ParsePABC1 +{ + 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) + { + 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/_ParsePABC1/ParsePABC1/BaseVisitors/SmallHelperVisitors.cs b/_ParsePABC1/ParsePABC1/BaseVisitors/SmallHelperVisitors.cs new file mode 100644 index 000000000..698c9dbf0 --- /dev/null +++ b/_ParsePABC1/ParsePABC1/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 ParsePABC1 +{ + public class FindLocalDefsVisitor : WalkingVisitor // Запускать только для подпрограмм + { + 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 : WalkingVisitor // в выражении 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/_ParsePABC1/ParsePABC1/ChangeWhileVisitor.cs b/_ParsePABC1/ParsePABC1/ChangeWhileVisitor.cs new file mode 100644 index 000000000..f7a0922ea --- /dev/null +++ b/_ParsePABC1/ParsePABC1/ChangeWhileVisitor.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; + +namespace ParsePABC1 +{ + class ChangeWhileVisitor : BaseChangeVisitor + { + int lbnum = 0; + + public string newLabelName() + { + lbnum++; + return "lb#" + lbnum.ToString(); + } + public override void Exit(syntax_tree_node st) + { + if (st.GetType() == typeof(while_node)) + { + var wn = st as while_node; + + var stl = new statement_list(); + + 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()); + + stl.Add(lb3).Add(gt2).Add(lb1).Add(gt3).Add(lb2); + + //var op = new if_node(wn.expr, wn.statements, null); + Replace(wn, stl); + // в declarations ближайшего блока добавить описание labels + block bl = listNodes.FindLast(x => x is block) as block; + + var il = new ident_list(); + il.Add(gt1.label).Add(gt2.label).Add(gt3.label); + var ld = new label_definitions(il); + bl.defs.Add(ld); + } + base.Exit(st); + } + + } + +} diff --git a/_ParsePABC1/ParsePABC1/CountNodesVisitor.cs b/_ParsePABC1/ParsePABC1/CountNodesVisitor.cs new file mode 100644 index 000000000..64b633777 --- /dev/null +++ b/_ParsePABC1/ParsePABC1/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 ParsePABC1 +{ + 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/_ParsePABC1/ParsePABC1/DeleteLocalDefs.cs b/_ParsePABC1/ParsePABC1/DeleteLocalDefs.cs new file mode 100644 index 000000000..3f3ebced8 --- /dev/null +++ b/_ParsePABC1/ParsePABC1/DeleteLocalDefs.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace ParsePABC1 +{ + 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 = UpperNode() as variable_definitions; + uvdsl.var_definitions.Remove(vd); // Проблема - мы удаляем первую var_def_statement и вторая становится первой. А в цикле обхода - индексы что естественно + if (uvdsl.var_definitions.Count == 0) + { + var d = UpperNode(2) as declarations; + d.defs.Remove(uvdsl); + } + } + + } + } + public override void visit(variable_definitions vd) + { + if (vd.var_definitions != null) + for (int i = vd.var_definitions.Count - 1; i >= 0; --i) // в обратном порядке - тогда удаление текущего элемента работает корректно + ProcessNode(vd.var_definitions[i]); + } + + public override void visit(declarations d) + { + if (d.defs != null) + for (int i = d.defs.Count - 1; i >= 0; --i) // в обратном порядке - тогда удаление текущего элемента работает корректно + ProcessNode(d.defs[i]); + } + + public void AfterProcTraverse() + { + idsToDelete.ExceptWith(deletedIdsToDeleteInLocalScope); // исключаем из множества удаляемых идентификаторов те, которые мы нашли и удалили в секции var_statement. Это надо делать не для каждого описания, а в конце подпрограммы после удаления из всех секций var_statement + } + } +} diff --git a/_ParsePABC1/ParsePABC1/DeleteRedundantBeginEnds.cs b/_ParsePABC1/ParsePABC1/DeleteRedundantBeginEnds.cs new file mode 100644 index 000000000..fd1ef9f38 --- /dev/null +++ b/_ParsePABC1/ParsePABC1/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 ParsePABC1 +{ + 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/_ParsePABC1/ParsePABC1/Optimization/CalcConstExprs.cs b/_ParsePABC1/ParsePABC1/Optimization/CalcConstExprs.cs new file mode 100644 index 000000000..69ba9e9e5 --- /dev/null +++ b/_ParsePABC1/ParsePABC1/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 ParsePABC1 +{ + 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/_ParsePABC1/ParsePABC1/ParsePABC1.csproj b/_ParsePABC1/ParsePABC1/ParsePABC1.csproj new file mode 100644 index 000000000..9c32cdf65 --- /dev/null +++ b/_ParsePABC1/ParsePABC1/ParsePABC1.csproj @@ -0,0 +1,103 @@ + + + + + Debug + AnyCPU + {BAA767F1-6544-4A44-BA17-5FBFCF6F2D99} + Exe + Properties + ParsePABC1 + ParsePABC1 + v4.5 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\..\PascalABC.NET\!PABC_SVN1\bin\Compiler.dll + + + ..\..\..\PascalABC.NET\!PABC_SVN1\bin\CompilerTools.dll + + + ..\..\..\PascalABC.NET\!PABC_SVN1\bin\Errors.dll + + + ..\..\..\PascalABC.NET\!PABC_SVN1\bin\Localization.dll + + + ..\..\..\PascalABC.NET\!PABC_SVN1\bin\ParserTools.dll + + + ..\..\..\PascalABC.NET\!PABC_Git\bin\PascalABCParser.dll + + + + + + + + + + + + + + Code + + + + + + + + + + + Code + + + + + + + + + + + {1ab15f6e-c22e-499a-a7ed-54ba7de5cfa6} + CodeCompletion + + + {c2cac65a-b2ae-4ccc-b067-e6b8e75df73a} + SyntaxTree + + + + + \ No newline at end of file diff --git a/_ParsePABC1/ParsePABC1/ProcessYieldsCapturedVars.cs b/_ParsePABC1/ParsePABC1/ProcessYieldsCapturedVars.cs new file mode 100644 index 000000000..33a7cdf67 --- /dev/null +++ b/_ParsePABC1/ParsePABC1/ProcessYieldsCapturedVars.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace ParsePABC1 +{ + class ProcessYieldCapturedVarsVisitor : BaseChangeVisitor + { + int clnum = 0; + + public string newClassName() + { + clnum++; + return "clyield#" + clnum.ToString(); + } + + + public FindMainIdentsVisitor mids = new FindMainIdentsVisitor(); // захваченные переменные процедуры по всем её yield + + public int countNodesVisited; + + public bool hasYields = false; + + public ProcessYieldCapturedVarsVisitor() + { + //PrintInfo = false; + } + + /*public override void visit(procedure_definition pd) + { + + } */ + + 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; + } + if (st is procedure_definition) + { + mids.vars.Clear(); // очищать при входе в процедуру + } + } + public override void Exit(syntax_tree_node st) + { + if (st is procedure_definition) // т.е. мы разобрали процедуру и уже выходим. Это значит, что пока yield будет обрабатываться только в процедурах. Так это и надо. + { + if (!hasYields) + return; + + var dld = new DeleteLocalDefs(mids.vars); // mids.vars - все захваченные переменные + st.visit(dld); // Удалить в локальных и блочных описаниях этой процедуры все захваченные переменные + // В результате работы в mids.vars что-то осталось. Это не локальные переменные и с ними непонятно что делать + dld.AfterProcTraverse(); + + var cm = new class_members(access_modifer.public_modifer); + foreach (var m in dld.BlockDeletedIds) + cm.Add(m); + cm.Add(st as procedure_definition); + var cc = new type_declaration(newClassName(), SyntaxTreeBuilder.BuildClassDefinition(true, cm), SyntaxTreeBuilder.BuildGenSC); + var cct = new type_declarations(cc, null); + + Replace(st, cct); + + /*Console.WriteLine("Удаленные переменные: " + (st as procedure_definition).proc_header.name.meth_name.name); + foreach (var dd in dld.deletedIdsToDeleteInLocalScope) + Console.Write(dd + " "); + Console.WriteLine(); + Console.WriteLine("Оставшиеся переменные: " + (st as procedure_definition).proc_header.name.meth_name.name); + foreach (var dd in mids.vars) + Console.Write(dd + " "); + Console.WriteLine();*/ + } + base.Exit(st); + } + public override void visit(yield_node yn) + { + hasYields = true; + yn.visit(mids); + // mids.vars - надо установить, какие из них - локальные, какие - из этого класса, какие - являются параметрами функции, а какие - глобальные (все остальные) + // те, которые являются параметрами, надо скопировать в локальные переменные и переименовать использование везде по ходу данной функции + // самое сложное - переменные-поля этого класса - они требуют в создаваемом классе, реализующем итератор, хранить Self текущего класса и добавлять это Self везде по ходу алгоритма + // вначале будем считать, что переменные-поля этого класса и переменные-параметры не захватываются yield + //base.visit(yn); + } + public override void visit(declarations d) // в обратном порядке + { + if (d.defs != null) + for (int i = d.defs.Count - 1; i >= 0; --i) // в обратном порядке - тогда удаление текущего элемента работает корректно + ProcessNode(d.defs[i]); + } + + } +} diff --git a/_ParsePABC1/ParsePABC1/Program.cs b/_ParsePABC1/ParsePABC1/Program.cs new file mode 100644 index 000000000..6840fab38 --- /dev/null +++ b/_ParsePABC1/ParsePABC1/Program.cs @@ -0,0 +1,67 @@ +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 ParsePABC1 +{ + class Program + { + static syntax_tree_node ParseFile(string fname) + { + Compiler c = new Compiler(); + + var err = new List(); + + var txt = System.IO.File.ReadAllText(fname); + + var cu = c.ParsersController.Compile(fname, txt, err, PascalABCCompiler.Parsers.ParseMode.ForFormatter); + + if (cu == null) + { + Console.WriteLine("Не распарсилось"); + } + return cu; + } + + static void Main(string[] args) + { + var cu = ParseFile(@"d:\w5\ex1.pas"); + if (cu == null) + return; + + /*cu.visit(new ChangeWhileVisitor()); + cu.visit(new DeleteRedundantBeginEnds());*/ + + /*cu.visit(new CollectUpperNamespacesVisitor()); + + var allv = new AllVarsInProcYields(); + cu.visit(allv); + allv.PrintDict();*/ + + /*var cnt = new CountNodesVisitor(); + cu.visit(cnt); + cnt.PrintSortedByValue();*/ + + /*var ld = new HashSet(); + ld.Add("a"); + ld.Add("p1"); + ld.Add("s"); + var dld = new DeleteLocalDefs(ld); + cu.visit(dld);*/ + + /*var p = new ProcessYieldCapturedVarsVisitor(); + cu.visit(p);*/ + + var p = new CalcConstExprs(); + cu.visit(p); + + cu.visit(new SimplePrettyPrinterVisitor()); + } + } +} diff --git a/_ParsePABC1/ParsePABC1/ProgramOld.cs b/_ParsePABC1/ParsePABC1/ProgramOld.cs new file mode 100644 index 000000000..651d8d97a --- /dev/null +++ b/_ParsePABC1/ParsePABC1/ProgramOld.cs @@ -0,0 +1,62 @@ +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 ParsePABC1 +{ + class Program + { + static syntax_tree_node ParseFile(string fname) + { + Compiler c = new Compiler(); + + var err = new List(); + + var txt = System.IO.File.ReadAllText(fname); + + var cu = c.ParsersController.Compile(fname, txt, err, PascalABCCompiler.Parsers.ParseMode.ForFormatter); + + if (cu == null) + { + Console.WriteLine("Не распарсилось"); + } + return cu; + } + + static void Main(string[] args) + { + var cu = ParseFile(@"d:\w5\e.pas"); + if (cu == null) + return; + + //CodeFormatters.CodeFormatter cf = new CodeFormatters.CodeFormatter(0); + //txt = cf.FormatTree(txt, cu as compilation_unit, 0, 0); + + cu.visit(new ChangeWhileVisitor()); + cu.visit(new DeleteRedundantBeginEnds()); + + /*cu.visit(new CollectUpperNamespacesVisitor()); + + var allv = new AllVarsInProcYields(); + cu.visit(allv); + allv.PrintDict();*/ + + /*var cnt = new CountNodesVisitor(); + cu.visit(cnt); + cnt.PrintSortedByValue();*/ + + var ld = new List(); + ld.Add("p1"); + var dld = new DeleteLocalDefs(ld); + cu.visit(dld); + + cu.visit(new SimplePrettyPrinterVisitor()); + } + } +} diff --git a/_ParsePABC1/ParsePABC1/Properties/AssemblyInfo.cs b/_ParsePABC1/ParsePABC1/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..624a2bb1d --- /dev/null +++ b/_ParsePABC1/ParsePABC1/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Управление общими сведениями о сборке осуществляется с помощью +// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, +// связанные со сборкой. +[assembly: AssemblyTitle("ParsePABC1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ParsePABC1")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми +// для COM-компонентов. Если требуется обратиться к типу в этой сборке через +// COM, задайте атрибуту ComVisible значение TRUE для этого типа. +[assembly: ComVisible(false)] + +// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM +[assembly: Guid("fa30eefc-3fcc-45a3-8b6f-465b1a5c17ba")] + +// Сведения о версии сборки состоят из следующих четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер сборки +// Редакция +// +// Можно задать все значения или принять номера сборки и редакции по умолчанию +// используя "*", как показано ниже: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/_ParsePABC1/ParsePABC1/SimplePrettyPrinterVisitor.cs b/_ParsePABC1/ParsePABC1/SimplePrettyPrinterVisitor.cs new file mode 100644 index 000000000..be11bd4ed --- /dev/null +++ b/_ParsePABC1/ParsePABC1/SimplePrettyPrinterVisitor.cs @@ -0,0 +1,183 @@ +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 ParsePABC1 +{ + class SimplePrettyPrinterVisitor: WalkingVisitor + { + int off = 0; + + bool printNodeType = false; + + 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 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; + PrintlnNoOffset("class"); + 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) + { + } + 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 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) + { + off -= 2; + } + else if (st is class_definition) + { + off -= 2; + Println("end;"); + } + } + + } +} diff --git a/_ParsePABC1/ParsePABC1/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs b/_ParsePABC1/ParsePABC1/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs new file mode 100644 index 000000000..e69de29bb diff --git a/_ParsePABC1/ParsePABC1/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs b/_ParsePABC1/ParsePABC1/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs new file mode 100644 index 000000000..e69de29bb diff --git a/_ParsePABC1/ParsePABC1/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs b/_ParsePABC1/ParsePABC1/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs new file mode 100644 index 000000000..e69de29bb diff --git a/bin/Lib/PABCRtl.dll b/bin/Lib/PABCRtl.dll index d246a5c60364e1cecec139271296b15d0aaebe20..202c63b9080ac05f53f5176e25067c257c707848 100644 GIT binary patch delta 8620 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 F^*=VXyv_gs delta 8599 zcmZvhe{5FO8OPsC3s)+ILR(r&X(_)eMcSgG2r2^p0)HSVW*dnW-c1BsQ(#k>dm(Co z_ygVM4#~Di6E_n#iOFI}mSv!s$>z+mC3A@+o620~oN+N(%yi7{`Fzhk_rB+4f83kz zdA`s2^*zsd&bjZq|Jbbk$7VfssO~S%KJ@fsH;$Y5=7H0Xo=zS;J?`bxb-f2G4_ic-5bu{rX4455BhOj>=bm_@gy154`d8 z$bwJnJ{sHdhv5(Je&f!)pLEUHdiQ(ZX&628Sb5*D+xM&YK574S)%&Oa_=SC2pZxb{ zXPPIi_{FLJes`>`?&$ANPPpZspEkeU*YW*tAN}Q%Q_4pV{poniJ!g|U4nBOS&YpUE z#-Dij(1eGUH}!mP#;-q{`S*1vUwpUUowxg2Cz?)8ID127SE*F0vnK&8wWpN4T1r&P z%@bv=->_r%o@81^rg%~ZGD&#VXViIt0+?-cax7yS19Krv$!cx1cT+99*t7MxghunK z(^PZ9rU!QKDc_sZE%-8=E;rPePS><%2ipPzr6j$!JX{{#u`RE&DDdhp@$-8&8%$py zv!QB+VWdj}39zQ4>0?`^v52+#mr4f?CZ&pbC4J^RVh++4u-qOmd0}?PC#7v)qI^Ci zpb?OFgJn{n0LFQhVWtM=5*Spr7eg;d*VC9b_ZDUIm@cj~%8EvSrZ>)jmJ!Qj3IH@MC3Wk|59Hjm!1-7kfBVp`y=5f_ zD$ES*4F;^LUQ8__JFfI>z6b^D?rTb08z|4A{$6*a$rPu|9#%6_EzSh+1gm&8o=jT1 zW80n`Bf~?Z58OGJAU#f31*dF$nsyl9>OihBV2$O{uc2zpdQn2nb-3eny*<@6v3b(% zoSJs^+;3&A58!5deA+0??uDu8%nIcxkboJ0e0{Je)B!9;)%sv+!2)Qvr<7E!55`&8 z05{oVP%mZ?k#6m@v}s9XVm0EO0j*2|xKJ6p0oae@{cdcUWf#hq`tmE&vU#ml*A^ z>=@oz-kzV8FxoD`r5G0$ZI=M7MW4knG}9Vjg*^uKLhc(PR_6!X&s<2Q5!tRv)j0{e z17E;AcVJrDv4G=IWs-SKPQp#QXPMuzROKmyD!Uxk8nAGD+$ z?rY5^rFM&Q`!~#4QUaKJDVbbIdDF=DvaTMmI^Tj@(E%1^m;kJEFDC|ND!|qDSmS!R zr&`nc$q{{}o7!SWWA5H5$7%_2@1hC7A|JfK3uJSjw_5O09`xm|>FKP+l&@0RUfBq8 z*&tU3a<%)N^*_OvU1hpuumi?P8h}3+2)@Y7v1dDWKF3k}o+8+>oz)j^mMIT%)< z2*?JP;2p-cG*ktcT_k&g3TA8dgAwbGzkepB58cz#)7F+Ps)4MJ7?RqLxK-_G_cqGf zivZ<7WgXhZqMQlvXIg&VVPgBq$p=wYK85WG?Cox9TiSe0Ue?)LwWT9xf0wO}M`> z0fSQ7?Qcu#8#wIL{R;PFn+4^{P+sp=x2J8B5tTX{WOoNr zjA50G0dX?MGSQwSfLuikQXCMH@vXQr=!j+VX3u4eNPn1CXAEfNWagWiCmWL#3u7W*id5pP znP*I%tL8V|@vd~xjm%EZbMJShAJy#{8Fg=Ur(4{~o^(>rGuF1m2KWIYc42lO_E=`1 zJc(fd;>>_WnIV8&Yz)c_fZEIukr$hTHJ*zdk$GmoYRcOnd}g4m%; z0O+CvEJ_UlgJ{!b>Uampu1uszm+R^#cut-4w zfoRj-JfKqqiy{($a-|!M8%&Pbz%XgM1C-~gwtGa*HU}Ez#gq!t4Rxojy_C^R#B2k_ zQX?L8560)**!;A)f$|(*?&(jPZ!5}XoNJFCKT8UwCtFk+Iq*>5@TC#84X zk$HBRB@=snpEn@cpLaJeNT)YbmYx7zhw9wB^U@U+TE;fj9szbKBU+Xm%P8A)p2|)e zIWS!6<)mg(rCLN1OmPH4TS)i&mc0yN!=NJkJSqXQj+v1A>-=n@#u=YJs@2r`HEiqX{3FTeb4&^8K4-}H9j)? zt*o&0Srt|q19Tj#3331yg(U#BZ9Z96#iAGnG6 z2B6DXo?)<%JZukmMOa9GZNs923$Vl<^Ws&}z#}%>u;Xw+q=-EC1_DhS%TIM{HN#_J z@W}dB>$X03s+!^zx7ynWwwTmpSy(7VEkK#uj0W>Dd(xdANN2h``qRd%E;80f;%f%9 z5CDH>6)WJA1dLW7xFmJ%2mR@aB}jrzmtcU;FX5(#g^PiFmbs5DRnE=J+4RQ2hju*a z-X63ce5p*>C9k>92h;X;%H%=cm;r-~+Z`Xs_d7n?l7OY|l>yt$McHgV2#^d9vWCE* PTqpSQiPx8