From 854581717397a00afef9b029fb8a749fa7abfb33 Mon Sep 17 00:00:00 2001 From: Mikhalkovich Stanislav Date: Sun, 8 Mar 2020 09:28:11 +0300 Subject: [PATCH] =?UTF-8?q?fix=20#1053=20=D0=92=D0=BB=D0=BE=D0=B6=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=B5=20=D0=B1=D0=B5=D0=B7=D1=8B=D0=BC=D1=8F?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=B5=20=D0=B7=D0=B0=D0=BF=D0=B8=D1=81=D0=B8?= =?UTF-8?q?=20=D1=82=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D1=81=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=20=D1=80=D0=B0=D0=B7=D1=80=D0=B5=D1=88=D0=B5=D0=BD?= =?UTF-8?q?=D1=8B,=20=D0=BD=D0=BE=20=D0=B7=D0=B0=D0=BF=D1=80=D0=B5=D1=89?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=D0=B7=D0=B0=D1=85=D0=B2=D0=B0=D1=82=D1=8B?= =?UTF-8?q?=D0=B2=D0=B0=D1=82=D1=8C=20=D0=B8=D0=BC=D0=B5=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=B8=D0=B7=20=D0=BD=D0=B5=D0=B3=D0=BB=D0=BE=D0=B1=D0=B0=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BA=D0=BE=D0=BD=D1=82=D0=B5?= =?UTF-8?q?=D0=BA=D1=81=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Configuration/GlobalAssemblyInfo.cs | 2 +- Configuration/Version.defs | 2 +- Localization/DefaultLang.resources | Bin 92405 -> 93158 bytes .../PascalABCParserNewSaushkin/ABCPascal.cs | 6 +- .../PascalABCParserNewSaushkin/ABCPascal.y | 4 +- .../ABCPascalYacc.cs | 10 +- Parsers/PascalABCParserNewSaushkin/PABC.ymc | 1 + Release/pabcversion.txt | 2 +- ReleaseGenerators/PascalABCNET_version.nsh | 2 +- .../StandardSyntaxConverter.cs | 4 + .../UnnamedRecordsCheckErrorsVisitor.cs | 266 + SyntaxVisitors/SyntaxVisitors.csproj | 5 +- TestSuite/CompilationSamples/OpenCL.pas | 14220 ++- TestSuite/CompilationSamples/OpenCLABC.pas | 130 +- TestSuite/CompilationSamples/OpenGL.pas | 82565 +++++++++------- TestSuite/CompilationSamples/PABCSystem.pas | 320 +- TestSuite/errors/err0348_ur.pas | 25 + TestSuite/errors/err0349_ur.pas | 25 + TestSuite/errors/err0350_ur.pas | 25 + TestSuite/errors/err0351_ur.pas | 25 + TestSuite/errors/err0352_ur.pas | 25 + TestSuite/ur1.pas | 26 + TestSuite/ur2.pas | 17 + .../TreeConversion/syntax_tree_visitor.cs | 15 +- bin/Lib/PABCSystem.pas | 320 +- bin/Lng/Eng/SyntaxTreeVisitorsErrors.dat | 13 +- bin/Lng/Rus/SemanticErrors_ms.dat | 2 +- bin/Lng/Rus/SyntaxTreeVisitorsErrors.dat | 10 +- 28 files changed, 58753 insertions(+), 39314 deletions(-) create mode 100644 SyntaxVisitors/CheckingVisitors/UnnamedRecordsCheckErrorsVisitor.cs create mode 100644 TestSuite/errors/err0348_ur.pas create mode 100644 TestSuite/errors/err0349_ur.pas create mode 100644 TestSuite/errors/err0350_ur.pas create mode 100644 TestSuite/errors/err0351_ur.pas create mode 100644 TestSuite/errors/err0352_ur.pas create mode 100644 TestSuite/ur1.pas create mode 100644 TestSuite/ur2.pas diff --git a/Configuration/GlobalAssemblyInfo.cs b/Configuration/GlobalAssemblyInfo.cs index 9640789d7..80ef1d85b 100644 --- a/Configuration/GlobalAssemblyInfo.cs +++ b/Configuration/GlobalAssemblyInfo.cs @@ -15,7 +15,7 @@ internal static class RevisionClass public const string Major = "3"; public const string Minor = "6"; public const string Build = "2"; - public const string Revision = "2368"; + public const string Revision = "2374"; 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 e06456d55..f7043ef6c 100644 --- a/Configuration/Version.defs +++ b/Configuration/Version.defs @@ -1,4 +1,4 @@ %COREVERSION%=2 -%REVISION%=2368 +%REVISION%=2374 %MINOR%=6 %MAJOR%=3 diff --git a/Localization/DefaultLang.resources b/Localization/DefaultLang.resources index 05d93d14c31b9708b8191ea4f6011a2dab8c4883..ef7f1c72daddb57cd9def042e6628e78d5206292 100644 GIT binary patch delta 170 zcmex*k@eYi)(H=on6fuM@>9JpLY@A-qT zj~;yb4a9#GUc7nw_JP8S=L&D1K7Re~;e*$I-oAVMPT|$Nx1XNA`uOPqFV}WQamFoy E0GV51a{vGU delta 36 ucmV+<0NelO*9G;_1(4tZ5oodEN~M$5r6#v;7y&^6vz4c^Z?`rY0kBb05fI4$ diff --git a/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs b/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs index 7afcc186f..a55e62937 100644 --- a/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs +++ b/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs @@ -1,9 +1,9 @@ // // This CSharp output file generated by Gardens Point LEX // Version: 1.1.3.301 -// Machine: DESKTOP-P4NLNB1 -// DateTime: 2/10/2020 2:41:45 PM -// UserName: fatco +// Machine: DESKTOP-G8V08V4 +// DateTime: 07.03.2020 10:31:43 +// UserName: ????????? // GPLEX input file // GPLEX frame file // diff --git a/Parsers/PascalABCParserNewSaushkin/ABCPascal.y b/Parsers/PascalABCParserNewSaushkin/ABCPascal.y index f90aa48e7..1e36b3d09 100644 --- a/Parsers/PascalABCParserNewSaushkin/ABCPascal.y +++ b/Parsers/PascalABCParserNewSaushkin/ABCPascal.y @@ -1550,7 +1550,7 @@ object_type { var cd = NewObjectType((class_attribute)$1, $2, $3 as named_type_reference_list, $4 as where_definition_list, $5 as class_body_list, @$); $$ = cd; - var tt = cd.DescendantNodes().OfType().Where(cld => cld.keyword == class_keyword.Record); + /*var tt = cd.DescendantNodes().OfType().Where(cld => cld.keyword == class_keyword.Record); if (tt.Count()>0) { foreach (var ttt in tt) @@ -1558,7 +1558,7 @@ object_type var sc = ttt.source_context; parsertools.AddErrorFromResource("NESTED_RECORD_DEFINITIONS_ARE_FORBIDDEN", new LexLocation(sc.begin_position.line_num, sc.begin_position.column_num-1, sc.end_position.line_num, sc.end_position.column_num, sc.FileName)); } - } + }*/ } ; diff --git a/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs b/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs index 6c3244baa..dd7a62de0 100644 --- a/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs +++ b/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs @@ -1,9 +1,9 @@ // (see accompanying GPPGcopyright.rtf) // GPPG version 1.3.6 -// Machine: DESKTOP-P4NLNB1 -// DateTime: 2/10/2020 2:41:46 PM -// UserName: fatco +// Machine: DESKTOP-G8V08V4 +// DateTime: 07.03.2020 10:31:44 +// UserName: ????????? // Input file // options: no-lines gplex @@ -3973,7 +3973,7 @@ public partial class GPPGParser: ShiftReduceParser().Where(cld => cld.keyword == class_keyword.Record); + /*var tt = cd.DescendantNodes().OfType().Where(cld => cld.keyword == class_keyword.Record); if (tt.Count()>0) { foreach (var ttt in tt) @@ -3981,7 +3981,7 @@ public partial class GPPGParser: ShiftReduceParser tkRecord, optional_base_classes, optional_where_section, diff --git a/Parsers/PascalABCParserNewSaushkin/PABC.ymc b/Parsers/PascalABCParserNewSaushkin/PABC.ymc index 9dc11b7da..6e21d7eac 100644 --- a/Parsers/PascalABCParserNewSaushkin/PABC.ymc +++ b/Parsers/PascalABCParserNewSaushkin/PABC.ymc @@ -262,5 +262,6 @@ script= + diff --git a/Release/pabcversion.txt b/Release/pabcversion.txt index 7eac1b1fc..47e09446b 100644 --- a/Release/pabcversion.txt +++ b/Release/pabcversion.txt @@ -1 +1 @@ -3.6.2.2368 +3.6.2.2374 diff --git a/ReleaseGenerators/PascalABCNET_version.nsh b/ReleaseGenerators/PascalABCNET_version.nsh index e4687abab..776045c89 100644 --- a/ReleaseGenerators/PascalABCNET_version.nsh +++ b/ReleaseGenerators/PascalABCNET_version.nsh @@ -1 +1 @@ -!define VERSION '3.6.2.2368' +!define VERSION '3.6.2.2374' diff --git a/SyntaxTreeConverters/StandardSyntaxConverter.cs b/SyntaxTreeConverters/StandardSyntaxConverter.cs index 1ac9e2b86..cdd552a22 100644 --- a/SyntaxTreeConverters/StandardSyntaxConverter.cs +++ b/SyntaxTreeConverters/StandardSyntaxConverter.cs @@ -7,6 +7,7 @@ using System.Text; using PascalABCCompiler.SyntaxTree; using SyntaxVisitors; using SyntaxVisitors.SugarVisitors; +using SyntaxVisitors.CheckingVisitors; namespace PascalABCCompiler.SyntaxTreeConverters { @@ -22,6 +23,9 @@ namespace PascalABCCompiler.SyntaxTreeConverters // new range - до всего! До выноса выражения с лямбдой из foreach NewRangeDesugarVisitor.New.ProcessNode(root); + // Unnamed Records перенёс сюда + UnnamedRecordsCheckVisitor.New.ProcessNode(root); + // Выносим выражения с лямбдами из заголовка foreach StandOutExprWithLambdaInForeachSequenceVisitor.New.ProcessNode(root); VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer.New.ProcessNode(root); // SSM bug fix #1147 diff --git a/SyntaxVisitors/CheckingVisitors/UnnamedRecordsCheckErrorsVisitor.cs b/SyntaxVisitors/CheckingVisitors/UnnamedRecordsCheckErrorsVisitor.cs new file mode 100644 index 000000000..a13d22287 --- /dev/null +++ b/SyntaxVisitors/CheckingVisitors/UnnamedRecordsCheckErrorsVisitor.cs @@ -0,0 +1,266 @@ +// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using PascalABCCompiler.SyntaxTree; + +namespace SyntaxVisitors.CheckingVisitors +{ + public class CollectDefNamesFromMostUpperLocalContextVisitor : BaseEnterExitVisitor + { + public List idents = new List(); + public class_definition StartUnnamedRecord; // безымянная запись, до которой и для которой будем искать имена + public static CollectDefNamesFromMostUpperLocalContextVisitor New(class_definition cd) + { + return new CollectDefNamesFromMostUpperLocalContextVisitor(cd); + } + public CollectDefNamesFromMostUpperLocalContextVisitor(class_definition cd) + { + StartUnnamedRecord = cd; + } + public void Add(ident id) + { + if (idents.FindIndex(x => string.Compare(x.name, id.name, true) == 0) == -1) + idents.Add(id); + } + public void AddIdentList(ident_list idl) + { + foreach (var id in idl.idents) + Add(id); + } + public void AddProcHeader(procedure_header h) + { + Add(h.name.meth_name); + if (h.template_args != null) + AddIdentList(h.template_args); + if (h.parameters != null) + foreach (var tp in h.parameters.params_list) + { + AddIdentList(tp.idents); + } + } + + /*public override void visit(template_type_name ttn) // при определении типа + { + Add(ttn); + AddIdentList(ttn.template_args); + }*/ + public override void visit(var_def_statement vds) + { + AddIdentList(vds.vars); + ProcessNode(vds.vars_type); + } + /*public override void visit(typed_parameters tp) + { + AddIdentList(tp.idents); + }*/ + public override void visit(procedure_header h) + { + AddProcHeader(h); + } + public override void visit(function_header h) + { + AddProcHeader(h); + } + public override void visit(typed_const_definition cd) + { + Add(cd.const_name); + } + public override void visit(simple_const_definition cd) + { + Add(cd.const_name); + } + public override void visit(type_declaration td) + { + Add(td.type_name); + if (td.type_name is template_type_name ttn) + { + AddIdentList(ttn.template_args); + } + ProcessNode(td.type_def); + } + + // var_def_statement.idents + + // typed_parameters (параметры процедуры-функции) + + // method_name + + // template_type_name + + // type_declaration.type_name + // const_definition.constant_name + + + public override void visit(class_definition cd) + { + if (cd == StartUnnamedRecord) + { + //cd = cd; + // то внутри нее не искать - мы как раз с ней и проверяем пересечение имен + } + else if (StartUnnamedRecord.source_context.In(cd.source_context)) + { + DefaultVisit(cd); + } + else + { + + } + } + + } + + public class OneUnnamedRecordCaptureNamesVisitor : BaseEnterExitVisitor + { + // Имена, захваченные записью. Их мы будем искать затем во внешних контекстах + // Сюда не включаются имена во вложенных безымянных записях + // Сюда не включаются имена, являющиеся определениями (в данном случае это только определения полей) + public List idents = new List(); + public class_definition StartUnnamedRecord; + public static OneUnnamedRecordCaptureNamesVisitor New(class_definition cd) + { + return new OneUnnamedRecordCaptureNamesVisitor(cd); + } + public OneUnnamedRecordCaptureNamesVisitor(class_definition cd) + { + StartUnnamedRecord = cd; + } + // Накопленные имена типов надо будет сравнивать только с именами в секции type (в процедуре) и с именами в параметрах внешних обобщений (процедур и классов) + public void CollectNames() + { + var defBlocks = StartUnnamedRecord.body.class_def_blocks; + // Теперь известно, что остался ровно один class_def_block + foreach (var member in defBlocks[0].members) + { + var q = member as var_def_statement; + var id = q.vars.idents[0]; // это просто имя + var type = q.vars_type; + var initValue = q.inital_value; + // idents.Add(id); - вот как раз не надо добавлять определения - только использования!!! + ProcessNode(type); + if (initValue != null) + ProcessNode(initValue); + } + } + public override void visit(ident id) + { + if (idents.FindIndex(x => string.Compare(x.name,id.name,true) == 0) == -1) + idents.Add(id); + } + public override void visit(named_type_reference ntr) + { + visit(ntr.names[0]); + if (ntr is template_type_reference ttr) + { + foreach (var tt in ttr.params_list.params_list) + ProcessNode(tt); + } + } + public override void visit(class_definition cd) + { + if (cd.keyword == class_keyword.Record && cd.Parent is var_def_statement) // безымянная запись + { + // то пропустить её - она вложенная, мы её уже обошли + } + else base.visit(cd); + } + + } + public class UnnamedRecordsCheckVisitor : BaseEnterExitVisitor + { + public static UnnamedRecordsCheckVisitor New + { + get { return new UnnamedRecordsCheckVisitor(); } + } + public override void Exit(syntax_tree_node st) + { + var cd = st as class_definition; + if (cd == null) + return; + if (cd.keyword == class_keyword.Record && cd.Parent is var_def_statement) // безымянная запись + { + if (cd.class_parents != null && cd.class_parents.Count > 0) + throw new SyntaxVisitorError("UNNAMED_RECORD_CANNOT_IMPLEMENT_INTERFACE", cd.class_parents[0].source_context); + + var defBlocks = cd.body.class_def_blocks; + + if (defBlocks[0].access_mod.access_level != access_modifer.public_modifer) + { + var f = cd.body.class_def_blocks.First(); + var loc = f.source_context; + if (loc == null) + loc = cd.source_context; + throw new SyntaxVisitorError("UNNAMED_RECORD_CAN_CONTAIN_ONLY_ONE_PUBLIC_VISIBILITY_SECTION", loc); + } + + if (defBlocks.Count > 1) + { + var el1 = cd.body.class_def_blocks.ElementAt(1); + var loc = el1.access_mod.source_context; + if (loc == null) + loc = cd.source_context; + throw new SyntaxVisitorError("UNNAMED_RECORD_CANNOT_CONTAIN_SEVERAL_VISIBILITY_SECTIONS", loc); + } + + // здесь уже известно, что defBlocks.Count = 1 - пройтись по этому блоку и проверить, нет ли методов или свойств + + foreach (var d in defBlocks[0].members) + { + var pd = d as procedure_definition; + if (pd != null) + throw new SyntaxVisitorError("UNNAMED_RECORD_CANNOT_CONTAIN_METHODS", pd.source_context); + var sp = d as simple_property; + if (sp != null) + throw new SyntaxVisitorError("UNNAMED_RECORD_CANNOT_CONTAIN_PROPERTIES", sp.source_context); + } + + var cdvis = OneUnnamedRecordCaptureNamesVisitor.New(cd); + cdvis.CollectNames(); + // после накопления имен подниматься по внешнему контексту, пропуская эту запись, и искать переменные и типы + // Переменные - в var_def_statement. Типы - в type_definition, в типовых параметрах обобщенных процедур и в типовых параметрах имен типов + + // Подняться вверх до program_module и запомнить последнюю class_definition, procedure_definition + // или class_definition или type_declaration если это именованный тип + // То есть у class_definition проверять Parent - если это type_declaration, то смотреть на имя типа, а если это var_def_statement, то смотреть на имена переменных + + syntax_tree_node MostUpperNodeWithNotGlobalNames = null; + + syntax_tree_node sn = cd; + while ((sn != null) && !(sn is program_module)) + { + sn = sn.Parent; + if (sn is procedure_definition) + MostUpperNodeWithNotGlobalNames = sn; + if (sn is class_definition) + { + MostUpperNodeWithNotGlobalNames = sn; + sn = sn.Parent; + if (sn is type_declaration || sn is var_def_statement) + MostUpperNodeWithNotGlobalNames = sn; + } + } + + var localsvis = CollectDefNamesFromMostUpperLocalContextVisitor.New(cd); + if (MostUpperNodeWithNotGlobalNames != null) + { + localsvis.ProcessNode(MostUpperNodeWithNotGlobalNames); + } + + var lvi = localsvis.idents.Select(id => id.name).ToArray(); + var cvi = cdvis.idents; + + // Теперь проверим пересечение + foreach (var id in cvi) + { + var s = id.name; + foreach (var lname in lvi) + { + if (string.Compare(s,lname,true)==0) + { + throw new SyntaxVisitorError("UNNAMED_RECORD_CANNOT_CATCH_NAMES_FROM_NONGLOBAL_CONTEXT", id); + } + } + } + } + } + } +} diff --git a/SyntaxVisitors/SyntaxVisitors.csproj b/SyntaxVisitors/SyntaxVisitors.csproj index 2dc8a3e9d..96febb7c1 100644 --- a/SyntaxVisitors/SyntaxVisitors.csproj +++ b/SyntaxVisitors/SyntaxVisitors.csproj @@ -46,6 +46,7 @@ + @@ -116,9 +117,7 @@ YieldHelpers - - - +