diff --git a/InstallerSamples/LanguageFeatures/IfThenElseExpr.pas b/InstallerSamples/LanguageFeatures/IfThenElseExpr.pas new file mode 100644 index 000000000..8b64f17d9 --- /dev/null +++ b/InstallerSamples/LanguageFeatures/IfThenElseExpr.pas @@ -0,0 +1,6 @@ +begin + var (a,b) := (2,3); + var min: integer; + min := if a0 then + if y>0 then + 1 + else 4 + else + if y>0 then + 2 + else 3; + + Print(q) +end. \ No newline at end of file diff --git a/SyntaxVisitors/SugarVisitors/NewRangeDesugarVisitor.cs b/SyntaxVisitors/SugarVisitors/NewRangeDesugarVisitor.cs index 748b2cb6d..a17cf66d0 100644 --- a/SyntaxVisitors/SugarVisitors/NewRangeDesugarVisitor.cs +++ b/SyntaxVisitors/SugarVisitors/NewRangeDesugarVisitor.cs @@ -9,6 +9,7 @@ using PascalABCCompiler.SyntaxTree; namespace SyntaxVisitors.SugarVisitors { + public class NewRangeDesugarVisitor : BaseChangeVisitor { public static NewRangeDesugarVisitor New @@ -83,10 +84,11 @@ namespace SyntaxVisitors.SugarVisitors var cr = fe.type_name is no_type_foreach; var left = new int32_const(0, fe.identifier.source_context); - var right = dn.left.dot_node("Count").Minus(1); + var right = dn.left.dot_node("Count").Minus(1); // Строки таким образом сделать не получится. Разве что в семантическом контроле чуть довернуть этот узел )) var fn = new for_node(fe.identifier, left, right, fe.stmt, for_cycle_type.to, null, typ, cr); var sl = new List(); + sl.Add(new semantic_check_sugared_statement_node(typeof(foreach_stmt), new List { dn.right }, fe.source_context)); sl.Add(fn); ReplaceStatementUsingParent(fe, sl); diff --git a/TreeConverter/TreeConversion/SyntaxTreeVisitorNodes/Foreach.cs b/TreeConverter/TreeConversion/SyntaxTreeVisitorNodes/Foreach.cs index 837035729..0d5d6fc61 100644 --- a/TreeConverter/TreeConversion/SyntaxTreeVisitorNodes/Foreach.cs +++ b/TreeConverter/TreeConversion/SyntaxTreeVisitorNodes/Foreach.cs @@ -165,14 +165,7 @@ namespace PascalABCCompiler.TreeConverter return false; } - - /// - /// Преобразует foreach в for, если коллекция это одномерный массив. - /// - /// - /// - /// True - если преобразование удалось, иначе False - private bool OptimizeForeachInCase1DArray(foreach_stmt _foreach_stmt, expression_node in_what) + private bool Is1DArray(expression_node in_what) { var is1dimdynarr = false; var comptn = in_what.type as compiled_type_node; @@ -186,15 +179,28 @@ namespace PascalABCCompiler.TreeConverter if (comtn != null && comtn.internal_type_special_kind == type_special_kind.array_kind && comtn.rank == 1) { - is1dimdynarr = true; + is1dimdynarr = true; } } + return is1dimdynarr; + } + + + /// + /// Преобразует foreach в for, если коллекция это одномерный массив. + /// + /// + /// + /// True - если преобразование удалось, иначе False + private bool OptimizeForeachInCase1DArray(foreach_stmt _foreach_stmt, expression_node in_what) + { + var is1dimdynarr = Is1DArray(in_what); var il = IsIList(in_what); // SSM 23.08.16 Закомментировал оптимизацию. Не работает с лямбдами. Лямбды обходят старое дерево. А заменить foreach на for на этом этапе пока не получается - не развита инфраструктура // SSM 24.12.19 Раскомментировал оптимизацию, но только если foreach не вложен в лямбду - if (is1dimdynarr) // Замена foreach на for для массива + if (is1dimdynarr || il) // Замена foreach на for для массива { // сгенерировать код для for и вызвать соответствующий visit var arrid = GenIdentName(); diff --git a/TreeConverter/TreeConversion/semantic_checks_for_sugar.cs b/TreeConverter/TreeConversion/semantic_checks_for_sugar.cs index 2e55c3d28..ece286d99 100644 --- a/TreeConverter/TreeConversion/semantic_checks_for_sugar.cs +++ b/TreeConverter/TreeConversion/semantic_checks_for_sugar.cs @@ -244,6 +244,11 @@ namespace PascalABCCompiler.TreeConverter } } + void semantic_check_for_indices(SyntaxTree.expression expr) + { + // Надо проверить, что expr - это одноразмерный массив или список. Эта проверка была в visit(foreach) + } + } } diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index 26b34c686..e2c191e1f 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -20305,12 +20305,17 @@ namespace PascalABCCompiler.TreeConverter var expr = st.lst[0] as SyntaxTree.expression; semantic_check_loop_stmt(expr); } - else if (st.typ as System.Type == typeof(SyntaxTree.foreach_stmt)) // для NewRange Visitorа. Если будет перекрытие, то надоделать новые типы-маркеры + else if (st.typ as System.Type == typeof(SyntaxTree.foreach_stmt) && st.lst.Count == 3) // для NewRange Visitorа. Если будет перекрытие, то надоделать новые типы-маркеры { var expr = st.lst[0] as SyntaxTree.diapason_expr_new; var td = st.lst[1] as SyntaxTree.type_definition; var id = st.lst[2] as SyntaxTree.ident; - semantic_check_for_new_range(expr,td,id); + semantic_check_for_new_range(expr, td, id); + } + else if (st.typ as System.Type == typeof(SyntaxTree.foreach_stmt) && st.lst.Count == 3) // для a.Indices. Пока непонятно, где описывать тип-маркер + { + var expr = st.lst[0] as SyntaxTree.expression; + semantic_check_for_indices(expr); } // Patterns else if (st.typ is SemanticCheckType.MatchedExpression)