Распространение проверки захвата имен на любые вложенные записи (в т.ч.не безымянные)

This commit is contained in:
Mikhalkovich Stanislav 2020-03-14 11:08:44 +03:00
parent e48218cd9e
commit 45d177bebc
13 changed files with 142 additions and 66 deletions

View file

@ -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 = "2386";
public const string Revision = "2387";
public const string MainVersion = Major + "." + Minor;
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;

View file

@ -1,4 +1,4 @@
%COREVERSION%=2
%REVISION%=2386
%MINOR%=6
%REVISION%=2387
%COREVERSION%=2
%MAJOR%=3

Binary file not shown.

View file

@ -1 +1 @@
3.6.2.2386
3.6.2.2387

View file

@ -1 +1 @@
!define VERSION '3.6.2.2386'
!define VERSION '3.6.2.2387'

View file

@ -1601,7 +1601,7 @@ namespace PascalABCCompiler.SyntaxTree
}
public override string ToString()
{
return /*""+this.ClassName+" "+this.name+" "+*/this.UnknownID.ToString();
return "yui(обраб.на сем.)"+this.ClassName+" "+this.UnknownID.ToString();
}
}

View file

@ -136,6 +136,8 @@ namespace SyntaxVisitors.CheckingVisitors
foreach (var member in defBlocks[0].members)
{
var q = member as var_def_statement;
if (q == null)
continue;
var id = q.vars.idents[0]; // это просто имя
var type = q.vars_type;
var initValue = q.inital_value;
@ -180,52 +182,9 @@ namespace SyntaxVisitors.CheckingVisitors
var cd = st as class_definition;
if (cd == null)
return;
if (cd.keyword == class_keyword.Record && cd.Parent is var_def_statement) // безымянная запись
if (cd.keyword == class_keyword.Record)
{
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;
@ -243,6 +202,59 @@ namespace SyntaxVisitors.CheckingVisitors
}
}
if (MostUpperNodeWithNotGlobalNames == null) // то есть, это - глобальный уроень, и захватывать можно всё
return;
// если попали сюда, то запись вложенная
//if (cd.Parent is var_def_statement) // безымянная запись
{
if (cd.class_parents != null && cd.class_parents.Count > 0)
throw new SyntaxVisitorError("NESTED_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("NESTED_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("NESTED_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("NESTED_RECORD_CANNOT_CONTAIN_METHODS", pd.source_context);
var sp = d as simple_property;
if (sp != null)
throw new SyntaxVisitorError("NESTED_RECORD_CANNOT_CONTAIN_PROPERTIES", sp.source_context);
}
}
// после накопления имен подниматься по внешнему контексту, пропуская эту запись, и искать переменные и типы
// Переменные - в var_def_statement. Типы - в type_definition, в типовых параметрах обобщенных процедур и в типовых параметрах имен типов
// Подняться вверх до program_module и запомнить последнюю class_definition, procedure_definition
// или class_definition или type_declaration если это именованный тип
// То есть у class_definition проверять Parent - если это type_declaration, то смотреть на имя типа, а если это var_def_statement, то смотреть на имена переменных
var cdvis = OneUnnamedRecordCaptureNamesVisitor.New(cd);
cdvis.CollectNames();
var localsvis = CollectDefNamesFromMostUpperLocalContextVisitor.New(cd);
if (MostUpperNodeWithNotGlobalNames != null)
{
@ -266,7 +278,7 @@ namespace SyntaxVisitors.CheckingVisitors
if (string.Compare(s,lname,true)==0 && !b)
{
// то надо еще проверить cvdi чтобы там как раз не было этих имен
throw new SyntaxVisitorError("UNNAMED_RECORD_CANNOT_CATCH_NAMES_FROM_NONGLOBAL_CONTEXT", id);
throw new SyntaxVisitorError("NESTED_RECORD_CANNOT_CATCH_NAMES_FROM_NONGLOBAL_CONTEXT", id);
}
}
}

View file

@ -0,0 +1,15 @@
type
A = class
i: integer;
procedure p;
type b = record
x := i;
end;
begin
end;
end;
begin
end.

View file

@ -0,0 +1,19 @@
var global: integer;
type int = integer;
type Class1<T,T1> = class
classfield: integer;
const cc = 2;
function p<PPT>(pa,pb: real): integer;
type int1 = record
j: integer := cc;
mostinternal1: set of integer := [j];
end;
begin
end;
end;
begin
end.

View file

@ -0,0 +1,18 @@
var global: integer;
type int = integer;
type Class1<T,T1> = class
classfield: integer;
const cc = 2;
function p(pa,pb: real): integer;
type int1 = record
j: T := 1;
end;
begin
end;
end;
begin
end.

View file

