diff --git a/Configuration/GlobalAssemblyInfo.cs b/Configuration/GlobalAssemblyInfo.cs index 58103cb67..fb5185c95 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 = "999"; + public const string Revision = "1001"; 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 2d25cf75d..2f20fd25c 100644 --- a/Configuration/Version.defs +++ b/Configuration/Version.defs @@ -1,4 +1,4 @@ %MINOR%=2 -%REVISION%=999 +%REVISION%=1001 %MAJOR%=2 %COREVERSION%=0 diff --git a/ReleaseGenerators/PascalABCNET_version.nsh b/ReleaseGenerators/PascalABCNET_version.nsh index 84b075d41..f1c06c80d 100644 --- a/ReleaseGenerators/PascalABCNET_version.nsh +++ b/ReleaseGenerators/PascalABCNET_version.nsh @@ -1 +1 @@ -!define VERSION '2.2.0.999' \ No newline at end of file +!define VERSION '2.2.0.1001' \ No newline at end of file diff --git a/SyntaxTree/tree/NodesBuilder.cs b/SyntaxTree/tree/NodesBuilder.cs index d5aaaf591..22c53aa6f 100644 --- a/SyntaxTree/tree/NodesBuilder.cs +++ b/SyntaxTree/tree/NodesBuilder.cs @@ -90,7 +90,7 @@ namespace PascalABCCompiler.SyntaxTree return cm; } - public static class_definition BuildClassDefinition(bool is_class, params class_members[] cms) + public static class_definition BuildClassOrRecordDefinition(bool is_class, params class_members[] cms) { var cb = new class_body(); foreach (var cm in cms) @@ -101,6 +101,11 @@ namespace PascalABCCompiler.SyntaxTree return cd; } + public static class_definition BuildClassDefinition(params class_members[] cms) + { + return BuildClassOrRecordDefinition(true,cms); + } + // names и types передаю во внешний мир на предмет анализа того, что они не указатели. Снаружи они инициализируются пустыми списками public static void AddMembersForAutoClass(class_definition cd, ref List names, ref List types) // SSM 24.03.14 { @@ -169,7 +174,7 @@ namespace PascalABCCompiler.SyntaxTree var cm2 = BuildSimpleConstructorSection(names, formnames, types); var cm3 = BuildOneMemberSection(pd); - return new type_declaration(class_name, BuildClassDefinition(true, cm1, cm2, cm3), BuildGenSC); + return new type_declaration(class_name, BuildClassOrRecordDefinition(true, cm1, cm2, cm3), BuildGenSC); } public static type_declaration BuildAutoClass(string class_name, List names, List types, bool is_class) @@ -180,7 +185,7 @@ namespace PascalABCCompiler.SyntaxTree var cm2 = BuildSimpleConstructorSection(fnames,names,types); var cm3 = BuildSimpleReadPropertiesSection(names, fnames, types); - return new type_declaration(class_name, BuildClassDefinition(is_class, cm1, cm2, cm3), BuildGenSC); + return new type_declaration(class_name, BuildClassOrRecordDefinition(is_class, cm1, cm2, cm3), BuildGenSC); } public static type_declaration BuildClassWithFieldsOnly(string class_name, List names, List types, bool is_class) @@ -189,7 +194,7 @@ namespace PascalABCCompiler.SyntaxTree var cm1 = BuildClassFieldsSection(fnames, types); - return new type_declaration(class_name, BuildClassDefinition(is_class, cm1), BuildGenSC); + return new type_declaration(class_name, BuildClassOrRecordDefinition(is_class, cm1), BuildGenSC); } public static procedure_definition BuildShortFuncDefinition(formal_parameters fp, procedure_attributes_list att, method_name name, type_definition result, expression ex, SourceContext headsc) diff --git a/TestSuite/CompilationSamples/PABCSystem.pas b/TestSuite/CompilationSamples/PABCSystem.pas index 40091a97a..e57763bfb 100644 --- a/TestSuite/CompilationSamples/PABCSystem.pas +++ b/TestSuite/CompilationSamples/PABCSystem.pas @@ -2721,6 +2721,26 @@ end; //------------------------------------------------------------------------------ // StructuredObjectToString //------------------------------------------------------------------------------ + +// ToString nil ToString Object +function RedefinedToString(o: object): System.Reflection.MethodInfo; +begin + var t := o.GetType; + var meth: System.Reflection.MethodInfo := nil; + while t<>typeof(Object) do + begin + meth := t.GetMethod('ToString',System.Reflection.BindingFlags.Public or + System.Reflection.BindingFlags.Instance or + System.Reflection.BindingFlags.DeclaredOnly,nil,new System.Type[0],nil); + if meth<>nil then + break; + t := t.BaseType; + end; + if t=typeof(Object) then + Result := nil + else Result := meth; +end; + function ArrNToString(a: System.Array; indexes: array of integer; i: integer): string; forward; function StructuredObjectToString(o: Object; n: integer := 0): string; @@ -2775,7 +2795,7 @@ begin end else begin - var q := o.GetType.GetMethod('ToString',System.Reflection.BindingFlags.Public or System.Reflection.BindingFlags.Instance,nil,new System.Type[0],nil); + var q := RedefinedToString(o); var gg := o.GetType.FullName.StartsWith('System.Tuple'); var gg1 := o.GetType.Name.StartsWith('KeyValuePair'); if (q<>nil) and q.IsVirtual and not gg and not gg1 then @@ -2997,7 +3017,7 @@ end;} // Extension methods for IEnumerable //------------------------------------------------------------------------------ /// , delim -function System.Collections.Generic.IEnumerable.Print(delim: string := ' '): sequence of T; +function System.Collections.Generic.IEnumerable.Print(delim: string): sequence of T; begin var g := Self.GetEnumerator(); if g.MoveNext() then @@ -3007,16 +3027,28 @@ begin Result := Self; end; +/// , +function System.Collections.Generic.IEnumerable.Print(): sequence of T; +begin + Result := Self.Print(' '); +end; + /// , delim , -function System.Collections.Generic.IEnumerable.Println(delim: string := ' '): sequence of T; +function System.Collections.Generic.IEnumerable.Println(delim: string): sequence of T; begin Self.Print(delim); Writeln; Result := Self; end; +/// , , +function System.Collections.Generic.IEnumerable.Println(): sequence of T; +begin + Result := Self.Println(' '); +end; + /// , , delim -function System.Collections.Generic.IEnumerable.JoinIntoString(delim: string := ' '): string; +function System.Collections.Generic.IEnumerable.JoinIntoString(delim: string): string; begin var g := Self.GetEnumerator(); var sb := new System.Text.StringBuilder(''); @@ -3027,6 +3059,12 @@ begin Result := sb.ToString; end; +/// , , +function System.Collections.Generic.IEnumerable.JoinIntoString(): string; +begin + Result := Self.JoinIntoString(' '); +end; + /// procedure System.Collections.Generic.IEnumerable.&ForEach(action: Action); begin diff --git a/TreeConverter/LambdaExpressions/Closure/CapturedVariablesSubstitutionClassGenerator.cs b/TreeConverter/LambdaExpressions/Closure/CapturedVariablesSubstitutionClassGenerator.cs index 814421da5..0b7b0887c 100644 --- a/TreeConverter/LambdaExpressions/Closure/CapturedVariablesSubstitutionClassGenerator.cs +++ b/TreeConverter/LambdaExpressions/Closure/CapturedVariablesSubstitutionClassGenerator.cs @@ -286,7 +286,7 @@ namespace TreeConverter.LambdaExpressions.Closure var nextNodeWhereVarsAreCaptured = upperScopesStack.Pop(); if (!_capturedVarsClassDefs.ContainsKey(nextNodeWhereVarsAreCaptured.ScopeIndex)) { - var classDef = SyntaxTreeBuilder.BuildClassDefinition(true); + var classDef = SyntaxTreeBuilder.BuildClassDefinition(); var typeDeclaration = new type_declaration(GeneratedClassName, classDef); _capturedVarsClassDefs.Add(nextNodeWhereVarsAreCaptured.ScopeIndex, new ScopeClassDefinition( @@ -462,7 +462,7 @@ namespace TreeConverter.LambdaExpressions.Closure { if (!_capturedVarsClassDefs.ContainsKey(scope.ScopeIndex)) { - var classDef = SyntaxTreeBuilder.BuildClassDefinition(true); + var classDef = SyntaxTreeBuilder.BuildClassDefinition(); var typeDeclaration = new type_declaration(GeneratedClassName, classDef); _capturedVarsClassDefs.Add(scope.ScopeIndex, new ScopeClassDefinition( @@ -641,7 +641,7 @@ namespace TreeConverter.LambdaExpressions.Closure { if (!_capturedVarsClassDefs.ContainsKey(currentNode.ScopeIndex)) { - var classDef = SyntaxTreeBuilder.BuildClassDefinition(true); + var classDef = SyntaxTreeBuilder.BuildClassDefinition(); var typeDeclaration = new type_declaration(((CapturedVariablesTreeNodeClassScope)currentNode).ClassName, classDef); _capturedVarsClassDefs.Add(currentNode.ScopeIndex, new ScopeClassDefinition(currentNode.CorrespondingSyntaxTreeNode, @@ -654,7 +654,7 @@ namespace TreeConverter.LambdaExpressions.Closure { if (!_capturedVarsClassDefs.ContainsKey(currentNode.ScopeIndex)) { - var classDef = SyntaxTreeBuilder.BuildClassDefinition(true); + var classDef = SyntaxTreeBuilder.BuildClassDefinition(); var typeDeclaration = new type_declaration(GeneratedClassName, classDef); _capturedVarsClassDefs.Add(currentNode.ScopeIndex, new ScopeClassDefinition(currentNode.CorrespondingSyntaxTreeNode, diff --git a/TreeConverter/LambdaExpressions/Closure/CapturedVariablesSubstitutor.cs b/TreeConverter/LambdaExpressions/Closure/CapturedVariablesSubstitutor.cs index a4064b5fb..521b29071 100644 --- a/TreeConverter/LambdaExpressions/Closure/CapturedVariablesSubstitutor.cs +++ b/TreeConverter/LambdaExpressions/Closure/CapturedVariablesSubstitutor.cs @@ -567,7 +567,7 @@ namespace TreeConverter.LambdaExpressions.Closure private Tuple> CreateTypeDeclarationWithForwardDeclaration(type_declaration cl) { var oldClDef = (class_definition) cl.type_def; - var classDef = SyntaxTreeBuilder.BuildClassDefinition(true); + var classDef = SyntaxTreeBuilder.BuildClassDefinition(); var typeDeclaration = new type_declaration(cl.type_name, classDef); classDef.where_section = oldClDef.where_section; var procedures = new List(); diff --git a/_ParsePABC1/ParsePABC1.sln b/_ParsePABC1/ParsePABC1.sln index 16eaf8ac5..4f80e9bb1 100644 --- a/_ParsePABC1/ParsePABC1.sln +++ b/_ParsePABC1/ParsePABC1.sln @@ -5,9 +5,9 @@ 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}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntaxTree", "..\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}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCompletion", "..\CodeCompletion\CodeCompletion.csproj", "{1AB15F6E-C22E-499A-A7ED-54BA7DE5CFA6}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/_ParsePABC1/ParsePABC1/App.config b/_ParsePABC1/ParsePABC1/App.config index 8e1564635..d1428ad71 100644 --- a/_ParsePABC1/ParsePABC1/App.config +++ b/_ParsePABC1/ParsePABC1/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/_ParsePABC1/ParsePABC1/BaseVisitors/BaseChangeVisitor.cs b/_ParsePABC1/ParsePABC1/BaseVisitors/BaseChangeVisitor.cs index dbd479653..7ef700855 100644 --- a/_ParsePABC1/ParsePABC1/BaseVisitors/BaseChangeVisitor.cs +++ b/_ParsePABC1/ParsePABC1/BaseVisitors/BaseChangeVisitor.cs @@ -11,61 +11,57 @@ namespace ParsePABC1 { class BaseChangeVisitor : CollectUpperNodesVisitor { + public override void DefaultVisit(syntax_tree_node 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"); - - int ind = -1; - for (var i = 0; i < upper.subnodes_count; i++) - if (from == upper[i]) - { - ind = i; - break; - } - upper[ind] = to; + upper.Replace(from, to); } - public statement_list UpperStatementList() + public T UpperNodeAs(int up = 1) where T : syntax_tree_node { - var stl = UpperNode() as statement_list; + var stl = UpperNode(up) as T; if (stl == null) - throw new Exception("оператор вложен не в statement_list"); + throw new Exception("Элемент вложен не в " + typeof(T)); return stl; } + public bool DeleteInIdentList(ident id) + { + var idl = UpperNodeAs(); + return idl.Remove(id); + } + 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; + var stl = UpperNodeAs(); + return stl.Remove(st); } 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; + var stl = UpperNodeAs(); + stl.Replace(from, to); } - public void ReplaceStatement(statement from, List to) + + public void ReplaceStatement(statement from, IEnumerable 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); + var stl = UpperNodeAs(); + stl.Replace(from, to); } } diff --git a/_ParsePABC1/ParsePABC1/BaseVisitors/BaseEnterExitVisitor.cs b/_ParsePABC1/ParsePABC1/BaseVisitors/BaseEnterExitVisitor.cs index f98d2e4e2..ad46a7ca8 100644 --- a/_ParsePABC1/ParsePABC1/BaseVisitors/BaseEnterExitVisitor.cs +++ b/_ParsePABC1/ParsePABC1/BaseVisitors/BaseEnterExitVisitor.cs @@ -9,7 +9,7 @@ using PascalABCCompiler.SyntaxTree; namespace ParsePABC1 { - class BaseEnterExitVisitor: WalkingVisitor + class BaseEnterExitVisitor: WalkingVisitorNew { public BaseEnterExitVisitor() { diff --git a/_ParsePABC1/ParsePABC1/BaseVisitors/CollectNamespaces.cs b/_ParsePABC1/ParsePABC1/BaseVisitors/CollectNamespaces.cs index dc6e1510a..0c74dfa07 100644 --- a/_ParsePABC1/ParsePABC1/BaseVisitors/CollectNamespaces.cs +++ b/_ParsePABC1/ParsePABC1/BaseVisitors/CollectNamespaces.cs @@ -49,9 +49,11 @@ namespace ParsePABC1 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) + { + var f = tds.types_decl.Find(td => td.type_def == cl); Console.WriteLine(" " + f.type_name); + } base.visit(cl); } } diff --git a/_ParsePABC1/ParsePABC1/BaseVisitors/SmallHelperVisitors.cs b/_ParsePABC1/ParsePABC1/BaseVisitors/SmallHelperVisitors.cs index 698c9dbf0..c172c5838 100644 --- a/_ParsePABC1/ParsePABC1/BaseVisitors/SmallHelperVisitors.cs +++ b/_ParsePABC1/ParsePABC1/BaseVisitors/SmallHelperVisitors.cs @@ -9,7 +9,7 @@ using PascalABCCompiler.SyntaxTree; namespace ParsePABC1 { - public class FindLocalDefsVisitor : WalkingVisitor // Запускать только для подпрограмм + public class FindLocalDefsVisitor : WalkingVisitorNew // Запускать только для подпрограмм { public ISet ids = new HashSet(); private bool indef = false; @@ -33,7 +33,7 @@ namespace ParsePABC1 } } - public class FindMainIdentsVisitor : WalkingVisitor // в выражении yield это надо будет. + public class FindMainIdentsVisitor : WalkingVisitorNew // в выражении yield это надо будет. { public HashSet vars = new HashSet(); public override void visit(ident id) diff --git a/_ParsePABC1/ParsePABC1/ChangeWhileVisitor.cs b/_ParsePABC1/ParsePABC1/ChangeWhileVisitor.cs index f7a0922ea..e6734af87 100644 --- a/_ParsePABC1/ParsePABC1/ChangeWhileVisitor.cs +++ b/_ParsePABC1/ParsePABC1/ChangeWhileVisitor.cs @@ -19,36 +19,26 @@ namespace ParsePABC1 lbnum++; return "lb#" + lbnum.ToString(); } - public override void Exit(syntax_tree_node st) + public override void visit(while_node wn) { - if (st.GetType() == typeof(while_node)) - { - var wn = st as while_node; + ProcessNode(wn.statements); + var gt1 = new goto_statement(newLabelName()); + var gt2 = new goto_statement(newLabelName()); + var gt3 = new goto_statement(newLabelName()); - var stl = new statement_list(); + 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 gt1 = new goto_statement(newLabelName()); - var gt2 = new goto_statement(newLabelName()); - var gt3 = new goto_statement(newLabelName()); + var stl = new statement_list(lb3, gt2, lb1, gt3, lb2); - 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()); + Replace(wn, stl); + // в declarations ближайшего блока добавить описание labels + block bl = listNodes.FindLast(x => x is block) as block; - 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); + var ld = new label_definitions(gt1.label, gt2.label, gt3.label); + bl.defs.Add(ld); } } diff --git a/_ParsePABC1/ParsePABC1/DeleteLocalDefs.cs b/_ParsePABC1/ParsePABC1/DeleteLocalDefs.cs index 3f3ebced8..3145379e1 100644 --- a/_ParsePABC1/ParsePABC1/DeleteLocalDefs.cs +++ b/_ParsePABC1/ParsePABC1/DeleteLocalDefs.cs @@ -54,31 +54,16 @@ namespace ParsePABC1 if (idents.Count == 0) { // Выше - variable_definitions, еще выше - declarations - var uvdsl = UpperNode() as variable_definitions; - uvdsl.var_definitions.Remove(vd); // Проблема - мы удаляем первую var_def_statement и вторая становится первой. А в цикле обхода - индексы что естественно + var uvdsl = UpperNodeAs(); + uvdsl.var_definitions.Remove(vd); if (uvdsl.var_definitions.Count == 0) { - var d = UpperNode(2) as declarations; + var d = UpperNodeAs(2); 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/ParsePABC1.csproj b/_ParsePABC1/ParsePABC1/ParsePABC1.csproj index 9c32cdf65..dd7aceee9 100644 --- a/_ParsePABC1/ParsePABC1/ParsePABC1.csproj +++ b/_ParsePABC1/ParsePABC1/ParsePABC1.csproj @@ -11,6 +11,7 @@ ParsePABC1 v4.5 512 + AnyCPU @@ -83,11 +84,11 @@ - + {1ab15f6e-c22e-499a-a7ed-54ba7de5cfa6} CodeCompletion - + {c2cac65a-b2ae-4ccc-b067-e6b8e75df73a} SyntaxTree diff --git a/_ParsePABC1/ParsePABC1/ProcessYieldsCapturedVars.cs b/_ParsePABC1/ParsePABC1/ProcessYieldsCapturedVars.cs index 33a7cdf67..83dcb65ea 100644 --- a/_ParsePABC1/ParsePABC1/ProcessYieldsCapturedVars.cs +++ b/_ParsePABC1/ParsePABC1/ProcessYieldsCapturedVars.cs @@ -19,8 +19,7 @@ namespace ParsePABC1 return "clyield#" + clnum.ToString(); } - - public FindMainIdentsVisitor mids = new FindMainIdentsVisitor(); // захваченные переменные процедуры по всем её yield + public FindMainIdentsVisitor mids; // захваченные переменные процедуры по всем её yield public int countNodesVisited; @@ -44,61 +43,54 @@ namespace ParsePABC1 // сокращение обходимых узлов. Как сделать фильтр по тем узлам, которые необходимо обходить? Например, все операторы (без выражений и описаний), все описания (без операторов) 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(); // очищать при входе в процедуру + visitNode = false; // фильтр - куда не заходить } } - public override void Exit(syntax_tree_node st) + + type_declaration GenClassForYield(procedure_definition pd, IEnumerable fields) { - 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); + // Теперь на месте процедуры генерируем класс + var cm = new class_members(access_modifer.public_modifer); + foreach (var m in fields) + cm.Add(m); + cm.Add(pd); + return new type_declaration(newClassName(), SyntaxTreeBuilder.BuildClassDefinition(cm), SyntaxTreeBuilder.BuildGenSC); } + + public override void visit(procedure_definition pd) + { + hasYields = false; + mids = new FindMainIdentsVisitor(); + + base.visit(pd); + + if (!hasYields) // т.е. мы разобрали процедуру и уже выходим. Это значит, что пока yield будет обрабатываться только в процедурах. Так это и надо. + return; + + var dld = new DeleteLocalDefs(mids.vars); // mids.vars - все захваченные переменные + pd.visit(dld); // Удалить в локальных и блочных описаниях этой процедуры все захваченные переменные + // В результате работы в mids.vars что-то осталось. Это не локальные переменные и с ними непонятно что делать + dld.AfterProcTraverse(); + + // Конструируем определение класса + var cc = GenClassForYield(pd, dld.BlockDeletedIds.Union(dld.LocalDeletedIds)); + var cct = new type_declarations(cc); + + Replace(pd, cct); + + mids = null; // вдруг мы выйдем из процедуры, не зайдем в другую, а там - оператор! Такого конечно не может быть + } + public override void visit(yield_node yn) { hasYields = true; - yn.visit(mids); + if (mids != null) // если мы - внутри процедуры + 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 index 6840fab38..003f2ddec 100644 --- a/_ParsePABC1/ParsePABC1/Program.cs +++ b/_ParsePABC1/ParsePABC1/Program.cs @@ -1,4 +1,5 @@ using System; +using static System.Console; using System.Collections.Generic; using System.Linq; using System.Text; @@ -24,44 +25,52 @@ namespace ParsePABC1 if (cu == null) { - Console.WriteLine("Не распарсилось"); + 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());*/ + try + { + var cu = ParseFile(@"d:\w5\yield2.pas"); + if (cu == null) + return; - /*cu.visit(new CollectUpperNamespacesVisitor()); + /*cu.visit(new ChangeWhileVisitor()); + cu.visit(new DeleteRedundantBeginEnds());*/ - var allv = new AllVarsInProcYields(); - cu.visit(allv); - allv.PrintDict();*/ + /*cu.visit(new CollectUpperNamespacesVisitor()); - /*var cnt = new CountNodesVisitor(); - cu.visit(cnt); - cnt.PrintSortedByValue();*/ + var allv = new AllVarsInProcYields(); + cu.visit(allv); + allv.PrintDict();*/ - /*var ld = new HashSet(); - ld.Add("a"); - ld.Add("p1"); - ld.Add("s"); - var dld = new DeleteLocalDefs(ld); - cu.visit(dld);*/ + /*var cnt = new CountNodesVisitor(); + cu.visit(cnt); + cnt.PrintSortedByValue();*/ - /*var p = new ProcessYieldCapturedVarsVisitor(); - cu.visit(p);*/ + /*var ld = new HashSet(); + ld.Add("a"); + ld.Add("p1"); + ld.Add("s"); + var dld = new DeleteLocalDefs(ld); + cu.visit(dld);*/ - var p = new CalcConstExprs(); - cu.visit(p); + var p = new ProcessYieldCapturedVarsVisitor(); + cu.visit(p); + + /*var p = new CalcConstExprs(); + cu.visit(p);*/ + + cu.visit(new SimplePrettyPrinterVisitor()); + } + catch (Exception e) + { + Console.WriteLine(e); + } - cu.visit(new SimplePrettyPrinterVisitor()); } } } diff --git a/_ParsePABC1/ParsePABC1/SimplePrettyPrinterVisitor.cs b/_ParsePABC1/ParsePABC1/SimplePrettyPrinterVisitor.cs index be11bd4ed..82552f9f2 100644 --- a/_ParsePABC1/ParsePABC1/SimplePrettyPrinterVisitor.cs +++ b/_ParsePABC1/ParsePABC1/SimplePrettyPrinterVisitor.cs @@ -14,7 +14,7 @@ using PascalABCCompiler.SyntaxTree; namespace ParsePABC1 { - class SimplePrettyPrinterVisitor: WalkingVisitor + class SimplePrettyPrinterVisitor: WalkingVisitorNew { int off = 0; diff --git a/_ParsePABC1/f.pas b/_ParsePABC1/f.pas index 25f5eab42..8f8c99052 100644 --- a/_ParsePABC1/f.pas +++ b/_ParsePABC1/f.pas @@ -7,8 +7,8 @@ const ccc: integer = 2; type bcd = integer; begin var k: integer; - yield x111.x222+fff; - yield aaa[i]^.d+(bbb.c*nnn^)*fff(4); +// yield x111.x222+fff; +// yield aaa[i]^.d+(bbb.c*nnn^)*fff(4); end; function f(var i,j,k: integer): integer; diff --git a/_ParsePABC1/f1.pas b/_ParsePABC1/f1.pas index 700cbfb48..b265c69d2 100644 --- a/_ParsePABC1/f1.pas +++ b/_ParsePABC1/f1.pas @@ -11,6 +11,7 @@ var l,m,n: integer; kk,jj: real; begin var i,j,k,mmm: integer; + yield x111.x222+fff; yield l*k; yield i*n; end; diff --git a/_ParsePABC1/yield2.pas b/_ParsePABC1/yield2.pas index fb3b26bd1..303043563 100644 --- a/_ParsePABC1/yield2.pas +++ b/_ParsePABC1/yield2.pas @@ -1,13 +1,13 @@ +type A = class + j,k: integer; +end; + function Gen: sequence of integer; +var j,k: real; begin var i := 1; - while i<=10 do - begin - yield i*i; - i += 1; - end; + yield i*j; end; begin - write(1) end. \ No newline at end of file diff --git a/bin/Lib/PABCRtl.dll b/bin/Lib/PABCRtl.dll index e42eded88..47e198293 100644 Binary files a/bin/Lib/PABCRtl.dll and b/bin/Lib/PABCRtl.dll differ diff --git a/bin/Lib/PABCSystem.pas b/bin/Lib/PABCSystem.pas index 31c9691eb..e57763bfb 100644 --- a/bin/Lib/PABCSystem.pas +++ b/bin/Lib/PABCSystem.pas @@ -3017,7 +3017,7 @@ end;} // Extension methods for IEnumerable //------------------------------------------------------------------------------ /// , delim -function System.Collections.Generic.IEnumerable.Print(delim: string := ' '): sequence of T; +function System.Collections.Generic.IEnumerable.Print(delim: string): sequence of T; begin var g := Self.GetEnumerator(); if g.MoveNext() then @@ -3027,16 +3027,28 @@ begin Result := Self; end; +/// , +function System.Collections.Generic.IEnumerable.Print(): sequence of T; +begin + Result := Self.Print(' '); +end; + /// , delim , -function System.Collections.Generic.IEnumerable.Println(delim: string := ' '): sequence of T; +function System.Collections.Generic.IEnumerable.Println(delim: string): sequence of T; begin Self.Print(delim); Writeln; Result := Self; end; +/// , , +function System.Collections.Generic.IEnumerable.Println(): sequence of T; +begin + Result := Self.Println(' '); +end; + /// , , delim -function System.Collections.Generic.IEnumerable.JoinIntoString(delim: string := ' '): string; +function System.Collections.Generic.IEnumerable.JoinIntoString(delim: string): string; begin var g := Self.GetEnumerator(); var sb := new System.Text.StringBuilder(''); @@ -3047,6 +3059,12 @@ begin Result := sb.ToString; end; +/// , , +function System.Collections.Generic.IEnumerable.JoinIntoString(): string; +begin + Result := Self.JoinIntoString(' '); +end; + /// procedure System.Collections.Generic.IEnumerable.&ForEach(action: Action); begin