diff --git a/Configuration/GlobalAssemblyInfo.cs b/Configuration/GlobalAssemblyInfo.cs
index 36293b861..ab47e90d6 100644
--- a/Configuration/GlobalAssemblyInfo.cs
+++ b/Configuration/GlobalAssemblyInfo.cs
@@ -15,7 +15,7 @@ internal static class RevisionClass
public const string Major = "3";
public const string Minor = "9";
public const string Build = "0";
- public const string Revision = "3280";
+ public const string Revision = "3282";
public const string MainVersion = Major + "." + Minor;
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
diff --git a/Configuration/Version.defs b/Configuration/Version.defs
index 0b53ff4fa..99269cba7 100644
--- a/Configuration/Version.defs
+++ b/Configuration/Version.defs
@@ -1,4 +1,4 @@
%COREVERSION%=0
-%REVISION%=3280
+%REVISION%=3282
%MINOR%=9
%MAJOR%=3
diff --git a/Release/pabcversion.txt b/Release/pabcversion.txt
index 7170f16b9..50c5d698d 100644
--- a/Release/pabcversion.txt
+++ b/Release/pabcversion.txt
@@ -1 +1 @@
-3.9.0.3280
+3.9.0.3282
diff --git a/ReleaseGenerators/PascalABCNET_version.nsh b/ReleaseGenerators/PascalABCNET_version.nsh
index 63a0eaa63..82c8ce806 100644
--- a/ReleaseGenerators/PascalABCNET_version.nsh
+++ b/ReleaseGenerators/PascalABCNET_version.nsh
@@ -1 +1 @@
-!define VERSION '3.9.0.3280'
+!define VERSION '3.9.0.3282'
diff --git a/SyntaxTree/tree/Tree.cs b/SyntaxTree/tree/Tree.cs
index 3d3293061..9f55acbb8 100644
--- a/SyntaxTree/tree/Tree.cs
+++ b/SyntaxTree/tree/Tree.cs
@@ -46956,7 +46956,8 @@ namespace PascalABCCompiler.SyntaxTree
///
- ///
+ ///Это внутри begin:var (a,b) := (1,2);
+
///
[Serializable]
public partial class assign_var_tuple : statement
@@ -50962,7 +50963,7 @@ namespace PascalABCCompiler.SyntaxTree
///
- ///
+ ///Это только в секции до begin: var (a,b) := (3,4); begin
///
[Serializable]
public partial class var_tuple_def_statement : var_def_statement
diff --git a/SyntaxTree/tree/tree.xml b/SyntaxTree/tree/tree.xml
index 2d4e83f5a..6fe4b2e0f 100644
--- a/SyntaxTree/tree/tree.xml
+++ b/SyntaxTree/tree/tree.xml
@@ -3520,7 +3520,7 @@
-
+
@@ -4858,7 +4858,7 @@
-
+
diff --git a/SyntaxVisitors/SugarVisitors/AssignTuplesDesugarVisitor.cs b/SyntaxVisitors/SugarVisitors/AssignTuplesDesugarVisitor.cs
index 9b38bb33b..9807b829c 100644
--- a/SyntaxVisitors/SugarVisitors/AssignTuplesDesugarVisitor.cs
+++ b/SyntaxVisitors/SugarVisitors/AssignTuplesDesugarVisitor.cs
@@ -120,6 +120,7 @@ namespace SyntaxVisitors.SugarVisitors
visit(assvartup.expr); // В assvartup.expr могут содержаться лямбды, в которых будут другие assign_var_tuple.
// И вообще другой синтаксический сахар, размещённый в этом визиторе
}
+
public override void visit(var_tuple_def_statement vtd)
{
// Состоит из var_def_statements. Некоторые являются var_tuple_def_statement
diff --git a/SyntaxVisitors/SugarVisitors/TupleVisitor.cs b/SyntaxVisitors/SugarVisitors/TupleVisitor.cs
index ec68ff2c6..a393a6675 100644
--- a/SyntaxVisitors/SugarVisitors/TupleVisitor.cs
+++ b/SyntaxVisitors/SugarVisitors/TupleVisitor.cs
@@ -19,6 +19,13 @@ namespace SyntaxVisitors.SugarVisitors
get { return new TupleVisitor(); }
}
+ private int num = 0;
+ public string UniqueName()
+ {
+ num++;
+ return "#tup_vis"+num.ToString();
+ }
+
public override void visit(read_accessor_name wn)
{
DefaultVisit(wn);
@@ -48,6 +55,8 @@ namespace SyntaxVisitors.SugarVisitors
ProcessNode(ls.to_statement);
}
+ // Здесь раскрываются ситуации когда справа - кортеж с константами: var (a,b) := (1,2) и только это.
+ // Остальное раскрывается в AssignTuplesDesugarVisitor
public override void visit(assign_var_tuple assvartup)
{
if (assvartup.expr is tuple_node tn && tn.el.expressions.All(ex => ex is const_node) && !tn.el.expressions.Any(ex => ex is nil_const))
@@ -94,6 +103,33 @@ namespace SyntaxVisitors.SugarVisitors
}
ReplaceStatementUsingParent(asstup, sl);
}
+ else if (asstup.expr is tuple_node tn1 && !tn1.el.expressions.Any(ex => ex is nil_const))
+ {
+ var n = asstup.vars.variables.Count();
+ if (n > tn1.el.Count)
+ throw new SyntaxVisitorError("TOO_MANY_ELEMENTS_ON_LEFT_SIDE_OF_TUPLE_ASSIGNMENT", asstup.vars.variables[0]);
+
+ var sl = new List();
+ for (var i = 0; i < n; i++)
+ {
+ var temp_id = new ident(UniqueName(), tn1.el.expressions[i].source_context);
+ var var_def = new var_def_statement(temp_id, tn1.el.expressions[i], tn1.el.expressions[i].source_context);
+ var a = new var_statement(var_def, tn1.el.expressions[i].source_context);
+ sl.Add(a);
+ }
+
+ //for (var i = 0; i < n; i++)
+ for (var i = n-1; i >=0; i--)
+ {
+ var a = new assign(asstup.vars.variables[i],
+ (sl[i] as var_statement).var_def.vars.idents[0],
+ Operators.Assignment,
+ asstup.vars.variables[i].source_context);
+ sl.Add(a);
+ }
+
+ ReplaceStatementUsingParent(asstup, sl);
+ }
else
{
DefaultVisit(asstup);
@@ -111,6 +147,7 @@ namespace SyntaxVisitors.SugarVisitors
}
}
+ // А это по идее до begin - там немного другие узлы и внешний контекст
public override void visit(var_tuple_def_statement vtd)
{
if (vtd.inital_value is tuple_node tn && tn.el.expressions.All(ex => ex is const_node) && !tn.el.expressions.Any(ex => ex is nil_const))
diff --git a/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs b/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs
index 9fb324280..4fbaa46f2 100644
--- a/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs
+++ b/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs
@@ -3000,8 +3000,9 @@ namespace PascalABCCompiler.TreeConverter
return AddError(new SeveralFunctionsCanBeCalled(loc, list)); // или другое сообщение
// Теперь раз в list осталась одна функция, найти её в functions и только её и оставить
- functions.RemoveAll(fun => fun.sym_info != list[0]);
- if (functions.Count == 0)
+ // Надо делать копию functions иначе это влияет на следующий код
+ var functions1 = functions.Where(fun => fun.sym_info == list[0]).ToList();
+ if (functions1.Count == 0)
return AddError(new NoFunctionWithSameArguments(FunctionName, loc, true)); // это не должно случиться, но вдруг
// Вот и в functions осталась одна функция
// Теперь делаем словарь сопоставлений именам -> expression_node (в параметрах)
@@ -3016,7 +3017,7 @@ namespace PascalABCCompiler.TreeConverter
// Я бы очистил хвост parameters и добавлял бы в него как раньше параметры по умолчанию
parameters.remove_range(indexOfFirstNamedArgumentSem, parameters.Count - indexOfFirstNamedArgumentSem); // удалить хвост
- var fun1 = functions[0].sym_info as function_node; // это - единственная функция
+ var fun1 = functions1[0].sym_info as function_node; // это - единственная функция
var is_ext = fun1.is_extension_method;
for (int i = indexOfFirstNamedArgument + (is_ext ? 1 : 0); i < fun1.parameters.Count; i++) // сверить это с другим кодом
{
@@ -3031,7 +3032,7 @@ namespace PascalABCCompiler.TreeConverter
// syntax_nodes_parameters мне кажется всё испортят - там именованные аргументы стоят не на своих местах!!!
// Это единственный - опасный и потенциально с ошибками вызов!
// Но ощущение, что всё верно, т.к. это нужно только для параметров лямбд, а у именованных аргументов их быть не может
- list = select_function_helper(parameters, functions, loc, syntax_nodes_parameters, only_from_not_extensions, out err_out);
+ list = select_function_helper(parameters, functions1, loc, syntax_nodes_parameters, only_from_not_extensions, out err_out);
if (err_out != null)
return AddError(err_out);
return list[0];
diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs
index 0a58db234..52df90659 100644
--- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs
+++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs
@@ -5910,6 +5910,9 @@ namespace PascalABCCompiler.TreeConverter
// Семантическая разница между exprs.Count и s_n_p.Count равна 1 !!! Только здесь! И вот ее и передавать!
// exprs.Count = 3; s_n_p = 2; false - не удаляем 1 параметр
// Добавил последний параметр = 1 - это единственное место где длина exprs на 1 больше
+ // Это первый вызов. Будет второй поэтому надо сохранить копию expr до вызова
+
+ var exprs_copy = exprs.Clone();
fn = convertion_data_and_alghoritms.select_function(exprs, sil, subloc, syntax_nodes_parameters, false, 1);
if (fn == null && skip_first_parameter)
{
@@ -5921,8 +5924,10 @@ namespace PascalABCCompiler.TreeConverter
Errors.Error last_err = LastError();
skip_first_parameter = false;
sil = tmp_sil;
+ exprs = exprs_copy;
exprs.remove_at(0);
// exprs.Count = 2; s_n_p = 2; true - удаляем 1 параметр, пропускаем расширения
+ // Только для методов, исключая методы расширения
fn = convertion_data_and_alghoritms.select_function(exprs, sil, subloc, syntax_nodes_parameters,true);
if (fn == null)
{
@@ -5943,8 +5948,11 @@ namespace PascalABCCompiler.TreeConverter
throw last_err;
}
}
+ // Это значит, что нашли метод расширения, но на всякий случай ищем метод поскольку он имеет приоритет
else if (fn != null && skip_first_parameter && sil.Count() > 1 && !sil.HasOnlyExtensionMethods())
{
+ var exprs_saved = exprs; // запомнили то что нашли - вдруг здесь не найдем
+ exprs = exprs_copy; // восстановили начальное exprs
function_node tmp_fn = fn;
exprs.remove_at(0);
sil = tmp_sil;
@@ -5954,7 +5962,8 @@ namespace PascalABCCompiler.TreeConverter
{
fn = tmp_fn;
RemoveLastError();
- exprs.AddElementFirst(exp);
+ exprs = exprs_saved; // восстановили - т.к. здесь не нашли
+ //exprs.AddElementFirst(exp);
}
}
}
diff --git a/TreeConverter/TreeRealization/Collections.cs b/TreeConverter/TreeRealization/Collections.cs
index 48eafc68f..1830fb04c 100644
--- a/TreeConverter/TreeRealization/Collections.cs
+++ b/TreeConverter/TreeRealization/Collections.cs
@@ -13,6 +13,13 @@ namespace PascalABCCompiler.TreeRealization
public class expressions_list : extended_collection
{
public override string ToString() => string.Join(", ", this._elements);
+ public expressions_list Clone()
+ {
+ var exprl = new expressions_list();
+ foreach (var elem in this)
+ exprl.AddElement(elem);
+ return exprl;
+ }
}
[Serializable]