Skip to content

Commit ce576c5

Browse files
authored
#71 - оптимизация GetAllNodes (#145)
* оптимизировал метод GetAllNodes * fix code * add link tg post * small fix
1 parent d49a3b1 commit ce576c5

File tree

2 files changed

+67
-9
lines changed

2 files changed

+67
-9
lines changed

src/Domain/HydraScript.Domain.FrontEnd/Parser/Impl/Ast/AbstractSyntaxTreeNode.cs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections;
2+
using System.Runtime.CompilerServices;
23

34
namespace HydraScript.Domain.FrontEnd.Parser.Impl.Ast;
45

@@ -22,24 +23,18 @@ public virtual void InitScope(Scope? scope = null)
2223
protected virtual IReadOnlyList<IAbstractSyntaxTreeNode> Children { get; } = [];
2324

2425
public IEnumerator<IAbstractSyntaxTreeNode> GetEnumerator() =>
25-
Children.ToList().GetEnumerator();
26+
Children.GetEnumerator();
2627

2728
IEnumerator IEnumerable.GetEnumerator() =>
28-
GetEnumerator();
29+
Children.GetEnumerator();
2930

3031
public int Count => Children.Count;
3132

3233
public IAbstractSyntaxTreeNode this[int index] =>
3334
Children[index];
3435

35-
public IReadOnlyList<IAbstractSyntaxTreeNode> GetAllNodes()
36-
{
37-
List<IAbstractSyntaxTreeNode> result = [this];
38-
for (var index = 0; index < Children.Count; index++)
39-
result.AddRange(Children[index].GetAllNodes());
36+
public IReadOnlyList<IAbstractSyntaxTreeNode> GetAllNodes() => new TraverseEnumerator(this).ToList();
4037

41-
return result;
42-
}
4338

4439
/// <summary>
4540
/// Метод возвращает <c>true</c>, если узел - потомок заданного типа и выполняется заданное условие.<br/>
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using System.Collections;
2+
using System.Runtime.CompilerServices;
3+
4+
namespace HydraScript.Domain.FrontEnd.Parser.Impl.Ast
5+
{
6+
/// <summary>
7+
/// Post in Telegram: https://t.me/csharp_gepard/89
8+
/// </summary>
9+
internal struct TraverseEnumerator :
10+
IEnumerator<IAbstractSyntaxTreeNode>,
11+
IEnumerable<IAbstractSyntaxTreeNode>
12+
{
13+
[ThreadStatic] private static Stack<IAbstractSyntaxTreeNode>? _buffer;
14+
15+
private IAbstractSyntaxTreeNode _current;
16+
public IAbstractSyntaxTreeNode Current
17+
{
18+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
19+
get => _current;
20+
}
21+
22+
private readonly Stack<IAbstractSyntaxTreeNode> _stack;
23+
public TraverseEnumerator(IAbstractSyntaxTreeNode parent)
24+
{
25+
var stack = _buffer ?? new Stack<IAbstractSyntaxTreeNode>(128);
26+
_buffer = null;
27+
28+
for (int i = 0; i < parent.Count; i++)
29+
stack.Push(parent[i]);
30+
31+
_stack = stack;
32+
_current = null!;
33+
}
34+
public bool MoveNext()
35+
{
36+
var stack = _stack;
37+
if (stack.Count == 0)
38+
return false;
39+
40+
var current = _stack.Pop();
41+
42+
for(int i=0; i< current.Count; i++)
43+
stack.Push(current[i]);
44+
45+
_current = current;
46+
return true;
47+
}
48+
49+
public void Dispose()
50+
{
51+
_stack.Clear();
52+
_buffer = _stack;
53+
}
54+
55+
public void Reset() { }
56+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
57+
public IEnumerator<IAbstractSyntaxTreeNode> GetEnumerator() => this;
58+
59+
IEnumerator IEnumerable.GetEnumerator() => this;
60+
61+
object IEnumerator.Current => Current;
62+
}
63+
}

0 commit comments

Comments
 (0)