bug fix #891 - попытка номер два

This commit is contained in:
Mikhalkovich Stanislav 2019-06-12 11:30:07 +03:00
parent 99882270d0
commit 76f4020256
10 changed files with 231 additions and 23 deletions

View file

@ -15,7 +15,7 @@ internal static class RevisionClass
public const string Major = "3";
public const string Minor = "5";
public const string Build = "0";
public const string Revision = "2098";
public const string Revision = "2102";
public const string MainVersion = Major + "." + Minor;
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;

View file

@ -1,4 +1,4 @@
%COREVERSION%=0
%REVISION%=2098
%REVISION%=2102
%MINOR%=5
%MAJOR%=3

View file

@ -1 +1 @@
!define VERSION '3.5.0.2098'
!define VERSION '3.5.0.2102'

View file

@ -7,6 +7,9 @@ using PascalABCCompiler.SyntaxTree;
namespace PascalABCCompiler.SyntaxTreeConverters
{
// Первое предназначение - вынести последовательность из заголовка в foreach до foreach как отдельное присваивание
// Второе предназначение - переименовать все переменные, совпадающие по имени с типом T обобщенного класса, в котором находится метод, содержащий лямбду
public class StandOutExprWithLambdaInForeachSequenceVisitor : BaseChangeVisitor
{
public static StandOutExprWithLambdaInForeachSequenceVisitor New
@ -18,12 +21,46 @@ namespace PascalABCCompiler.SyntaxTreeConverters
}
private int GenIdNum = 0;
//private int GenRenameIdNum = 0;
//private ident_list ClassTemplateArgsOrNull = null; // если мы - в обобщенном классе, то это - его обобщенные параметры
// надо бы еще то же сделать если метод описывается отдельно
public ident GenIdentName()
{
GenIdNum++;
return new ident("$GenContFE" + GenIdNum.ToString());
}
/* public string RenameIdentName(string name)
{
GenRenameIdNum++;
return "$GenRenameLocalInLambda" + GenRenameIdNum.ToString();
}
public override void Enter(syntax_tree_node st)
{
if (st is class_definition cd)
{
var a = cd.Parent as type_declaration;
ClassTemplateArgsOrNull = (a?.type_name as template_type_name)?.template_args;
}
}
public override void Exit(syntax_tree_node st)
{
if (st is class_definition)
ClassTemplateArgsOrNull = null;
}
public override void visit(procedure_definition pd)
{
if (ClassTemplateArgsOrNull == null)
return;
var lfds = pd.DescendantNodes().OfType<function_lambda_definition>();
if (lfds.Count() == 0)
return;
}*/
public override void visit(foreach_stmt fe)
{
//if (fe.DescendantNodes().OfType<function_lambda_definition>().Count() > 0) // из-за #1984 убрал вообще условие. Пусть будет всегда
@ -40,4 +77,58 @@ namespace PascalABCCompiler.SyntaxTreeConverters
base.visit(fe);
}
}
// Может, переименовать все T? Всё равно алгоритм переименовывания будет один
// Искать описания с T. Как нашли - с этого места переименовывать
// Сделать визитор LocalRenamer и переименовывать с места описания
public class LocalRenamer : BaseChangeVisitor
{
public static void RenameFrom(var_def_statement vd, string Name, string NewName)
{
var lr = new LocalRenamer();
lr.ProcessNode(vd);
}
}
// Поиск всех захваченных переменных в лямбде
// Это сложно
public class LambdaCapturedNamesSearcher : BaseChangeVisitor
{
List<ident> idents = new List<ident>();
public static LambdaCapturedNamesSearcher New
{
get
{
return new LambdaCapturedNamesSearcher();
}
}
public override void visit(ident id)
{
// хорошо бы всё здесь захватить! Но вдруг это - описание...
}
public override void visit(dot_node dn)
{
// это точно надо захватывать
}
public override void visit(var_def_statement vds)
{
// имена обойти отдельно, инициализатор - отдельно
foreach (var id in vds.vars.idents)
{
// Надо проверять совпадение имен с именами в параметрах обобщения
// если не совпадают, то просто пропускаем
// если совпадают, то исключаем это имя из списка проверки! Всё - имя уже переопределено! И это произошло в лямбде, что можно
}
visit(vds.inital_value);
}
public override void visit(function_lambda_definition ld)
{
// параметры обойти отдельно, тело отдельно
// проблема, что могут быть вложенные лямбды. Т.е это - основная, а в ней - ещё.
}
}
}

View file

