bug fix #1270
This commit is contained in:
parent
f1fce6b524
commit
e1d6336bee
|
|
@ -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 = "2106";
|
public const string Revision = "2110";
|
||||||
|
|
||||||
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%=2106
|
%REVISION%=2110
|
||||||
%MINOR%=5
|
%MINOR%=5
|
||||||
%MAJOR%=3
|
%MAJOR%=3
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
!define VERSION '3.5.0.2106'
|
!define VERSION '3.5.0.2110'
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@
|
||||||
<Compile Include="SugarVisitors\PatternsDesugaringVisitor.cs" />
|
<Compile Include="SugarVisitors\PatternsDesugaringVisitor.cs" />
|
||||||
<Compile Include="SugarVisitors\SliceDesugarVisitor.cs" />
|
<Compile Include="SugarVisitors\SliceDesugarVisitor.cs" />
|
||||||
<Compile Include="SugarVisitors\TupleVisitor.cs" />
|
<Compile Include="SugarVisitors\TupleVisitor.cs" />
|
||||||
|
<Compile Include="VisitorsForLambdas\RenameSameVarNamesVisitor.cs" />
|
||||||
<Compile Include="VisitorsForLambdas\StandOutExprWithLambdaInForeachSequenceVisitor.cs" />
|
<Compile Include="VisitorsForLambdas\StandOutExprWithLambdaInForeachSequenceVisitor.cs" />
|
||||||
<Compile Include="YieldVisitors\ObjectCopier\ObjectCopier.cs" />
|
<Compile Include="YieldVisitors\ObjectCopier\ObjectCopier.cs" />
|
||||||
<Compile Include="Optimization\CalcConstExprs.cs" />
|
<Compile Include="Optimization\CalcConstExprs.cs" />
|
||||||
|
|
|
||||||
181
SyntaxVisitors/VisitorsForLambdas/RenameSameVarNamesVisitor.cs
Normal file
181
SyntaxVisitors/VisitorsForLambdas/RenameSameVarNamesVisitor.cs
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
// Copyright (c) Ivan Bondarev, Stanislav Mihalkovich (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 PascalABCCompiler.SyntaxTree;
|
||||||
|
|
||||||
|
namespace PascalABCCompiler.SyntaxTreeConverters
|
||||||
|
{
|
||||||
|
|
||||||
|
// Первое предназначение - вынести последовательность из заголовка в foreach до foreach как отдельное присваивание
|
||||||
|
// Второе предназначение - переименовать все переменные, совпадающие по имени с типом T обобщенного класса, в котором находится метод, содержащий лямбду
|
||||||
|
public class VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer: CollectLightSymInfoVisitor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Надо приводить к нижнему регистру
|
||||||
|
/// </summary>
|
||||||
|
//public List<string> NamesForReplace = new List<string>();
|
||||||
|
|
||||||
|
private int LambdaNestedLevel = 0;
|
||||||
|
|
||||||
|
Dictionary<string, ScopeSyntax> d = new Dictionary<string, ScopeSyntax>(); // словарь скоупов для каждого имени
|
||||||
|
// При входе в обобщенный класс или запись мы в словарь добавляем все его обобщенные параметры со значением nil
|
||||||
|
// При выходе из класса мы очищаем словарь
|
||||||
|
// При встрече описания переменной с именем, совпадающим с одним из ключей в словаре, мы заменяем значение null на пространство имен, в котором мы находимся
|
||||||
|
// Описание переменной в словарь добавляется только если она описана в методе, но вне лямбды, поскольку в лямбде конфликтов имен нет
|
||||||
|
// При выходе из пространства имен мы проверяем, есть ли в словаре такое значение, и если да, очищаем его, присваивая null
|
||||||
|
// Переименовывать будем все имена name если ключ name есть в словаре и d[name] != null
|
||||||
|
public static new VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer New
|
||||||
|
{
|
||||||
|
get => new VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer();
|
||||||
|
}
|
||||||
|
public override void AddSymbol(ident name, SymKind kind, type_definition td = null, Attributes attr = 0)
|
||||||
|
{
|
||||||
|
if (name == null || name.name == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var n = name.name.ToLower();
|
||||||
|
//if (LambdaNestedLevel > 0) // т.е. впервые встретилось переопределение именно в лямбде, тогда пропускать эту лямбду
|
||||||
|
// return;
|
||||||
|
if (d.ContainsKey(n) && d[n] == null && (kind == SymKind.var || kind == SymKind.param)) // Добавляем не все, а только разыскиваемые и только если это - переменная
|
||||||
|
{
|
||||||
|
d[n] = this.Current;
|
||||||
|
base.AddSymbol(name, kind, td, attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void Enter(syntax_tree_node st)
|
||||||
|
{
|
||||||
|
base.Enter(st);
|
||||||
|
if (st is function_lambda_definition)
|
||||||
|
LambdaNestedLevel += 1;
|
||||||
|
else if (st is class_definition cl)
|
||||||
|
{
|
||||||
|
var td = cl.Parent as type_declaration;
|
||||||
|
if (td?.type_name is template_type_name ttn)
|
||||||
|
{
|
||||||
|
foreach (var id in ttn.template_args.idents)
|
||||||
|
{
|
||||||
|
d[id.name.ToLower()] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (st is procedure_definition pd)
|
||||||
|
{
|
||||||
|
var cn = pd.proc_header.name?.class_name;
|
||||||
|
if (cn is template_type_name ttn)
|
||||||
|
{
|
||||||
|
foreach (var id in ttn.template_args.idents)
|
||||||
|
{
|
||||||
|
d[id.name.ToLower()] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void PreExitScope(syntax_tree_node st)
|
||||||
|
{
|
||||||
|
var l = d.Keys.Where(k => d[k] == Current).ToList();
|
||||||
|
// Обходим все словари и смотрим у них вершину стеков
|
||||||
|
foreach (var k in l)
|
||||||
|
{
|
||||||
|
d[k] = null; // т.е. в этом пространстве имен мы захватили одноименное описание переменной - освобождаем его
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void Exit(syntax_tree_node st)
|
||||||
|
{
|
||||||
|
if (st is function_lambda_definition)
|
||||||
|
LambdaNestedLevel -= 1;
|
||||||
|
else if (st is class_definition) // то мы не ищем переопределение имен, поскольку мы вышли из класса
|
||||||
|
{
|
||||||
|
d.Clear();
|
||||||
|
}
|
||||||
|
else if (st is procedure_definition pd) // мы вышли из метода вида t1<t>.p
|
||||||
|
{
|
||||||
|
var cn = pd.proc_header.name?.class_name;
|
||||||
|
if (cn is template_type_name ttn)
|
||||||
|
d.Clear();
|
||||||
|
}
|
||||||
|
base.Exit(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void visit(template_type_name tn)
|
||||||
|
{
|
||||||
|
// игнорировать чтобы там ничего не переименовывалось
|
||||||
|
}
|
||||||
|
public override void visit(ident id)
|
||||||
|
{
|
||||||
|
ReplaceNameOrNot(id);
|
||||||
|
}
|
||||||
|
public override void visit(dot_node dn)
|
||||||
|
{
|
||||||
|
if (dn.left is ident id)
|
||||||
|
ReplaceNameOrNot(id);
|
||||||
|
else ProcessNode(dn.left);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int ReplaceNum = 0;
|
||||||
|
public void ReplaceNameOrNot(ident id)
|
||||||
|
{
|
||||||
|
var n = id.name.ToLower();
|
||||||
|
if (d.ContainsKey(n) && d[n] != null) // Переименовываем без страха
|
||||||
|
{
|
||||||
|
id.name = id.name + "$Replace$" + ReplaceNum; // имя такое чтобы при выдаче сообщения об ошибке в нем можно было бы обрезать конец
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Может, переименовать все 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)
|
||||||
|
{
|
||||||
|
// параметры обойти отдельно, тело отдельно
|
||||||
|
// проблема, что могут быть вложенные лямбды. Т.е это - основная, а в ней - ещё.
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
@ -45,174 +45,4 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
||||||
base.visit(fe);
|
base.visit(fe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer: CollectLightSymInfoVisitor
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Надо приводить к нижнему регистру
|
|
||||||
/// </summary>
|
|
||||||
//public List<string> NamesForReplace = new List<string>();
|
|
||||||
|
|
||||||
private int LambdaNestedLevel = 0;
|
|
||||||
|
|
||||||
Dictionary<string, ScopeSyntax> d = new Dictionary<string, ScopeSyntax>(); // словарь скоупов для каждого имени
|
|
||||||
// При входе в обобщенный класс или запись мы в словарь добавляем все его обобщенные параметры со значением nil
|
|
||||||
// При выходе из класса мы очищаем словарь
|
|
||||||
// При встрече описания переменной с именем, совпадающим с одним из ключей в словаре, мы заменяем значение null на пространство имен, в котором мы находимся
|
|
||||||
// Описание переменной в словарь добавляется только если она описана в методе, но вне лямбды, поскольку в лямбде конфликтов имен нет
|
|
||||||
// При выходе из пространства имен мы проверяем, есть ли в словаре такое значение, и если да, очищаем его, присваивая null
|
|
||||||
// Переименовывать будем все имена name если ключ name есть в словаре и d[name] != null
|
|
||||||
public static new VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer New
|
|
||||||
{
|
|
||||||
get => new VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer();
|
|
||||||
}
|
|
||||||
public override void AddSymbol(ident name, SymKind kind, type_definition td = null, Attributes attr = 0)
|
|
||||||
{
|
|
||||||
if (name == null || name.name == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var n = name.name.ToLower();
|
|
||||||
//if (LambdaNestedLevel > 0) // т.е. впервые встретилось переопределение именно в лямбде, тогда пропускать эту лямбду
|
|
||||||
// return;
|
|
||||||
if (d.ContainsKey(n) && d[n] == null && (kind == SymKind.var || kind == SymKind.param)) // Добавляем не все, а только разыскиваемые и только если это - переменная
|
|
||||||
{
|
|
||||||
d[n] = this.Current;
|
|
||||||
base.AddSymbol(name, kind, td, attr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override void Enter(syntax_tree_node st)
|
|
||||||
{
|
|
||||||
base.Enter(st);
|
|
||||||
if (st is function_lambda_definition)
|
|
||||||
LambdaNestedLevel += 1;
|
|
||||||
else if (st is class_definition cl)
|
|
||||||
{
|
|
||||||
var td = cl.Parent as type_declaration;
|
|
||||||
if (td?.type_name is template_type_name ttn)
|
|
||||||
{
|
|
||||||
foreach (var id in ttn.template_args.idents)
|
|
||||||
{
|
|
||||||
d[id.name.ToLower()] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (st is procedure_definition pd)
|
|
||||||
{
|
|
||||||
var cn = pd.proc_header.name?.class_name;
|
|
||||||
if (cn is template_type_name ttn)
|
|
||||||
{
|
|
||||||
foreach (var id in ttn.template_args.idents)
|
|
||||||
{
|
|
||||||
d[id.name.ToLower()] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override void PreExitScope(syntax_tree_node st)
|
|
||||||
{
|
|
||||||
var l = d.Keys.Where(k => d[k] == Current).ToList();
|
|
||||||
// Обходим все словари и смотрим у них вершину стеков
|
|
||||||
foreach (var k in l)
|
|
||||||
{
|
|
||||||
d[k] = null; // т.е. в этом пространстве имен мы захватили одноименное описание переменной - освобождаем его
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override void Exit(syntax_tree_node st)
|
|
||||||
{
|
|
||||||
if (st is function_lambda_definition)
|
|
||||||
LambdaNestedLevel -= 1;
|
|
||||||
else if (st is class_definition) // то мы не ищем переопределение имен, поскольку мы вышли из класса
|
|
||||||
{
|
|
||||||
d.Clear();
|
|
||||||
}
|
|
||||||
else if (st is procedure_definition pd) // мы вышли из метода вида t1<t>.p
|
|
||||||
{
|
|
||||||
var cn = pd.proc_header.name?.class_name;
|
|
||||||
if (cn is template_type_name ttn)
|
|
||||||
d.Clear();
|
|
||||||
}
|
|
||||||
base.Exit(st);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void visit(template_type_name tn)
|
|
||||||
{
|
|
||||||
// игнорировать чтобы там ничего не переименовывалось
|
|
||||||
}
|
|
||||||
public override void visit(ident id)
|
|
||||||
{
|
|
||||||
ReplaceNameOrNot(id);
|
|
||||||
}
|
|
||||||
public override void visit(dot_node dn)
|
|
||||||
{
|
|
||||||
if (dn.left is ident id)
|
|
||||||
ReplaceNameOrNot(id);
|
|
||||||
else ProcessNode(dn.left);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int ReplaceNum = 0;
|
|
||||||
public void ReplaceNameOrNot(ident id)
|
|
||||||
{
|
|
||||||
var n = id.name.ToLower();
|
|
||||||
if (d.ContainsKey(n) && d[n] != null) // Переименовываем без страха
|
|
||||||
{
|
|
||||||
id.name = id.name + "$Replace$" + ReplaceNum; // имя такое чтобы при выдаче сообщения об ошибке в нем можно было бы обрезать конец
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Может, переименовать все 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)
|
|
||||||
{
|
|
||||||
// параметры обойти отдельно, тело отдельно
|
|
||||||
// проблема, что могут быть вложенные лямбды. Т.е это - основная, а в ней - ещё.
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
9
TestSuite/lambda_nested1.pas
Normal file
9
TestSuite/lambda_nested1.pas
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
begin
|
||||||
|
var s: sequence of integer := Seq(1,2);
|
||||||
|
|
||||||
|
Assert(s.SelectMany(
|
||||||
|
t1->
|
||||||
|
s.Select(t2->t1+t2).Where(t->true)
|
||||||
|
).First = 2)
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
@ -2739,6 +2739,16 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
lambdaProcessingState = LambdaProcessingState.TypeInferencePhase;
|
lambdaProcessingState = LambdaProcessingState.TypeInferencePhase;
|
||||||
visit_program_code(_block.program_code);
|
visit_program_code(_block.program_code);
|
||||||
|
|
||||||
|
// Грубо - удаление мусора при разборе лямбд. Происходит исключение - заголовок разбирается, тело остается пустым - и из-за этого была ошибка #1270.
|
||||||
|
while (context._cmn.functions.Count > 0 && context._cmn.functions[context._cmn.functions.Count-1].function_code == null && context._cmn.functions[context._cmn.functions.Count - 1].name.StartsWith("<>lambda") && !context._cmn.functions[context._cmn.functions.Count - 1].name.StartsWith("<>lambda_initializer"))
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
System.IO.File.AppendAllText("d:\\aa.txt", context._cmn.functions[context._cmn.functions.Count - 1].name+"\n");
|
||||||
|
#endif
|
||||||
|
context._cmn.functions.remove_at(context._cmn.functions.Count - 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
lambdaProcessingState = LambdaProcessingState.ClosuresProcessingPhase;
|
lambdaProcessingState = LambdaProcessingState.ClosuresProcessingPhase;
|
||||||
CapturedVariablesSubstitutionsManager.Substitute(this, _block.defs, _block.program_code);
|
CapturedVariablesSubstitutionsManager.Substitute(this, _block.defs, _block.program_code);
|
||||||
|
|
||||||
|
|
@ -19397,6 +19407,47 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public expression ProcedureForLambdaAndVisit(function_lambda_definition lambdaDefinition, ident_list tempParsList, where_definition_list whereSection)
|
||||||
|
{
|
||||||
|
var procDecl = LambdaHelper.ConvertLambdaNodeToProcDefNode(lambdaDefinition);
|
||||||
|
|
||||||
|
if (tempParsList != null)
|
||||||
|
{
|
||||||
|
procDecl.proc_header.template_args = tempParsList;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (whereSection != null && whereSection.defs != null && whereSection.defs.Count != 0)
|
||||||
|
{
|
||||||
|
procDecl.proc_header.where_defs = whereSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!context.func_stack.Empty && context.func_stack.top().polymorphic_state == SemanticTree.polymorphic_state.ps_static
|
||||||
|
|| context.converted_type != null && context.converted_type.IsStatic)
|
||||||
|
{
|
||||||
|
procDecl.proc_header.class_keyword = true;
|
||||||
|
if (procDecl.proc_header.proc_attributes == null)
|
||||||
|
procDecl.proc_header.proc_attributes = new SyntaxTree.procedure_attributes_list();
|
||||||
|
procDecl.proc_header.proc_attributes.proc_attributes.Add(new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static));
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
visit(procDecl);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
context.remove_lambda_function(procDecl.proc_header.name.meth_name.name, true);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.remove_lambda_function(procDecl.proc_header.name.meth_name.name, false);
|
||||||
|
|
||||||
|
return tempParsList == null ?
|
||||||
|
(expression)procDecl.proc_header.name.meth_name :
|
||||||
|
(expression)new ident_with_templateparams(procDecl.proc_header.name.meth_name, new template_param_list(tempParsList.idents.Select(l => SyntaxTreeBuilder.BuildSimpleType(l.name)).ToList()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int ccc = 0;
|
int ccc = 0;
|
||||||
public override void visit(SyntaxTree.function_lambda_definition _function_lambda_definition)
|
public override void visit(SyntaxTree.function_lambda_definition _function_lambda_definition)
|
||||||
{
|
{
|
||||||
|
|
@ -19432,47 +19483,7 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Func<function_lambda_definition, ident_list, where_definition_list, expression> makeProcedureForLambdaAndVisit =
|
Func<function_lambda_definition, ident_list, where_definition_list, expression> makeProcedureForLambdaAndVisit = ProcedureForLambdaAndVisit;
|
||||||
(lambdaDefinition, tempParsList, whereSection) =>
|
|
||||||
{
|
|
||||||
var procDecl = LambdaHelper.ConvertLambdaNodeToProcDefNode(lambdaDefinition);
|
|
||||||
|
|
||||||
if (tempParsList != null)
|
|
||||||
{
|
|
||||||
procDecl.proc_header.template_args = tempParsList;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (whereSection != null && whereSection.defs != null && whereSection.defs.Count != 0)
|
|
||||||
{
|
|
||||||
procDecl.proc_header.where_defs = whereSection;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!context.func_stack.Empty && context.func_stack.top().polymorphic_state == SemanticTree.polymorphic_state.ps_static
|
|
||||||
|| context.converted_type != null && context.converted_type.IsStatic)
|
|
||||||
{
|
|
||||||
procDecl.proc_header.class_keyword = true;
|
|
||||||
if (procDecl.proc_header.proc_attributes == null)
|
|
||||||
procDecl.proc_header.proc_attributes = new SyntaxTree.procedure_attributes_list();
|
|
||||||
procDecl.proc_header.proc_attributes.proc_attributes.Add(new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static));
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
visit(procDecl);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
context.remove_lambda_function(procDecl.proc_header.name.meth_name.name, true);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
context.remove_lambda_function(procDecl.proc_header.name.meth_name.name, false);
|
|
||||||
|
|
||||||
return tempParsList == null ?
|
|
||||||
(expression)procDecl.proc_header.name.meth_name :
|
|
||||||
(expression)new ident_with_templateparams(procDecl.proc_header.name.meth_name, new template_param_list(tempParsList.idents.Select(l => SyntaxTreeBuilder.BuildSimpleType(l.name)).ToList()));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
switch (lambdaProcessingState)
|
switch (lambdaProcessingState)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue