bug fix #891 - попытка номер два
This commit is contained in:
parent
99882270d0
commit
76f4020256
|
|
@ -15,7 +15,7 @@ internal static class RevisionClass
|
||||||
public const string Major = "3";
|
public const string Major = "3";
|
||||||
public const string Minor = "5";
|
public const string Minor = "5";
|
||||||
public const string Build = "0";
|
public const string Build = "0";
|
||||||
public const string Revision = "2098";
|
public const string Revision = "2102";
|
||||||
|
|
||||||
public const string MainVersion = Major + "." + Minor;
|
public const string MainVersion = Major + "." + Minor;
|
||||||
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
%COREVERSION%=0
|
%COREVERSION%=0
|
||||||
%REVISION%=2098
|
%REVISION%=2102
|
||||||
%MINOR%=5
|
%MINOR%=5
|
||||||
%MAJOR%=3
|
%MAJOR%=3
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
!define VERSION '3.5.0.2098'
|
!define VERSION '3.5.0.2102'
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ using PascalABCCompiler.SyntaxTree;
|
||||||
|
|
||||||
namespace PascalABCCompiler.SyntaxTreeConverters
|
namespace PascalABCCompiler.SyntaxTreeConverters
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Первое предназначение - вынести последовательность из заголовка в foreach до foreach как отдельное присваивание
|
||||||
|
// Второе предназначение - переименовать все переменные, совпадающие по имени с типом T обобщенного класса, в котором находится метод, содержащий лямбду
|
||||||
public class StandOutExprWithLambdaInForeachSequenceVisitor : BaseChangeVisitor
|
public class StandOutExprWithLambdaInForeachSequenceVisitor : BaseChangeVisitor
|
||||||
{
|
{
|
||||||
public static StandOutExprWithLambdaInForeachSequenceVisitor New
|
public static StandOutExprWithLambdaInForeachSequenceVisitor New
|
||||||
|
|
@ -18,12 +21,46 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GenIdNum = 0;
|
private int GenIdNum = 0;
|
||||||
|
//private int GenRenameIdNum = 0;
|
||||||
|
|
||||||
|
//private ident_list ClassTemplateArgsOrNull = null; // если мы - в обобщенном классе, то это - его обобщенные параметры
|
||||||
|
// надо бы еще то же сделать если метод описывается отдельно
|
||||||
public ident GenIdentName()
|
public ident GenIdentName()
|
||||||
{
|
{
|
||||||
GenIdNum++;
|
GenIdNum++;
|
||||||
return new ident("$GenContFE" + GenIdNum.ToString());
|
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)
|
public override void visit(foreach_stmt fe)
|
||||||
{
|
{
|
||||||
//if (fe.DescendantNodes().OfType<function_lambda_definition>().Count() > 0) // из-за #1984 убрал вообще условие. Пусть будет всегда
|
//if (fe.DescendantNodes().OfType<function_lambda_definition>().Count() > 0) // из-за #1984 убрал вообще условие. Пусть будет всегда
|
||||||
|
|
@ -40,4 +77,58 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
||||||
base.visit(fe);
|
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)
|
||||||
|
{
|
||||||
|
// параметры обойти отдельно, тело отдельно
|
||||||
|
// проблема, что могут быть вложенные лямбды. Т.е это - основная, а в ней - ещё.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
TestSuite/lambda_capture_local_and_proc_noparams_call-1.pas
Normal file
31
TestSuite/lambda_capture_local_and_proc_noparams_call-1.pas
Normal 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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
10
TestSuite/lambda_capture_static_methods.pas
Normal file
10
TestSuite/lambda_capture_static_methods.pas
Normal 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.
|
||||||
|
|
@ -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.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.namespace_constant_definition ||
|
||||||
si.sym_info.semantic_node_type == semantic_node_type.compiled_function_node ||
|
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_namespace_node ||
|
||||||
si.sym_info.semantic_node_type == semantic_node_type.compiled_variable_definition ||
|
si.sym_info.semantic_node_type == semantic_node_type.compiled_variable_definition ||
|
||||||
si.sym_info.semantic_node_type == semantic_node_type.common_type_node ||
|
si.sym_info.semantic_node_type == semantic_node_type.common_type_node ||
|
||||||
|
|
@ -212,6 +212,48 @@ namespace TreeConverter.LambdaExpressions.Closure
|
||||||
return;
|
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)
|
if (!(acceptableVarType) && InLambdaContext)
|
||||||
{
|
{
|
||||||
_visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id)));
|
_visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id)));
|
||||||
|
|
|
||||||
|
|
@ -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>
|
|
||||||
Loading…
Reference in a new issue