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]