Оптимизирован foreach для массивов - для него генерируется цикл for

This commit is contained in:
miks1965 2016-07-29 16:54:51 +03:00
parent a73432abc3
commit 945b18a326
10 changed files with 97 additions and 27 deletions

View file

@ -15,7 +15,7 @@ internal static class RevisionClass
public const string Major = "3";
public const string Minor = "1";
public const string Build = "0";
public const string Revision = "1284";
public const string Revision = "1286";
public const string MainVersion = Major + "." + Minor;
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;

View file

@ -1,4 +1,4 @@
%MINOR%=1
%REVISION%=1284
%REVISION%=1286
%COREVERSION%=0
%MAJOR%=3

View file

@ -1154,15 +1154,6 @@
</Items>
</Node>
<Node Name="a.Sort((row1, row2) -&gt; 1)">
<FileName>\TreeConverter\TreeConversion\syntax_tree_visitor.cs</FileName>
<Text>return;</Text>
<OCtx>
<i Type="Method">internal void visit_method_call ( SyntaxTree . method_call _method_call )</i>
<i Type="ClassOrNamespace">public class syntax_tree_visitor : SyntaxTree . AbstractVisitor</i>
<i Type="ClassOrNamespace">namespace PascalABCCompiler . TreeConverter</i>
<i Type="CS_TreeNode">
</i>
</OCtx>
<Items>
<Node Name="visit_method_call">
<FileName>\TreeConverter\TreeConversion\syntax_tree_visitor.cs</FileName>
@ -1177,6 +1168,32 @@
</Node>
</Items>
</Node>
<Node Name="foreach Arr -&gt; for">
<Items>
<Node Name="visit(SyntaxTree.foreach_stmt">
<FileName>\TreeConverter\TreeConversion\syntax_tree_visitor.cs</FileName>
<Text>public override void visit(SyntaxTree.foreach_stmt _foreach_stmt)</Text>
<OCtx>
<i Type="Method">public override void visit ( SyntaxTree . foreach_stmt _foreach_stmt )</i>
<i Type="ClassOrNamespace">public class syntax_tree_visitor : SyntaxTree . AbstractVisitor</i>
<i Type="ClassOrNamespace">namespace PascalABCCompiler . TreeConverter</i>
<i Type="CS_TreeNode">
</i>
</OCtx>
</Node>
<Node Name="visit(SyntaxTree.semantic_type_node">
<FileName>\TreeConverter\TreeConversion\syntax_tree_visitor.cs</FileName>
<Text>public override void visit(SyntaxTree.semantic_type_node stn)</Text>
<OCtx>
<i Type="Method">public override void visit ( SyntaxTree . semantic_type_node stn )</i>
<i Type="ClassOrNamespace">public class syntax_tree_visitor : SyntaxTree . AbstractVisitor</i>
<i Type="ClassOrNamespace">namespace PascalABCCompiler . TreeConverter</i>
<i Type="CS_TreeNode">
</i>
</OCtx>
</Node>
</Items>
</Node>
</Items>
</Node>
</AspectFile>

View file

@ -1 +1 @@
!define VERSION '3.1.0.1284'
!define VERSION '3.1.0.1286'

View file

