В оптимизацию foreach добавлен IList

This commit is contained in:
Mikhalkovich Stanislav 2020-01-06 11:23:55 +03:00
parent 17339ade0c
commit 5aa72fac74
6 changed files with 51 additions and 13 deletions

View file

@ -0,0 +1,6 @@
begin
var (a,b) := (2,3);
var min: integer;
min := if a<b then a else b;
Print(min)
end.

View file

@ -0,0 +1,14 @@
begin
var (x,y) := (5,-3);
var q :=
if x>0 then
if y>0 then
1
else 4
else
if y>0 then
2
else 3;
Print(q)
end.

View file

@ -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<statement>();
sl.Add(new semantic_check_sugared_statement_node(typeof(foreach_stmt), new List<syntax_tree_node> { dn.right }, fe.source_context));
sl.Add(fn);
ReplaceStatementUsingParent(fe, sl);

View file

@ -165,14 +165,7 @@ namespace PascalABCCompiler.TreeConverter
return false;
}
/// <summary>
/// Преобразует foreach в for, если коллекция это одномерный массив.
/// </summary>
/// <param name="_foreach_stmt"></param>
/// <param name="in_what"></param>
/// <returns>True - если преобразование удалось, иначе False</returns>
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;
}
/// <summary>
/// Преобразует foreach в for, если коллекция это одномерный массив.
/// </summary>
/// <param name="_foreach_stmt"></param>
/// <param name="in_what"></param>
/// <returns>True - если преобразование удалось, иначе False</returns>
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();

View file

@ -244,6 +244,11 @@ namespace PascalABCCompiler.TreeConverter
}
}
void semantic_check_for_indices(SyntaxTree.expression expr)
{
// Надо проверить, что expr - это одноразмерный массив или список. Эта проверка была в visit(foreach)
}
}
}

View file

@ -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)