1+ using System . Runtime . CompilerServices ;
2+ using System . Runtime . InteropServices ;
3+
14namespace MrKWatkins . Ast ;
25
36/// <summary>
@@ -11,19 +14,19 @@ namespace MrKWatkins.Ast;
1114public sealed partial class Children < TNode > : IList < TNode >
1215 where TNode : Node < TNode >
1316{
14- private readonly List < TNode > nodes ;
1517 private readonly TNode parent ;
18+ private TNode [ ] nodes ;
1619
1720 internal Children ( TNode parent )
1821 {
1922 this . parent = parent ;
20- nodes = new List < TNode > ( ) ;
23+ nodes = Array . Empty < TNode > ( ) ;
2124 }
2225
2326 internal Children ( TNode parent , [ InstantHandle ] IEnumerable < TNode > nodes )
2427 {
2528 this . parent = parent ;
26- this . nodes = nodes . ToList ( ) ;
29+ this . nodes = nodes . ToArray ( ) ;
2730 foreach ( var node in this . nodes )
2831 {
2932 node . Parent = parent ;
@@ -38,7 +41,11 @@ internal Children(TNode parent, [InstantHandle] IEnumerable<TNode> nodes)
3841 public void Add ( TNode node )
3942 {
4043 node . Parent = parent ;
41- nodes . Add ( node ) ;
44+
45+ var newNodes = new TNode [ nodes . Length + 1 ] ;
46+ Array . Copy ( nodes , newNodes , nodes . Length ) ;
47+ newNodes [ ^ 1 ] = node ;
48+ nodes = newNodes ;
4249 }
4350
4451 /// <summary>
@@ -73,7 +80,7 @@ public void Clear()
7380 node . RemoveParent ( ) ;
7481 }
7582
76- nodes . Clear ( ) ;
83+ nodes = Array . Empty < TNode > ( ) ;
7784 }
7885
7986 /// <summary>
@@ -92,9 +99,10 @@ public void Clear()
9299 /// <returns><c>true</c> if <paramref name="node" /> was in the collection and was removed, <c>false</c> otherwise.</returns>
93100 public bool Remove ( TNode node )
94101 {
95- if ( nodes . Remove ( node ) )
102+ var index = IndexOf ( node ) ;
103+ if ( index != - 1 )
96104 {
97- node . RemoveParent ( ) ;
105+ RemoveAt ( index ) ;
98106 return true ;
99107 }
100108
@@ -146,7 +154,11 @@ public void Move([InstantHandle] IEnumerable<TNode> nodes)
146154 /// <summary>
147155 /// The number of nodes in the collection.
148156 /// </summary>
149- public int Count => nodes . Count ;
157+ public int Count
158+ {
159+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
160+ get => nodes . Length ;
161+ }
150162
151163 bool ICollection < TNode > . IsReadOnly => false ;
152164
@@ -157,7 +169,7 @@ public void Move([InstantHandle] IEnumerable<TNode> nodes)
157169 /// <returns>The index of the node or -1 if it is not in the collection.</returns>
158170 public int IndexOf ( TNode node ) =>
159171 node . HasParent && ReferenceEquals ( node . Parent , parent )
160- ? nodes . IndexOf ( node )
172+ ? Array . IndexOf ( nodes , node )
161173 : - 1 ;
162174
163175 /// <summary>
@@ -170,7 +182,12 @@ public int IndexOf(TNode node) =>
170182 public void Insert ( int index , TNode node )
171183 {
172184 node . Parent = parent ;
173- nodes . Insert ( index , node ) ;
185+
186+ var newNodes = new TNode [ nodes . Length + 1 ] ;
187+ Array . Copy ( nodes , newNodes , index ) ;
188+ Array . Copy ( nodes , index , newNodes , index + 1 , nodes . Length - index ) ;
189+ newNodes [ index ] = node ;
190+ nodes = newNodes ;
174191 }
175192
176193 void IList < TNode > . RemoveAt ( int index ) => RemoveAt ( index ) ;
@@ -184,8 +201,18 @@ public void Insert(int index, TNode node)
184201 public TNode RemoveAt ( int index )
185202 {
186203 var node = nodes [ index ] ;
204+ if ( nodes . Length == 1 )
205+ {
206+ nodes = Array . Empty < TNode > ( ) ;
207+ }
208+ else
209+ {
210+ var newNodes = new TNode [ nodes . Length - 1 ] ;
211+ Array . Copy ( nodes , newNodes , index ) ;
212+ Array . Copy ( nodes , index + 1 , newNodes , index , nodes . Length - index - 1 ) ;
213+ nodes = newNodes ;
214+ }
187215 node . RemoveParent ( ) ;
188- nodes . RemoveAt ( index ) ;
189216 return node ;
190217 }
191218
@@ -391,4 +418,15 @@ public TChild SingleOfType<TChild>()
391418
392419 return single ?? throw new InvalidOperationException ( $ "Expected { parent . GetType ( ) . SimpleName ( ) } to have 1 child of type { typeof ( TChild ) . SimpleName ( ) } but found none.") ;
393420 }
421+
422+ /// <summary>
423+ /// TODO
424+ /// </summary>
425+ [ Pure ]
426+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
427+ public TNode UnsafeGet ( int index )
428+ {
429+ ref var nodesReference = ref MemoryMarshal . GetArrayDataReference ( nodes ) ;
430+ return Unsafe . Add ( ref nodesReference , index ) ;
431+ }
394432}
0 commit comments