@ -9,6 +9,13 @@ namespace PascalABCCompiler.SyntaxTree
{
public static SourceContext BuildGenSC = new SourceContext(0, 777777, 0, 0, 0, 0);
private static int GenIdNum = 0;
public static ident GenIdentName()
{
GenIdNum++;
return new ident("$GenId" + GenIdNum.ToString());
}
public static type_definition BuildSimpleType(string name)
{
return new named_type_reference(name, null);

Binary file not shown.

View file

@ -8452,7 +8452,7 @@ end;
// Дополнения февраль 2016: Shuffle, AdjacentFind, IndexMin, IndexMax, Replace, Transform
// Статические методы - в методы расширения: BinarySearch, ConvertAll, Find, FindIndex, FindAll,
// FindLast, FindLastIndex, IndexOf, Contains, LastIndexOf, Reverse, Resize, Sort
// FindLast, FindLastIndex, IndexOf, Contains, LastIndexOf, Reverse, Sort
/// Перемешивает элементы массива случайным образом
function Shuffle<T>(Self: array of T): array of T; extensionmethod;
@ -8645,12 +8645,6 @@ begin
Result := System.Array.LastIndexOf(self,x,start);
end;
/// Меняет размер массива
procedure Resize<T>(self: array of T; x: integer); extensionmethod;
begin
System.Array.Resize(self,x);
end;
/// Сортирует массив по возрастанию
procedure Sort<T>(self: array of T); extensionmethod;
begin

View file

@ -16524,13 +16524,68 @@ namespace PascalABCCompiler.TreeConverter
AddError(new LambdasNotAllowedInForeachInWhatSatetement(get_location(lambdaSearcher.FoundLambda)));
}
expression_node in_what = convert_strong(_foreach_stmt.in_what);
// SSM 29.07.16 - если in_what - одномерный массив, то заменить код foreach на for
var is1dimdynarr = false;
var comptn = in_what.type as compiled_type_node;
if (comptn != null && comptn.type_special_kind == SemanticTree.type_special_kind.array_kind && comptn.rank == 1)
{
is1dimdynarr = true;
}
if (!is1dimdynarr)
{
var comtn = in_what.type as common_type_node;
if (comtn != null && comtn.internal_type_special_kind == SemanticTree.type_special_kind.array_kind && comtn.rank == 1)
{
is1dimdynarr = true;
}
}
if (is1dimdynarr) // Замена foreach на for для массива
{
// сгенерировать код для for и вызвать соответствующий visit
var sem_expr = new semantic_addr_value(in_what); // перевод в синтаксис для мгновенного вычисления семантического выражения, которое уже вычислено в in_what
var arrid = SyntaxTreeBuilder.GenIdentName();
var vdarr = new var_def_statement(arrid, null, sem_expr);
visit(vdarr);
statement_list newbody;
if (_foreach_stmt.stmt is statement_list)
newbody = _foreach_stmt.stmt as statement_list;
else newbody = new statement_list(_foreach_stmt.stmt);
var i = SyntaxTreeBuilder.GenIdentName();
var x = _foreach_stmt.identifier;
// Возможны 3 случая:
// 1. _foreach_stmt.type_name = null - значит, переменная определена в другом месте
// 2. _foreach_stmt.type_name = no_type_foreach - значит, это for var x in a
// 3. _foreach_stmt.type_name = T - значит, это for var x: T in a
statement vd;
if (_foreach_stmt.type_name == null)
vd = new assign(x, new indexer(arrid,new expression_list(i)));
else if (_foreach_stmt.type_name is no_type_foreach)
vd = new var_statement(x, new indexer(arrid,new expression_list(i)));
else vd = new var_statement(x,_foreach_stmt.type_name, new indexer(arrid,new expression_list(i)));
newbody.AddFirst(vd);
var high = new bin_expr(new dot_node(arrid, new ident("Length")),new int32_const(1),Operators.Minus);
var fornode = new SyntaxTree.for_node(i, new int32_const(0), high, newbody, for_cycle_type.to, null, null, true);
visit(fornode);
return;
}
/// SSM 29.07.16
//throw new NotSupportedError(get_location(_foreach_stmt));
definition_node dn = null;
var_definition_node vdn = null;
statements_list sl2 = new statements_list(get_location(_foreach_stmt));
convertion_data_and_alghoritms.statement_list_stack_push(sl2);
expression_node in_what = convert_strong(_foreach_stmt.in_what);
expression_node tmp = in_what;
if (in_what is typed_expression) in_what = convert_typed_expression_to_function_call(in_what as typed_expression);
type_node elem_type = null;
@ -16538,6 +16593,9 @@ namespace PascalABCCompiler.TreeConverter
in_what = tmp;
//if (in_what.type.find_in_type("GetEnumerator") == null)
//(in_what.type as common_type_node).internal_type_special_kind == SemanticTree.type_special_kind.array_kind
//in_what.type as compiled_type_node
if (!FindIEnumerableElementType(/*_foreach_stmt, */in_what.type, ref elem_type))
//if (!IsGetEnumerator(in_what.type, ref elem_type))
AddError(in_what.location, "CAN_NOT_EXECUTE_FOREACH_BY_EXPR_OF_TYPE_{0}", in_what.type.name);

Binary file not shown.

View file

@ -8452,7 +8452,7 @@ end;
// Дополнения февраль 2016: Shuffle, AdjacentFind, IndexMin, IndexMax, Replace, Transform
// Статические методы - в методы расширения: BinarySearch, ConvertAll, Find, FindIndex, FindAll,
// FindLast, FindLastIndex, IndexOf, Contains, LastIndexOf, Reverse, Resize, Sort
// FindLast, FindLastIndex, IndexOf, Contains, LastIndexOf, Reverse, Sort
/// Перемешивает элементы массива случайным образом
function Shuffle<T>(Self: array of T): array of T; extensionmethod;
@ -8645,12 +8645,6 @@ begin
Result := System.Array.LastIndexOf(self,x,start);
end;
/// Меняет размер массива
procedure Resize<T>(self: array of T; x: integer); extensionmethod;
begin
System.Array.Resize(self,x);
end;
/// Сортирует массив по возрастанию
procedure Sort<T>(self: array of T); extensionmethod;
begin