Вложенные лямбды
This commit is contained in:
parent
1872434f19
commit
1b61879a42
18
TestSuite/nested_lambdas_1.pas
Normal file
18
TestSuite/nested_lambdas_1.pas
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
procedure p(f: Func<string, IEnumerable<string>>);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
procedure p(f: Func<integer, IEnumerable<integer>>);
|
||||
begin
|
||||
var res := f(3).ToList();
|
||||
assert(res.Count = 4);
|
||||
assert(res[0] = 0);
|
||||
assert(res[1] = 1);
|
||||
assert(res[2] = 4);
|
||||
assert(res[3] = 9);
|
||||
end;
|
||||
|
||||
begin
|
||||
p(x -> Range(0, x).Select(y -> y * y));
|
||||
end.
|
||||
14
TestSuite/nested_lambdas_2.pas
Normal file
14
TestSuite/nested_lambdas_2.pas
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
procedure p(f: Func<integer, IEnumerable<integer>>);
|
||||
begin
|
||||
var res := f(5).ToList();
|
||||
assert(res.Count = 5);
|
||||
assert(res[0] = 2);
|
||||
assert(res[1] = 3);
|
||||
assert(res[2] = 4);
|
||||
assert(res[3] = 5);
|
||||
assert(res[4] = 6);
|
||||
end;
|
||||
|
||||
begin
|
||||
p(x -> Seq(1,2,3,4,5).Select(y -> Range(0, y).Select(z -> z).Count()));
|
||||
end.
|
||||
27
TestSuite/nested_lambdas_3.pas
Normal file
27
TestSuite/nested_lambdas_3.pas
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
type cl = class
|
||||
public
|
||||
procedure p(f: Func<string, IEnumerable<string>>);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
procedure p(f: Func<integer, IEnumerable<integer>>);
|
||||
begin
|
||||
var res := f(3).ToList();
|
||||
assert(res.Count = 4);
|
||||
assert(res[0] = 0);
|
||||
assert(res[1] = 1);
|
||||
assert(res[2] = 4);
|
||||
assert(res[3] = 9);
|
||||
end;
|
||||
|
||||
procedure tt();
|
||||
begin
|
||||
p(x -> Range(0, x).Select(y -> y * y));
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
(new cl()).p(x -> Range(0, x).Select(y -> y * y));
|
||||
(new cl()).tt();
|
||||
end.
|
||||
22
TestSuite/nested_lambdas_4.pas
Normal file
22
TestSuite/nested_lambdas_4.pas
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
type cl = class
|
||||
public
|
||||
constructor(f: Func<string, IEnumerable<string>>);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
constructor (f: Func<integer, IEnumerable<integer>>);
|
||||
begin
|
||||
var res := f(3).ToList();
|
||||
assert(res.Count = 4);
|
||||
assert(res[0] = 0);
|
||||
assert(res[1] = 1);
|
||||
assert(res[2] = 4);
|
||||
assert(res[3] = 9);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
begin
|
||||
new cl(x -> Range(0, x).Select(y -> y * y));
|
||||
end.
|
||||
12
TestSuite/nested_lambdas_5.pas
Normal file
12
TestSuite/nested_lambdas_5.pas
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
begin
|
||||
var a := 3;
|
||||
var ttt := Seq(1,2).Select(x -> begin
|
||||
var t := 5;
|
||||
result := Range(1,a+x).Select(y -> begin
|
||||
var g := 5;
|
||||
t += 5;
|
||||
result := Range(1,2).Where(f -> f + a > 0).Select(z -> z + g + t);
|
||||
end)
|
||||
end).ToList();
|
||||
assert(ttt[0].ToList()[0].ToList()[0] = 31);
|
||||
end.
|
||||
20
TestSuite/nested_lambdas_6.pas
Normal file
20
TestSuite/nested_lambdas_6.pas
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
type cl = class
|
||||
private gg := 9;
|
||||
public
|
||||
procedure h(k: integer);
|
||||
begin
|
||||
var a := 5;
|
||||
Seq(1,2,3).Select(x -> begin
|
||||
var t := 5;
|
||||
result := Range(1,a).Select(y -> begin
|
||||
var g := 5;
|
||||
writeln(a);
|
||||
result := Range(1,3).Where(f -> f + a > 0).Select(z -> z + g + t);
|
||||
end)
|
||||
end);
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
(new cl).h(6);
|
||||
end.
|
||||
20
TestSuite/nested_lambdas_7.pas
Normal file
20
TestSuite/nested_lambdas_7.pas
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
type cl = class
|
||||
protected gg:integer := 9;
|
||||
public
|
||||
function h(k: integer):string;
|
||||
begin
|
||||
var a := 5;
|
||||
foreach var tt in Seq(1,2,3) do
|
||||
begin
|
||||
var d := Seq(1,2,3).Select(x -> begin
|
||||
var e := 65;
|
||||
result := e + x + tt + self.gg + Range(1,2).Select(y -> gg + self.gg+y+a + tt).First()
|
||||
end).ToList();
|
||||
assert(d[0] = 100 + (tt * 2 - 1));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
(new cl).h(5);
|
||||
end.
|
||||
15
TestSuite/nested_lambdas_8.pas
Normal file
15
TestSuite/nested_lambdas_8.pas
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
begin
|
||||
var yy := 5;
|
||||
Range(1,1).Select(x -> begin
|
||||
var l := x + yy; //6
|
||||
begin
|
||||
writeln(l);
|
||||
begin
|
||||
writeln(l);
|
||||
end;
|
||||
end;
|
||||
writeln(yy);
|
||||
result := Range(1, x).Select(y -> y + l + yy + Seq(1,2).Select(z -> l + yy).First())
|
||||
end);
|
||||
writeln(yy);
|
||||
end.
|
||||
13
TestSuite/nested_lambdas_9.pas
Normal file
13
TestSuite/nested_lambdas_9.pas
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
procedure p<T>(aa: T); where T: class;
|
||||
begin
|
||||
var a := Seq(1,2,3).Select(x -> begin
|
||||
var tt := new List<T>();
|
||||
writeln(aa);
|
||||
tt.Add(aa);
|
||||
result := tt.Select(y -> begin result := aa; writeln(aa) end).ToList()
|
||||
end).ToList();
|
||||
end;
|
||||
|
||||
begin
|
||||
p('sss');
|
||||
end.
|
||||
|
|
@ -20,7 +20,8 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
private static int _generatedClassCounter;
|
||||
private static int _generatedUpperClassCounter;
|
||||
private readonly Dictionary<SubstitutionKey, dot_node> _substitutions;
|
||||
|
||||
private readonly List<LambdaReferencesSubstitutionInfo> _lambdaIdReferences = new List<LambdaReferencesSubstitutionInfo>();
|
||||
private readonly List<RewriteReferencesForNodesThatAreChildNodesToThoseThatContainCapturedVariableInfo> _rewriteReferencesForNodesThatAreChildNodesToThoseThatContainCapturedVariableInfo = new List<RewriteReferencesForNodesThatAreChildNodesToThoseThatContainCapturedVariableInfo>();
|
||||
public static void Reset()
|
||||
{
|
||||
_generatedClassCounter = 0;
|
||||
|
|
@ -58,6 +59,8 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
private const string GeneratedSubstitutingFieldPrefix = "<>local_variables_"; //это поле для того, чтобы заменять в текущем блоке, где захватывались переменные, левую часть dot_node
|
||||
private static int _generatedSubstitutingFieldCounter;
|
||||
|
||||
public List<CapturedVariablesTreeNodeLambdaScope> NestedLambdas { get; set; }
|
||||
|
||||
public syntax_tree_node CorrespondingSyntaxTreeNode
|
||||
{
|
||||
get;
|
||||
|
|
@ -129,9 +132,25 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
ClassDeclaration = classDeclaration;
|
||||
_generatedSubstitutingFieldName = generatedSubstitutingFieldName;
|
||||
CorrespondingTreeNode = correspondingTreeNode;
|
||||
NestedLambdas = new List<CapturedVariablesTreeNodeLambdaScope>();
|
||||
}
|
||||
}
|
||||
|
||||
private class LambdaReferencesSubstitutionInfo
|
||||
{
|
||||
public CapturedVariablesTreeNodeLambdaScope LambdaScope { get; set; }
|
||||
public string VarName { get; set; }
|
||||
public syntax_tree_node SyntaxTreeNodeWithVarDeclaration { get; set; }
|
||||
public dot_node DotNode { get; set; }
|
||||
}
|
||||
|
||||
private class RewriteReferencesForNodesThatAreChildNodesToThoseThatContainCapturedVariableInfo
|
||||
{
|
||||
public CapturedVariablesTreeNode TreeNode { get; set; }
|
||||
public string Varname { get; set; }
|
||||
public syntax_tree_node NodeWithVarDecl { get; set; }
|
||||
}
|
||||
|
||||
public CapturedVariablesSubstitutionClassGenerator(CapturedVariablesTreeNode capturedVariablesRootTreeNode)
|
||||
{
|
||||
_capturedVariablesRootTreeNode = capturedVariablesRootTreeNode;
|
||||
|
|
@ -150,21 +169,27 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
|
||||
private void VisitCapturedVar(CapturedVariablesTreeNode scope, CapturedVariablesTreeNode.CapturedSymbolInfo symbolInfo)
|
||||
{
|
||||
var varName = ((IVAriableDefinitionNode)symbolInfo.SymbolInfo.sym_info).name.ToLower(); //TODO: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
var varName = ((IVAriableDefinitionNode)symbolInfo.SymbolInfo.sym_info).name.ToLower();
|
||||
var isSelfWordInClass = scope is CapturedVariablesTreeNodeClassScope && varName == compiler_string_consts.self_word;
|
||||
|
||||
for (var k = 0; k < symbolInfo.ReferencingLambdas.Count; k++)
|
||||
foreach (var referencingLambda in symbolInfo.ReferencingLambdas.OrderByDescending(rl => rl.ScopeIndex))
|
||||
{
|
||||
var referencingLambda = symbolInfo.ReferencingLambdas[k];
|
||||
if (scope != referencingLambda.ParentNode)
|
||||
{
|
||||
var upperScopesStack = new Stack<CapturedVariablesTreeNode>();
|
||||
var crawlUpScope = referencingLambda.ParentNode;
|
||||
var anotherLambdaIsOnTheWay = crawlUpScope is CapturedVariablesTreeNodeLambdaScope;
|
||||
|
||||
while (crawlUpScope != scope)
|
||||
while (crawlUpScope != null && crawlUpScope != scope && !anotherLambdaIsOnTheWay)
|
||||
{
|
||||
upperScopesStack.Push(crawlUpScope);
|
||||
crawlUpScope = crawlUpScope.ParentNode;
|
||||
anotherLambdaIsOnTheWay = crawlUpScope is CapturedVariablesTreeNodeLambdaScope;
|
||||
}
|
||||
|
||||
if (anotherLambdaIsOnTheWay || crawlUpScope == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var upperScopeWhereVarsAreCaptured = scope;
|
||||
|
|
@ -352,7 +377,6 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
}
|
||||
}
|
||||
|
||||
//TODO: Nested Lambdas
|
||||
if (!(upperScopeWhereVarsAreCaptured == scope &&
|
||||
upperScopeWhereVarsAreCaptured is CapturedVariablesTreeNodeClassScope))
|
||||
{
|
||||
|
|
@ -403,8 +427,27 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
dotnode1 = new dot_node(dotnode1, new ident(varName));
|
||||
}
|
||||
}
|
||||
AddReferencesToIdentInLambda(referencingLambda.ChildNodes[0], varName,
|
||||
symbolInfo.SyntaxTreeNodeWithVarDeclaration, dotnode1);
|
||||
_lambdaIdReferences.Add(new LambdaReferencesSubstitutionInfo
|
||||
{
|
||||
LambdaScope = referencingLambda,
|
||||
VarName = varName,
|
||||
SyntaxTreeNodeWithVarDeclaration = symbolInfo.SyntaxTreeNodeWithVarDeclaration,
|
||||
DotNode = dotnode1
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
var dotnode1 = new dot_node(
|
||||
new ident(compiler_string_consts.self_word),
|
||||
new ident(varName));
|
||||
|
||||
_lambdaIdReferences.Add(new LambdaReferencesSubstitutionInfo
|
||||
{
|
||||
LambdaScope = referencingLambda,
|
||||
VarName = varName,
|
||||
SyntaxTreeNodeWithVarDeclaration = symbolInfo.SyntaxTreeNodeWithVarDeclaration,
|
||||
DotNode = dotnode1
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!referencingLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.HasValue ||
|
||||
|
|
@ -454,6 +497,18 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
}
|
||||
}
|
||||
|
||||
var dotnode1 = new dot_node(
|
||||
new ident(compiler_string_consts.self_word),
|
||||
new ident(varName));
|
||||
|
||||
_lambdaIdReferences.Add(new LambdaReferencesSubstitutionInfo
|
||||
{
|
||||
LambdaScope = referencingLambda,
|
||||
VarName = varName,
|
||||
SyntaxTreeNodeWithVarDeclaration = symbolInfo.SyntaxTreeNodeWithVarDeclaration,
|
||||
DotNode = dotnode1
|
||||
});
|
||||
|
||||
if (!referencingLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.HasValue ||
|
||||
scope.ScopeIndex > referencingLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod)
|
||||
{
|
||||
|
|
@ -468,24 +523,93 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
}
|
||||
}
|
||||
|
||||
private void AddReferencesToIdentInLambda(CapturedVariablesTreeNode scope, string varName, syntax_tree_node syntaxTreeNodeWithVarDeclaration, dot_node substDotNode)
|
||||
private void AddReferencesToIdentInLambda(type_declaration upperScopeWhereVarsAreCapturedClass, CapturedVariablesTreeNode scope, string varName, syntax_tree_node syntaxTreeNodeWithVarDeclaration, dot_node substDotNode, bool nestedLambda)
|
||||
{
|
||||
//TODO: Nested Lambdas
|
||||
|
||||
for (var i = 0; i < scope.ChildNodes.Count; i++)
|
||||
{
|
||||
if (!(scope.ChildNodes[i] is CapturedVariablesTreeNodeLambdaScope)) // Вложенные лямбды пока не рассматриваем
|
||||
if (!(scope.ChildNodes[i] is CapturedVariablesTreeNodeLambdaScope))
|
||||
{
|
||||
var substKey = new SubstitutionKey(varName, syntaxTreeNodeWithVarDeclaration,
|
||||
scope.ChildNodes[i].CorrespondingSyntaxTreeNode);
|
||||
|
||||
if (_capturedVarsClassDefs.ContainsKey(scope.ChildNodes[i].ScopeIndex))
|
||||
{
|
||||
var cl = _capturedVarsClassDefs[scope.ChildNodes[i].ScopeIndex];
|
||||
if (cl.AssignNodeForUpperClassFieldInitialization == null)
|
||||
{
|
||||
var fieldType =
|
||||
SyntaxTreeBuilder.BuildSimpleType(upperScopeWhereVarsAreCapturedClass.type_name.name);
|
||||
var field =
|
||||
SyntaxTreeBuilder.BuildClassFieldsSection(
|
||||
new List<ident>
|
||||
{
|
||||
new ident(cl.GeneratedUpperClassFieldName)
|
||||
},
|
||||
new List<type_definition> { fieldType });
|
||||
|
||||
var clClass = (class_definition) cl.ClassDeclaration.type_def;
|
||||
clClass.body.Add(field);
|
||||
|
||||
cl.AssignNodeForUpperClassFieldInitialization =
|
||||
new assign(
|
||||
new dot_node(new ident(cl.GeneratedSubstitutingFieldName),new ident(cl.GeneratedUpperClassFieldName)),
|
||||
new ident(compiler_string_consts.self_word));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!_substitutions.ContainsKey(substKey))
|
||||
{
|
||||
_substitutions.Add(substKey, substDotNode);
|
||||
}
|
||||
|
||||
AddReferencesToIdentInLambda(scope.ChildNodes[i], varName, syntaxTreeNodeWithVarDeclaration,
|
||||
substDotNode);
|
||||
AddReferencesToIdentInLambda(upperScopeWhereVarsAreCapturedClass, scope.ChildNodes[i], varName, syntaxTreeNodeWithVarDeclaration, substDotNode, nestedLambda);
|
||||
}
|
||||
else
|
||||
{
|
||||
var scopeAsLambda = scope.ChildNodes[i] as CapturedVariablesTreeNodeLambdaScope;
|
||||
if (scopeAsLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.HasValue)
|
||||
{
|
||||
dot_node substDotNode1;
|
||||
if (!nestedLambda)
|
||||
{
|
||||
substDotNode1 = new dot_node(new ident(_capturedVarsClassDefs[scopeAsLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.Value].GeneratedUpperClassFieldName), new ident(varName));
|
||||
}
|
||||
else
|
||||
{
|
||||
var parts = new Stack<ident>();
|
||||
var dn = substDotNode;
|
||||
parts.Push((ident)dn.right);
|
||||
|
||||
while (!(dn.left is ident && dn.right is ident))
|
||||
{
|
||||
dn = (dot_node)dn.left;
|
||||
parts.Push((ident)dn.right);
|
||||
}
|
||||
|
||||
parts.Push((ident)dn.left);
|
||||
|
||||
substDotNode1 = new dot_node(new ident(_capturedVarsClassDefs[scopeAsLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.Value].GeneratedUpperClassFieldName), parts.Pop());
|
||||
|
||||
while (parts.Count > 0)
|
||||
{
|
||||
substDotNode1 = new dot_node(substDotNode, parts.Pop());
|
||||
}
|
||||
}
|
||||
|
||||
var substKey = new SubstitutionKey(varName, syntaxTreeNodeWithVarDeclaration,
|
||||
scope.ChildNodes[0].CorrespondingSyntaxTreeNode);
|
||||
if (!_substitutions.ContainsKey(substKey))
|
||||
{
|
||||
_substitutions.Add(substKey, substDotNode1);
|
||||
}
|
||||
|
||||
AddReferencesToIdentInLambda(_capturedVarsClassDefs[scopeAsLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.Value].ClassDeclaration, scopeAsLambda.ChildNodes[0], varName, syntaxTreeNodeWithVarDeclaration, substDotNode1, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddReferencesToIdentInLambda(upperScopeWhereVarsAreCapturedClass, scope.ChildNodes[0], varName, syntaxTreeNodeWithVarDeclaration, substDotNode, nestedLambda);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -524,7 +648,6 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
currentNode));
|
||||
}
|
||||
|
||||
// TODO: тут предусматривать разные случаи
|
||||
|
||||
var vars = variablesFromThisScopeWhichWereCaptured
|
||||
.Select(field => field.SymbolInfo.sym_info as IVAriableDefinitionNode)
|
||||
|
|
@ -571,7 +694,6 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
|
||||
if (variablesFromThisScopeWhichWereCaptured.Count > 0)
|
||||
{
|
||||
// TODO: тут предусматривать разные случаи
|
||||
var vars = variablesFromThisScopeWhichWereCaptured
|
||||
.Select(x =>
|
||||
new
|
||||
|
|
@ -586,7 +708,13 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
{
|
||||
foreach (CapturedVariablesTreeNode childNode in currentNode.ChildNodes)
|
||||
{
|
||||
RewriteReferencesForNodesThatAreChildNodesToThoseThatContainCapturedVariable(childNode, var.IVarDefinitionNode.name, var.VarDeclNode);
|
||||
_rewriteReferencesForNodesThatAreChildNodesToThoseThatContainCapturedVariableInfo.Add(
|
||||
new RewriteReferencesForNodesThatAreChildNodesToThoseThatContainCapturedVariableInfo
|
||||
{
|
||||
TreeNode = childNode,
|
||||
Varname = var.IVarDefinitionNode.name,
|
||||
NodeWithVarDecl = var.VarDeclNode
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -594,9 +722,15 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
|
||||
private void RewriteReferencesForNodesThatAreChildNodesToThoseThatContainCapturedVariable(CapturedVariablesTreeNode node, string varName, syntax_tree_node nodeWithVarDecl)
|
||||
{
|
||||
if (node is CapturedVariablesTreeNodeLambdaScope)
|
||||
{
|
||||
RewriteReferencesForNodesThatAreChildNodesToThoseThatContainCapturedVariable(node.ChildNodes[0], varName, nodeWithVarDecl);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(node is CapturedVariablesTreeNodeBlockScope ||
|
||||
node is CapturedVariablesTreeNodeForScope ||
|
||||
node is CapturedVariablesTreeNodeForEachScope)) // Добавляем ссылки только для скоупов-блоков и циклов, потому что остальные случаи должны были уже быть рассмотрены (когда эти случаи буду реализованы)
|
||||
node is CapturedVariablesTreeNodeForEachScope))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -637,6 +771,17 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
{
|
||||
VisitTreeAndBuildClassDefinitions(_capturedVariablesRootTreeNode);
|
||||
|
||||
foreach (var ls in _lambdaIdReferences.Where(x => x.LambdaScope.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.HasValue))
|
||||
{
|
||||
AddReferencesToIdentInLambda(_capturedVarsClassDefs[ls.LambdaScope.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.Value].ClassDeclaration,
|
||||
ls.LambdaScope.ChildNodes[0], ls.VarName, ls.SyntaxTreeNodeWithVarDeclaration, ls.DotNode, false);
|
||||
}
|
||||
|
||||
foreach (var r in _rewriteReferencesForNodesThatAreChildNodesToThoseThatContainCapturedVariableInfo)
|
||||
{
|
||||
RewriteReferencesForNodesThatAreChildNodesToThoseThatContainCapturedVariable(r.TreeNode, r.Varname, r.NodeWithVarDecl);
|
||||
}
|
||||
|
||||
return new VariableSubstitutionsInfo
|
||||
{
|
||||
GeneratedScopeClassesInfo = _capturedVarsClassDefs,
|
||||
|
|
|
|||
|
|
@ -232,6 +232,34 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
SubstituteInNode(currentBlock, node);
|
||||
}
|
||||
|
||||
private List<CapturedVariablesTreeNodeLambdaScope> GetNestedLambdasToBeAddedToThisClass(CapturedVariablesTreeNode scope)
|
||||
{
|
||||
var res = new List<CapturedVariablesTreeNodeLambdaScope>();
|
||||
|
||||
foreach (var child in scope.ChildNodes)
|
||||
{
|
||||
var childAsLambda = child as CapturedVariablesTreeNodeLambdaScope;
|
||||
if (childAsLambda == null)
|
||||
{
|
||||
res.AddRange(GetNestedLambdasToBeAddedToThisClass(child));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (childAsLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.HasValue)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
res.Add(childAsLambda);
|
||||
res.AddRange(GetNestedLambdasToBeAddedToThisClass(childAsLambda));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private void SubstituteLambdas()
|
||||
{
|
||||
for (var i = 0; i < _lambdasToBeAddedAsMethods.Count; i++)
|
||||
|
|
@ -245,15 +273,24 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
continue;
|
||||
}
|
||||
|
||||
var otherLambdasToBeAddedAsMethods =
|
||||
GetNestedLambdasToBeAddedToThisClass(_lambdasToBeAddedAsMethods[i]);
|
||||
classDef.NestedLambdas.AddRange(otherLambdasToBeAddedAsMethods);
|
||||
|
||||
foreach (var oltaam in otherLambdasToBeAddedAsMethods)
|
||||
{
|
||||
oltaam.LambdaDefinition.substituting_node = new ident(oltaam.LambdaDefinition.lambda_name);
|
||||
}
|
||||
|
||||
var left = new ident(classDef.GeneratedSubstitutingFieldName);
|
||||
|
||||
var lambdaDef = _lambdasToBeAddedAsMethods[i].LambdaDefinition;
|
||||
lambdaDef.substituting_node = new dot_node(left, new ident(lambdaDef.lambda_name));
|
||||
|
||||
var classDecl = (class_definition)classDef.ClassDeclaration.type_def;
|
||||
/*var classDecl = (class_definition)classDef.ClassDeclaration.type_def;
|
||||
var procDecl = LambdaHelper.ConvertLambdaNodeToProcDefNode(lambdaDef);
|
||||
|
||||
classDecl.body.Add(SyntaxTreeBuilder.BuildOneMemberSection(procDecl));
|
||||
classDecl.body.Add(SyntaxTreeBuilder.BuildOneMemberSection(procDecl));*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -370,6 +407,44 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
}
|
||||
}
|
||||
|
||||
private void SubstituteLambdaParameters()
|
||||
{
|
||||
var lambdaScopes =
|
||||
_capturedVarsTreeNodesDictionary.Where(n => n.Value is CapturedVariablesTreeNodeLambdaScope)
|
||||
.Select(n => (CapturedVariablesTreeNodeLambdaScope)n.Value)
|
||||
.ToList();
|
||||
|
||||
foreach (var lambdaScope in lambdaScopes)
|
||||
{
|
||||
CapturedVariablesSubstitutionClassGenerator.ScopeClassDefinition generatedClass;
|
||||
if (_generatedScopeClassesInfo.TryGetValue(lambdaScope.ScopeIndex, out generatedClass))
|
||||
{
|
||||
|
||||
var nodesToAdd = new List<statement>();
|
||||
nodesToAdd.Add(generatedClass.GeneratedVarStatementForScope);
|
||||
if (generatedClass.AssignNodeForUpperClassFieldInitialization != null)
|
||||
{
|
||||
nodesToAdd.Add(generatedClass.AssignNodeForUpperClassFieldInitialization);
|
||||
}
|
||||
|
||||
var variables = lambdaScope
|
||||
.VariablesDefinedInScope
|
||||
.Where(l => l.ReferencingLambdas.Count > 0)
|
||||
.Select(var => ((IVAriableDefinitionNode) var.SymbolInfo.sym_info).name.ToLower())
|
||||
.ToList();
|
||||
|
||||
foreach (var variable in variables)
|
||||
{
|
||||
var assignStmt = new assign(new dot_node(new ident(generatedClass.GeneratedSubstitutingFieldName),
|
||||
new ident(variable)), new ident(variable));
|
||||
nodesToAdd.Add(assignStmt);
|
||||
}
|
||||
|
||||
((statement_list)lambdaScope.LambdaDefinition.proc_body).subnodes.InsertRange(0, nodesToAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SubstituteVariablesDeclarations()
|
||||
{
|
||||
var classDefsTreeNodes = _generatedScopeClassesInfo.Join(_capturedVarsTreeNodesDictionary,
|
||||
|
|
@ -489,16 +564,105 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
}
|
||||
}
|
||||
|
||||
private void VisitClassDefinitions()
|
||||
private Tuple<type_declaration, List<procedure_definition>> CreateTypeDeclarationWithForwardDeclaration(type_declaration cl)
|
||||
{
|
||||
var oldClDef = (class_definition) cl.type_def;
|
||||
var classDef = SyntaxTreeBuilder.BuildClassDefinition(true);
|
||||
var typeDeclaration = new type_declaration(cl.type_name, classDef);
|
||||
classDef.where_section = oldClDef.where_section;
|
||||
var procedures = new List<procedure_definition>();
|
||||
var classMembers = new class_members(access_modifer.public_modifer);
|
||||
classDef.body.class_def_blocks.Add(classMembers);
|
||||
|
||||
foreach (var member in oldClDef.body.class_def_blocks.SelectMany(x => x.members))
|
||||
{
|
||||
if (member is var_def_statement)
|
||||
{
|
||||
classMembers.Add(member);
|
||||
}
|
||||
else
|
||||
{
|
||||
var procDef = (procedure_definition) member;
|
||||
if (procDef.proc_header is constructor)
|
||||
{
|
||||
classMembers.Add(procDef);
|
||||
continue;
|
||||
}
|
||||
procedure_header procHeader;
|
||||
if (procDef.proc_header is function_header)
|
||||
{
|
||||
var fh = (function_header) procDef.proc_header;
|
||||
procHeader = new function_header
|
||||
{
|
||||
name = new method_name(fh.name.meth_name.name),
|
||||
source_context = fh.source_context,
|
||||
parameters = fh.parameters,
|
||||
of_object = fh.of_object,
|
||||
class_keyword = fh.class_keyword
|
||||
};
|
||||
((function_header)procHeader).return_type = fh.return_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
procHeader = new procedure_header
|
||||
{
|
||||
name = new method_name(procDef.proc_header.name.meth_name.name),
|
||||
source_context = procDef.proc_header.source_context,
|
||||
parameters = procDef.proc_header.parameters,
|
||||
of_object = procDef.proc_header.of_object,
|
||||
class_keyword = procDef.proc_header.class_keyword
|
||||
};
|
||||
}
|
||||
|
||||
procDef.proc_header.name.class_name = cl.type_name;
|
||||
procedures.Add(procDef);
|
||||
classMembers.Add(procHeader);
|
||||
}
|
||||
}
|
||||
|
||||
return new Tuple<type_declaration, List<procedure_definition>>(typeDeclaration, procedures);
|
||||
}
|
||||
|
||||
private List<procedure_definition> VisitClassDefinitions()
|
||||
{
|
||||
_visitor.context.SaveContextAndUpToGlobalLevel();
|
||||
_visitor.lambdaProcessingState = LambdaProcessingState.ClosuresProcessingVisitGeneratedClassesPhase;
|
||||
|
||||
foreach (var clDecl in _generatedScopeClassesInfo.Where(cd => !(cd.Value.CorrespondingTreeNode is CapturedVariablesTreeNodeClassScope)))
|
||||
var procedures = new List<procedure_definition>();
|
||||
var lambdaGroups =
|
||||
_lambdasToBeAddedAsMethods.GroupBy(l => l.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod)
|
||||
.ToDictionary(x => x.Key, x => x.ToList());
|
||||
foreach (var clDecl in _generatedScopeClassesInfo.Where(cd => !(cd.Value.CorrespondingTreeNode is CapturedVariablesTreeNodeClassScope)).OrderBy(cd => cd.Key))
|
||||
{
|
||||
_visitor.visit(clDecl.Value.ClassDeclaration);
|
||||
var lambdas = clDecl.Value.NestedLambdas;
|
||||
List<CapturedVariablesTreeNodeLambdaScope> ls;
|
||||
if (lambdaGroups.TryGetValue(clDecl.Key, out ls))
|
||||
{
|
||||
lambdas = lambdas.Concat(ls).ToList();
|
||||
}
|
||||
var classDecl = (class_definition)clDecl.Value.ClassDeclaration.type_def;
|
||||
foreach (var lambdaDef in lambdas)
|
||||
{
|
||||
var procDecl = LambdaHelper.ConvertLambdaNodeToProcDefNode(lambdaDef.LambdaDefinition);
|
||||
classDecl.body.Add(SyntaxTreeBuilder.BuildOneMemberSection(procDecl));
|
||||
}
|
||||
|
||||
var cl = CreateTypeDeclarationWithForwardDeclaration(clDecl.Value.ClassDeclaration);
|
||||
procedures.AddRange(cl.Item2);
|
||||
_visitor.visit(cl.Item1);
|
||||
}
|
||||
|
||||
_visitor.context.RestoreCurrentContext();
|
||||
_visitor.lambdaProcessingState = LambdaProcessingState.ClosuresProcessingPhase;
|
||||
|
||||
return procedures;
|
||||
}
|
||||
|
||||
private void VisitProceduresOfClasses(List<procedure_definition> procedures)
|
||||
{
|
||||
_visitor.context.SaveContextAndUpToGlobalLevel();
|
||||
_visitor.lambdaProcessingState = LambdaProcessingState.ClosuresProcessingVisitGeneratedClassesPhase;
|
||||
procedures.ForEach(p => _visitor.visit(p));
|
||||
_visitor.context.RestoreCurrentContext();
|
||||
_visitor.lambdaProcessingState = LambdaProcessingState.ClosuresProcessingPhase;
|
||||
}
|
||||
|
|
@ -581,9 +745,15 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
/* Предусмотреть случай, когда захвата переменных не происходит, но мы все равно находимся в лямбде - это нужно сделать на FinishPhase в syntax_tree_visitor
|
||||
/* Не забыть про where секцию */
|
||||
|
||||
for (var i = 0; i < _lambdasToBeAddedAsMethods.Count; i++)
|
||||
var nestedLambdas = new List<CapturedVariablesTreeNodeLambdaScope>();
|
||||
foreach (var cl in _generatedScopeClassesInfo.Where(cd => !(cd.Value.CorrespondingTreeNode is CapturedVariablesTreeNodeClassScope)))
|
||||
{
|
||||
var lambdaDef = _lambdasToBeAddedAsMethods[i].LambdaDefinition;
|
||||
nestedLambdas.AddRange(cl.Value.NestedLambdas);
|
||||
}
|
||||
|
||||
foreach (CapturedVariablesTreeNodeLambdaScope t in _lambdasToBeAddedAsMethods.Concat(nestedLambdas))
|
||||
{
|
||||
var lambdaDef = t.LambdaDefinition;
|
||||
if (lambdaDef.formal_parameters != null && lambdaDef.formal_parameters.params_list.Count > 0)
|
||||
{
|
||||
for (var j = 0; j < lambdaDef.formal_parameters.params_list.Count; j++)
|
||||
|
|
@ -716,8 +886,17 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
{
|
||||
get
|
||||
{
|
||||
return _visitor.context.top_function != null && _visitor.context.top_function.generic_params != null ||
|
||||
_visitor.context._ctn != null && _visitor.context._ctn.generic_params != null;
|
||||
var funcStackAsList = _visitor.context.func_stack == null
|
||||
? null
|
||||
: _visitor.context.func_stack.CloneInternalStack().ToList();
|
||||
|
||||
var funcIsGeneric = false;
|
||||
if (funcStackAsList != null)
|
||||
{
|
||||
funcIsGeneric = funcStackAsList.FirstOrDefault(f => f.generic_params != null) != null;
|
||||
}
|
||||
|
||||
return funcIsGeneric || _visitor.context._ctn != null && _visitor.context._ctn.generic_params != null;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -738,9 +917,17 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
res.AddRange(_visitor.context._ctn.generic_params.Select(par => new ident(par.name)));
|
||||
}
|
||||
|
||||
if (_visitor.context.top_function != null && _visitor.context.top_function.generic_params != null)
|
||||
var funcStackAsList = _visitor.context.func_stack == null
|
||||
? null
|
||||
: _visitor.context.func_stack.CloneInternalStack().ToList();
|
||||
|
||||
if (funcStackAsList != null)
|
||||
{
|
||||
res.AddRange(_visitor.context.top_function.generic_params.Select(par => new ident(par.name)));
|
||||
var funcGeneric = funcStackAsList.FirstOrDefault(f => f.generic_params != null);
|
||||
if (funcGeneric != null)
|
||||
{
|
||||
res.AddRange(funcGeneric.generic_params.Select(par => new ident(par.name)));
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
|
@ -856,14 +1043,16 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
{
|
||||
OnLeave += OnNodeLeave;
|
||||
ProcessNode(statementList);
|
||||
SubstituteTypesInCaseOfGenerics();
|
||||
SubstituteLambdas();
|
||||
SubstituteTypesInCaseOfGenerics();
|
||||
AddPropertiesToConvertingClass();
|
||||
VisitClassDefinitions();
|
||||
var procedures = VisitClassDefinitions();
|
||||
SubstituteVariablesDeclarations();
|
||||
SubstituteForLoopVariables();
|
||||
SubstituteForEachLoopVariables();
|
||||
SubstituteVarDefInProcedure(statementList);
|
||||
//SubstituteLambdaParameters();
|
||||
VisitProceduresOfClasses(procedures);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
private readonly syntax_tree_visitor _visitor;
|
||||
private CapturedVariablesTreeNode _currentTreeNode;
|
||||
private readonly Dictionary<int, CapturedVariablesTreeNode> _scopesCapturedVarsNodesDictionary;
|
||||
private CapturedVariablesTreeNodeLambdaScope _currentLambdaScopeNode; //TODO Пересмотреть для вложенных лямбд
|
||||
private Stack<CapturedVariablesTreeNodeLambdaScope> _currentLambdaScopeNodeStack = new Stack<CapturedVariablesTreeNodeLambdaScope>();
|
||||
private readonly Dictionary<SubstitutionKey, List<ident>> _identsReferences;
|
||||
private CapturedVariablesTreeNode _rootNode;
|
||||
private CapturedVariablesTreeNodeClassScope _classScope;
|
||||
|
|
@ -49,6 +49,13 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
}
|
||||
}
|
||||
|
||||
private bool InLambdaContext
|
||||
{
|
||||
get
|
||||
{
|
||||
return _currentLambdaScopeNodeStack.Count > 0;
|
||||
}
|
||||
}
|
||||
public CapturedVariablesTreeBuilder(syntax_tree_visitor visitor)
|
||||
{
|
||||
_visitor = visitor;
|
||||
|
|
@ -125,7 +132,7 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
|
||||
if (si == null)
|
||||
{
|
||||
if (_currentLambdaScopeNode != null)
|
||||
if (InLambdaContext)
|
||||
{
|
||||
_visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id)));
|
||||
return;
|
||||
|
|
@ -154,13 +161,13 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
si.sym_info.semantic_node_type == semantic_node_type.common_parameter ||
|
||||
si.sym_info.semantic_node_type == semantic_node_type.class_field;
|
||||
|
||||
if (!(acceptableVarType) && _currentLambdaScopeNode != null)
|
||||
if (!(acceptableVarType) && InLambdaContext)
|
||||
{
|
||||
_visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (si.sym_info.semantic_node_type == semantic_node_type.class_field && _currentLambdaScopeNode != null)
|
||||
if (si.sym_info.semantic_node_type == semantic_node_type.class_field && InLambdaContext)
|
||||
{
|
||||
var semClassField = (class_field)si.sym_info;
|
||||
if (semClassField.polymorphic_state != polymorphic_state.ps_common)
|
||||
|
|
@ -186,12 +193,12 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
{
|
||||
if (si.sym_info.semantic_node_type == semantic_node_type.local_variable)
|
||||
{
|
||||
if (!(idName == compiler_string_consts.self_word && si.scope is SymbolTable.ClassMethodScope && _classScope != null) && _currentLambdaScopeNode != null)
|
||||
if (!(idName == compiler_string_consts.self_word && si.scope is SymbolTable.ClassMethodScope && _classScope != null) && InLambdaContext)
|
||||
{
|
||||
_visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id)));
|
||||
}
|
||||
}
|
||||
if (si.sym_info.semantic_node_type == semantic_node_type.common_parameter && prScope.FunctionNode.parameters.First(v => v.name.ToLower() == idName).parameter_type != parameter_type.value && _currentLambdaScopeNode != null)
|
||||
if (si.sym_info.semantic_node_type == semantic_node_type.common_parameter && prScope.FunctionNode.parameters.First(v => v.name.ToLower() == idName).parameter_type != parameter_type.value && InLambdaContext)
|
||||
{
|
||||
_visitor.AddError(new CannotCaptureNonValueParameters(_visitor.get_location(id)));
|
||||
}
|
||||
|
|
@ -268,19 +275,43 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
_identsReferences[substKey].Add(id);
|
||||
}
|
||||
|
||||
if (_currentLambdaScopeNode == null ||
|
||||
scopeIndex >= _currentLambdaScopeNode.ScopeIndex)
|
||||
if (InLambdaContext && scope is CapturedVariablesTreeNodeLambdaScope &&
|
||||
scopeIndex < _currentLambdaScopeNodeStack.Peek().ScopeIndex) //TODO: Захват параметров лямбды в другой лямбде
|
||||
{
|
||||
_visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!InLambdaContext ||
|
||||
scopeIndex >= _currentLambdaScopeNodeStack.Peek().ScopeIndex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_currentLambdaScopeNode.CapturedVarsSymbolInfo.Contains(si))
|
||||
var stackAsList = _currentLambdaScopeNodeStack.ToList();
|
||||
stackAsList.RemoveAt(0);
|
||||
|
||||
if (!_currentLambdaScopeNodeStack.Peek().CapturedVarsSymbolInfo.Contains(si))
|
||||
{
|
||||
_currentLambdaScopeNode.CapturedVarsSymbolInfo.Add(si);
|
||||
_currentLambdaScopeNodeStack.Peek().CapturedVarsSymbolInfo.Add(si);
|
||||
foreach (var capturedVariablesTreeNodeLambdaScope in stackAsList)
|
||||
{
|
||||
if (!capturedVariablesTreeNodeLambdaScope.CapturedVarsSymbolInfo.Contains(si))
|
||||
{
|
||||
capturedVariablesTreeNodeLambdaScope.CapturedVarsSymbolInfo.Add(si);
|
||||
}
|
||||
if (!idRef.ReferencingLambdas.Contains(_currentLambdaScopeNode))
|
||||
}
|
||||
}
|
||||
if (!idRef.ReferencingLambdas.Contains(_currentLambdaScopeNodeStack.Peek()))
|
||||
{
|
||||
idRef.ReferencingLambdas.Add(_currentLambdaScopeNode);
|
||||
idRef.ReferencingLambdas.Add(_currentLambdaScopeNodeStack.Peek());
|
||||
foreach (var capturedVariablesTreeNodeLambdaScope in stackAsList)
|
||||
{
|
||||
if (!idRef.ReferencingLambdas.Contains(capturedVariablesTreeNodeLambdaScope))
|
||||
{
|
||||
idRef.ReferencingLambdas.Add(capturedVariablesTreeNodeLambdaScope);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -529,14 +560,14 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
_visitor.context.func_stack.top().scope.ScopeNum, lambdaDefinition);
|
||||
|
||||
_currentTreeNode.LambdasDefinedInScope.Add(newTreeNode);
|
||||
_currentLambdaScopeNode = newTreeNode;
|
||||
_currentLambdaScopeNodeStack.Push(newTreeNode);
|
||||
|
||||
if (_currentTreeNode != null)
|
||||
{
|
||||
_currentTreeNode.ChildNodes.Add(newTreeNode);
|
||||
}
|
||||
_currentTreeNode = newTreeNode;
|
||||
|
||||
_scopesCapturedVarsNodesDictionary.Add(_currentTreeNode.ScopeIndex, _currentTreeNode);
|
||||
|
||||
VisitProcParameters(procDecl.proc_header.parameters);
|
||||
ProcessNode(procDecl.proc_body);
|
||||
|
|
@ -545,7 +576,7 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
_visitor.context.remove_lambda_function(procDecl.proc_header.name.meth_name.name, false);
|
||||
|
||||
_currentTreeNode = _currentTreeNode.ParentNode;
|
||||
_currentLambdaScopeNode = null; //TODO: Вложенные лямбды - изменить это
|
||||
_currentLambdaScopeNodeStack.Pop();
|
||||
|
||||
LambdaHelper.RemoveLambdaInfoFromCompilationContext(_visitor.context, lambdaDefinition);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1048,12 +1048,6 @@ namespace PascalABCCompiler.TreeConverter
|
|||
{
|
||||
var func_stack_as_array = _func_stack.CloneInternalStack().ToList();
|
||||
|
||||
var upperLambda = func_stack_as_array.FirstOrDefault(func => LambdaHelper.IsLambdaName(func.name));
|
||||
if (upperLambda != null)
|
||||
{
|
||||
syntax_tree_visitor.AddError(new NestedLambdasAreNotSupportedInThisVersionOfCompiler(def_loc));
|
||||
}
|
||||
|
||||
var nestedFunc = func_stack_as_array.FirstOrDefault(func => func is common_in_function_function_node);
|
||||
if (nestedFunc != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5082,6 +5082,10 @@ namespace PascalABCCompiler.TreeConverter
|
|||
if (lambdas_are_in_parameters)
|
||||
{
|
||||
LambdaHelper.processingLambdaParametersForTypeInference++;
|
||||
// SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями
|
||||
function_node_list spf = null;
|
||||
try
|
||||
{
|
||||
function_node ffn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters);
|
||||
int exprCounter = 0;
|
||||
if (skip_first_parameter)
|
||||
|
|
@ -5097,11 +5101,140 @@ namespace PascalABCCompiler.TreeConverter
|
|||
}
|
||||
else
|
||||
{
|
||||
LambdaHelper.InferTypesFromVarStmt(ffn.parameters[exprCounter].type, en as SyntaxTree.function_lambda_definition, this);
|
||||
var enLambda = (SyntaxTree.function_lambda_definition)en;
|
||||
LambdaHelper.InferTypesFromVarStmt(ffn.parameters[exprCounter].type, enLambda, this);
|
||||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing;
|
||||
exprs[exprCounter] = convert_strong(en);
|
||||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing;
|
||||
exprCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SeveralFunctionsCanBeCalled sf)
|
||||
{
|
||||
spf = sf.set_of_possible_functions; // Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна
|
||||
}
|
||||
|
||||
Exception lastmultex = null;
|
||||
if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try
|
||||
{ // exprs - глобальная, поэтому надо копировать
|
||||
int spfnum = -1; // первый номер правильно инстанцированной. Если потом встретился второй, то тоже ошибка
|
||||
for (int i = 0; i < spf.Count; i++)
|
||||
{
|
||||
function_node fnn = spf[i];
|
||||
try
|
||||
{
|
||||
int exprCounter = 0;
|
||||
expressions_list exprs1 = new expressions_list();
|
||||
exprs1.AddRange(exprs); // сделали копию
|
||||
|
||||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions)
|
||||
{
|
||||
if (!(en is SyntaxTree.function_lambda_definition))
|
||||
{
|
||||
exprCounter++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
var fld = en as SyntaxTree.function_lambda_definition;
|
||||
|
||||
var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо
|
||||
var fl = fld.lambda_visit_mode;
|
||||
|
||||
// запомнили типы параметров лямбды - SSM
|
||||
object[] realparamstype = new object[fld.formal_parameters.params_list.Count]; // здесь хранятся выведенные типы лямбд или null если типы явно заданы
|
||||
for (var k = 0; k < fld.formal_parameters.params_list.Count; k++)
|
||||
{
|
||||
var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type;
|
||||
if (laminftypeK == null)
|
||||
realparamstype[k] = null;
|
||||
else realparamstype[k] = laminftypeK.real_type;
|
||||
}
|
||||
|
||||
// запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим
|
||||
var restype = fld.return_type as SyntaxTree.lambda_inferred_type;
|
||||
object realrestype = null;
|
||||
if (restype != null)
|
||||
realrestype = restype.real_type;
|
||||
|
||||
LambdaHelper.InferTypesFromVarStmt(fnn.parameters[exprCounter].type, fld, this);
|
||||
fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //lroman
|
||||
fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName); // поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ!
|
||||
|
||||
//contextChanger.SaveContextAndUpToNearestDefSect();
|
||||
try
|
||||
{
|
||||
exprs1[exprCounter] = convert_strong(en);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition);
|
||||
// восстанавливаем сохраненный тип возвращаемого значения
|
||||
if (restype != null)
|
||||
restype.real_type = realrestype;
|
||||
// восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно
|
||||
for (var k = 0; k < fld.formal_parameters.params_list.Count; k++)
|
||||
{
|
||||
var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type;
|
||||
if (laminftypeK != null)
|
||||
laminftypeK.real_type = realparamstype[k];
|
||||
}
|
||||
|
||||
fld.lambda_name = lambdaName; //lroman Восстанавливаем имена
|
||||
fld.lambda_visit_mode = fl;
|
||||
}
|
||||
|
||||
//contextChanger.RestoreCurrentContext();
|
||||
exprCounter++;
|
||||
}
|
||||
}
|
||||
if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так
|
||||
{
|
||||
spfnum = -2;
|
||||
break;
|
||||
}
|
||||
|
||||
spfnum = i;
|
||||
for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо
|
||||
exprs[j] = exprs1[j];
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать
|
||||
//contextChanger.RestoreCurrentContext();
|
||||
lastmultex = e;
|
||||
}
|
||||
}
|
||||
if (spfnum == -2) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так
|
||||
throw new SeveralFunctionsCanBeCalled(subloc, spf);
|
||||
if (spfnum == -1) // было много, но ни одна не подошла из-за лямбд
|
||||
{
|
||||
throw lastmultex;
|
||||
//throw new NoFunctionWithSameArguments(subloc2, false);
|
||||
}
|
||||
|
||||
var kk = 0;
|
||||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions) //lroman окончательно подставить типы в лямбды
|
||||
{
|
||||
if (!(en is SyntaxTree.function_lambda_definition))
|
||||
{
|
||||
kk++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type, en as SyntaxTree.function_lambda_definition, this);
|
||||
exprs[kk] = convert_strong(en);
|
||||
kk++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// SSM 21.05.14 end
|
||||
LambdaHelper.processingLambdaParametersForTypeInference--;
|
||||
}
|
||||
//lroman//
|
||||
|
|
@ -6022,8 +6155,11 @@ namespace PascalABCCompiler.TreeConverter
|
|||
}
|
||||
else
|
||||
{
|
||||
LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type, en as SyntaxTree.function_lambda_definition, this);
|
||||
var enLambda = (SyntaxTree.function_lambda_definition) en;
|
||||
LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type, enLambda, this);
|
||||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing;
|
||||
exprs[exprCounter] = convert_strong(en);
|
||||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing;
|
||||
exprCounter++;
|
||||
}
|
||||
}
|
||||
|
|
@ -6085,8 +6221,13 @@ namespace PascalABCCompiler.TreeConverter
|
|||
{
|
||||
exprs1[exprCounter] = convert_strong(en);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition);
|
||||
// восстанавливаем сохраненный тип возвращаемого значения
|
||||
if (restype != null)
|
||||
restype.real_type = realrestype;
|
||||
|
|
@ -6121,7 +6262,6 @@ namespace PascalABCCompiler.TreeConverter
|
|||
// если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать
|
||||
//contextChanger.RestoreCurrentContext();
|
||||
lastmultex = e;
|
||||
context.converted_namespace.functions.remove_at(context.converted_namespace.functions.Count - 1);
|
||||
}
|
||||
}
|
||||
if (spfnum == -2) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так
|
||||
|
|
@ -10565,7 +10705,7 @@ namespace PascalABCCompiler.TreeConverter
|
|||
if ((context.top_function.semantic_node_type == semantic_node_type.common_method_node)
|
||||
|| ((context.func_stack_size_is_one()) && (_is_interface_part)))
|
||||
{
|
||||
context.leave_block();
|
||||
//context.leave_block();
|
||||
}
|
||||
}
|
||||
body_exists = false;
|
||||
|
|
@ -16154,9 +16294,11 @@ namespace PascalABCCompiler.TreeConverter
|
|||
}
|
||||
else
|
||||
{
|
||||
LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type,
|
||||
en as SyntaxTree.function_lambda_definition, this);
|
||||
var enLambda = (SyntaxTree.function_lambda_definition)en;
|
||||
LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type, enLambda, this);
|
||||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing;
|
||||
exprs[exprCounter] = convert_strong(en);
|
||||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing;
|
||||
exprCounter++;
|
||||
}
|
||||
}
|
||||
|
|
@ -16226,8 +16368,13 @@ namespace PascalABCCompiler.TreeConverter
|
|||
{
|
||||
exprs1[exprCounter] = convert_strong(en);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition);
|
||||
// восстанавливаем сохраненный тип возвращаемого значения
|
||||
if (restype != null)
|
||||
restype.real_type = realrestype;
|
||||
|
|
@ -16265,8 +16412,6 @@ namespace PascalABCCompiler.TreeConverter
|
|||
// если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать
|
||||
//contextChanger.RestoreCurrentContext();
|
||||
lastmultex = e;
|
||||
context.converted_namespace.functions.remove_at(
|
||||
context.converted_namespace.functions.Count - 1);
|
||||
}
|
||||
}
|
||||
if (spfnum == -2)
|
||||
|
|
|
|||
Loading…
Reference in a new issue