@ -0,0 +1,31 @@
type
t1 = class
public procedure p0 := exit;
public i: integer := 2;
public procedure p1;
{begin
var v := 0;
var p: procedure := ()->begin
v := v;
Assert(i=2);
p0;
end;
p;
end;}
end;
procedure t1.p1;
begin
var v := 0;
var p: procedure := ()->begin
v := v;
Assert(i=2);
p0;
end;
p;
end;
begin
t1.Create.p1;
end.

View file

@ -0,0 +1,32 @@
type
t1<T> = class
public static procedure p0 := Print(111);
public static i: integer := 2;
public static function p1: integer;
{begin
var v := 0;
var p: procedure := ()->begin
v := v;
Assert(i=2);
p0;
end;
p;
end;}
end;
static function t1<T>.p1: integer;
begin
var v := 0;
var p: procedure := ()->begin
v := v;
Assert(i=2);
p0;
end;
p;
end;
begin
t1&<integer>.p1;
end.

View file

@ -0,0 +1,21 @@
type
t1<T> = class
public static procedure p0 := Print(111);
public static i: integer := 2;
public static function p1: integer;
begin
var v := 0;
var p: procedure := ()->begin
v := v;
Assert(i=2);
p0;
end;
p;
end;
end;
begin
t1&<integer>.p1;
end.

View file

@ -0,0 +1,10 @@
type
T = class
public static procedure p1(a: integer) := exit;
public static procedure P := &Array.ForEach(Arr(0), x -> p1(x)); // В данной версии компилятора не поддерживается замыкание данного типа символов
end;
begin
Assert(1=1)
end.

View file

@ -164,7 +164,7 @@ namespace TreeConverter.LambdaExpressions.Closure
si.sym_info.semantic_node_type == semantic_node_type.common_namespace_function_node ||
si.sym_info.semantic_node_type == semantic_node_type.namespace_constant_definition ||
si.sym_info.semantic_node_type == semantic_node_type.compiled_function_node ||
//si.sym_info.semantic_node_type == semantic_node_type.common_method_node || // SSM bug fix #167 - SSM 30.05.19 эта строчка не влияет на #167 и я её закомментировал
//si.sym_info.semantic_node_type == semantic_node_type.common_method_node || // SSM bug fix #1991 11.06.19 конкурирует с #891
si.sym_info.semantic_node_type == semantic_node_type.compiled_namespace_node ||
si.sym_info.semantic_node_type == semantic_node_type.compiled_variable_definition ||
si.sym_info.semantic_node_type == semantic_node_type.common_type_node ||
@ -212,6 +212,48 @@ namespace TreeConverter.LambdaExpressions.Closure
return;
}
}
if (si.sym_info.semantic_node_type == semantic_node_type.common_method_node && (si.sym_info as common_method_node).IsStatic)
{
// надо дописывать к идентификатору имя типа. Подниматься по синтаксическому дереву конечно долго ))
syntax_tree_node sn = id;
ident cname = null;
while (!(sn is procedure_definition) && sn != null) // Это если метод класса определен вне интерфейса класса
sn = sn.Parent;
if (sn != null)
{
var pd = sn as procedure_definition;
var ph = pd.proc_header;
if (ph.name.class_name != null)
{
cname = ph.name.class_name;
addressed_value id1 = null;
if (cname is template_type_name ttn)
{
var tpl = new template_param_list(ttn.template_args.idents.Select(l => SyntaxTreeBuilder.BuildSimpleType(l.name)).ToList(), ttn.template_args.source_context);
id1 = new ident_with_templateparams(new ident(ttn.name, ttn.source_context), tpl,ttn.source_context);
}
else id1 = new ident(cname.name, cname.source_context);
dot_node dn = new dot_node(id1, new ident(id.name, id.source_context), id.source_context);
id.Parent.ReplaceDescendantUnsafe(id, dn);
ProcessNode(id.Parent);
return;
}
}
while (!(sn is class_definition) && sn != null)
sn = sn.Parent;
if (sn != null)
{
var cd = sn as class_definition;
cname = (cd.Parent as type_declaration).type_name;
dot_node dn = new dot_node(new ident(cname.name, cname.source_context), new ident(id.name, id.source_context), id.source_context);
id.Parent.ReplaceDescendantUnsafe(id, dn);
ProcessNode(id.Parent);
}
return;
}
if (!(acceptableVarType) && InLambdaContext)
{
_visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id)));

View file

@ -1,19 +0,0 @@
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
<System.Windows.Forms.ApplicationConfigurationSection>
<add key="DpiAwareness" value="PerMonitorV2" />
<add key="EnableWindowsFormsHighDpiAutoResizing" value="true" />
</System.Windows.Forms.ApplicationConfigurationSection>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="ICSharpCode.NRefactory" publicKeyToken="EFE927ACF176EEA2" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.1.8805" newVersion="4.2.1.8805"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>