@ -0,0 +1,12 @@
var global: integer;
function p(pa,pb: real): integer;
type int1 = record
j: T := pa;
end;
begin
end;
begin
end.

View file

@ -28,10 +28,10 @@ Var_{0}_is_already_defined=Variable {0} is already defined
INVALID_INTERFACE_MEMBER=Interfaces cannot contain fields and method implementation
INDEXED_AUTO_PROPERTY=Autoproperties cannot be indexed properties
UNNAMED_RECORD_CANNOT_IMPLEMENT_INTERFACE=Unnamed records can not implement interfaces
UNNAMED_RECORD_CANNOT_CONTAIN_METHODS=Unnamed records can not contain methods
UNNAMED_RECORD_CANNOT_CONTAIN_PROPERTIES=Unnamed records can not contain properties
UNNAMED_RECORD_CANNOT_CONTAIN_CONSTRUCTORS=Unnamed records can not contain constructors
UNNAMED_RECORD_CAN_CONTAIN_ONLY_ONE_PUBLIC_VISIBILITY_SECTION=Unnamed records can contain only one section with public visibility
UNNAMED_RECORD_CANNOT_CONTAIN_SEVERAL_VISIBILITY_SECTIONS=Unnamed records can not contain several visibility section
UNNAMED_RECORD_CANNOT_CATCH_NAMES_FROM_NONGLOBAL_CONTEXT=Unnamed records cannot catch names from nonglobal context
NESTED_RECORD_CANNOT_IMPLEMENT_INTERFACE=Nested records can not implement interfaces
NESTED_RECORD_CANNOT_CONTAIN_METHODS=Nested records can not contain methods
NESTED_RECORD_CANNOT_CONTAIN_PROPERTIES=Nested records can not contain properties
NESTED_RECORD_CANNOT_CONTAIN_CONSTRUCTORS=Nested records can not contain constructors
NESTED_RECORD_CAN_CONTAIN_ONLY_ONE_PUBLIC_VISIBILITY_SECTION=Nested records can contain only one section with public visibility
NESTED_RECORD_CANNOT_CONTAIN_SEVERAL_VISIBILITY_SECTIONS=Nested records can not contain several visibility section
UNNAMED_RECORD_CANNOT_CATCH_NAMES_FROM_NONGLOBAL_CONTEXT=Nested records cannot catch names from nonglobal context

View file

@ -31,10 +31,10 @@ Var_{0}_is_already_defined=Переменная {0} уже определена
INVALID_INTERFACE_MEMBER=Интерфейсы не могут содержать поля и реализацию методов
INDEXED_AUTO_PROPERTY=Автосвойства не могут быть индексными
UNNAMED_RECORD_CANNOT_IMPLEMENT_INTERFACE=Безымянные записи не могут реализовывать интерфейсы
UNNAMED_RECORD_CANNOT_CONTAIN_METHODS=Безымянные записи не могут содержать методы
UNNAMED_RECORD_CANNOT_CONTAIN_PROPERTIES=Безымянные записи не могут содержать свойства
UNNAMED_RECORD_CANNOT_CONTAIN_CONSTRUCTORS=Безымянные записи не могут содержать конструкторы
UNNAMED_RECORD_CAN_CONTAIN_ONLY_ONE_PUBLIC_VISIBILITY_SECTION=Безымянные записи могут содержать лишь одну секцию с public-видимостью
UNNAMED_RECORD_CANNOT_CONTAIN_SEVERAL_VISIBILITY_SECTIONS=Безымянные записи не могут содержать несколько секций видимости
UNNAMED_RECORD_CANNOT_CATCH_NAMES_FROM_NONGLOBAL_CONTEXT=Безымянные записи не могут захватывать имена из неглобального контекста
NESTED_RECORD_CANNOT_IMPLEMENT_INTERFACE=Вложенные записи не могут реализовывать интерфейсы
NESTED_RECORD_CANNOT_CONTAIN_METHODS=Вложенные записи не могут содержать методы
NESTED_RECORD_CANNOT_CONTAIN_PROPERTIES=Вложенные записи не могут содержать свойства
NESTED_RECORD_CANNOT_CONTAIN_CONSTRUCTORS=Вложенные записи не могут содержать конструкторы
NESTED_RECORD_CAN_CONTAIN_ONLY_ONE_PUBLIC_VISIBILITY_SECTION=Вложенные записи могут содержать лишь одну секцию с public-видимостью
NESTED_RECORD_CANNOT_CONTAIN_SEVERAL_VISIBILITY_SECTIONS=Вложенные записи не могут содержать несколько секций видимости
NESTED_RECORD_CANNOT_CATCH_NAMES_FROM_NONGLOBAL_CONTEXT=Вложенные записи не могут захватывать имена из неглобального контекста