@@ -5,16 +5,21 @@ This Source Code Form is subject to the terms of the
55at http://mozilla.org/MPL/2.0/.
66----------------------------------------------------------*/
77
8- using System . Collections . Generic ;
98using OneScript . Contexts ;
109using OneScript . Exceptions ;
1110using OneScript . Types ;
1211using OneScript . Values ;
1312using ScriptEngine . Machine ;
1413using ScriptEngine . Machine . Contexts ;
14+ using System . Collections . Generic ;
1515
1616namespace OneScript . StandardLibrary . Collections
1717{
18+ /// <summary>
19+ /// Коллекция элементов произвольного типа.
20+ /// Возможно обращение к значениям элементов по числовому индексу (нумерация начинается с 0).
21+ /// Доступен обход в цикле <c>Для Каждого Из</c>.
22+ /// </summary>
1823 [ ContextClass ( "Массив" , "Array" ) ]
1924 public class ArrayImpl : AutoCollectionContext < ArrayImpl , IValue > , IValueArray
2025 {
@@ -24,6 +29,11 @@ public ArrayImpl()
2429 {
2530 _values = new List < IValue > ( ) ;
2631 }
32+
33+ public ArrayImpl ( int capacity )
34+ {
35+ _values = new List < IValue > ( capacity ) ;
36+ }
2737
2838 public ArrayImpl ( IEnumerable < IValue > values )
2939 {
@@ -56,16 +66,23 @@ public override void SetIndexedValue(IValue index, IValue val)
5666 Set ( ( int ) index . AsNumber ( ) , val ) ;
5767 else
5868 base . SetIndexedValue ( index , val ) ;
59- }
60-
69+ }
70+
6171 #region ICollectionContext Members
62-
72+
73+ /// <summary>
74+ /// Получает количество элементов в массиве
75+ /// </summary>
76+ /// <returns>Количество элементов массива</returns>
6377 [ ContextMethod ( "Количество" , "Count" ) ]
6478 public override int Count ( )
6579 {
6680 return _values . Count ;
67- }
68-
81+ }
82+
83+ /// <summary>
84+ /// Удаляет все элементы из массива
85+ /// </summary>
6986 [ ContextMethod ( "Очистить" , "Clear" ) ]
7087 public void Clear ( )
7188 {
@@ -82,19 +99,27 @@ public override IEnumerator<IValue> GetEnumerator()
8299 {
83100 yield return item ;
84101 }
85- }
86-
102+ }
103+
87104 #endregion
88-
105+
106+ /// <summary>
107+ /// Добавляет элемент в конец массива
108+ /// </summary>
109+ /// <param name="value">Произвольный: Добавляемое значение. Если не указано, то добавляется Неопределено</param>
89110 [ ContextMethod ( "Добавить" , "Add" ) ]
90111 public void Add ( IValue value = null )
91112 {
92- if ( value == null )
93- _values . Add ( ValueFactory . Create ( ) ) ;
94- else
95- _values . Add ( value ) ;
96- }
97-
113+ _values . Add ( value ?? ValueFactory . Create ( ) ) ;
114+ }
115+
116+ /// <summary>
117+ /// Вставляет значение в массив по указанному индексу
118+ /// </summary>
119+ /// <param name="index">Число: Индекс вставляемого значения.
120+ /// Если индекс превышает размер массива, то массив дополняется элементами Неопределено до указанного индекса.
121+ /// Если индекс отрицательный, то выбрасывается исключение</param>
122+ /// <param name="value">Произвольный: Вставляемое значение. Если не указано, то вставляется Неопределено</param>
98123 [ ContextMethod ( "Вставить" , "Insert" ) ]
99124 public void Insert ( int index , IValue value = null )
100125 {
@@ -104,26 +129,27 @@ public void Insert(int index, IValue value = null)
104129 if ( index > _values . Count )
105130 Extend ( index - _values . Count ) ;
106131
107- if ( value == null )
108- _values . Insert ( index , ValueFactory . Create ( ) ) ;
109- else
110- _values . Insert ( index , value ) ;
132+ _values . Insert ( index , value ?? ValueFactory . Create ( ) ) ;
111133 }
112134
135+ /// <summary>
136+ /// Выполняет поиск элемента в массиве
137+ /// </summary>
138+ /// <param name="what">Произвольный: Искомое значение</param>
139+ /// <returns>Если элемент найден, возвращается его индекс, иначе Неопределено</returns>
113140 [ ContextMethod ( "Найти" , "Find" ) ]
114141 public IValue Find ( IValue what )
115142 {
116143 var idx = _values . FindIndex ( x => x . StrictEquals ( what ) ) ;
117- if ( idx < 0 )
118- {
119- return ValueFactory . Create ( ) ;
120- }
121- else
122- {
123- return ValueFactory . Create ( idx ) ;
124- }
125- }
126-
144+ return idx >= 0 ? ValueFactory . Create ( idx ) : ValueFactory . Create ( ) ;
145+ }
146+
147+ /// <summary>
148+ /// Удаляет значение из массива
149+ /// </summary>
150+ /// <param name="index">Число: Индекс удаляемого элемента.
151+ /// Если индекс находится за границами массива, то выбрасывается исключение
152+ /// </param>
127153 [ ContextMethod ( "Удалить" , "Delete" ) ]
128154 public void Remove ( int index )
129155 {
@@ -133,21 +159,39 @@ public void Remove(int index)
133159 _values . RemoveAt ( index ) ;
134160 }
135161
162+ /// <summary>
163+ /// Получает наибольший индекс элемента массива
164+ /// </summary>
165+ /// <returns>Наибольший индекс в массиве. Если количество элементов массива равно 0, возвращает -1</returns>
136166 [ ContextMethod ( "ВГраница" , "UBound" ) ]
137167 public int UpperBound ( )
138168 {
139169 return _values . Count - 1 ;
140- }
141-
170+ }
171+
172+ /// <summary>
173+ /// Получает значение из массива по индексу
174+ /// </summary>
175+ /// <param name="index">Число: Индекс элемента.
176+ /// Если индекс находится за границами массива, то выбрасывается исключение
177+ /// </param>
178+ /// <returns>Значение элемента массива</returns>
142179 [ ContextMethod ( "Получить" , "Get" ) ]
143180 public IValue Get ( int index )
144181 {
145182 if ( index < 0 || index >= _values . Count )
146183 throw RuntimeException . IndexOutOfRange ( ) ;
147184
148185 return _values [ index ] ;
149- }
150-
186+ }
187+
188+ /// <summary>
189+ /// Устанавливает значение в массиве по индексу
190+ /// </summary>
191+ /// <param name="index">Число: Индекс элемента.
192+ /// Если индекс находится за границами массива, то выбрасывается исключение
193+ /// </param>
194+ /// <param name="value">Произвольный: Устанавливаемое значение</param>
151195 [ ContextMethod ( "Установить" , "Set" ) ]
152196 public void Set ( int index , IValue value )
153197 {
@@ -165,20 +209,22 @@ private void Extend(int count)
165209 }
166210 }
167211
168- private static void FillArray ( ArrayImpl currentArray , int bound )
212+ private static ArrayImpl CreateArray ( int bound )
169213 {
214+ var array = new ArrayImpl ( bound ) ;
170215 for ( int i = 0 ; i < bound ; i ++ )
171216 {
172- currentArray . _values . Add ( ValueFactory . Create ( ) ) ;
217+ array . _values . Add ( ValueFactory . Create ( ) ) ;
173218 }
219+ return array ;
174220 }
175221
176- private static IValue CloneArray ( ArrayImpl cloneable )
222+ private static ArrayImpl CloneArray ( ArrayImpl cloneable )
177223 {
178- ArrayImpl clone = new ArrayImpl ( ) ;
224+ ArrayImpl clone = new ArrayImpl ( cloneable . _values . Count ) ;
179225 foreach ( var item in cloneable . _values )
180226 {
181- clone . _values . Add ( item ?? ValueFactory . Create ( ) ) ;
227+ clone . _values . Add ( item is ArrayImpl arr ? CloneArray ( arr ) : item ) ;
182228 }
183229 return clone ;
184230 }
@@ -198,35 +244,37 @@ public static ArrayImpl Constructor()
198244 public static ArrayImpl Constructor ( IValue [ ] dimensions )
199245 {
200246 if ( dimensions . Length == 1 && dimensions [ 0 ] is FixedArrayImpl fa )
201- {
202- return Constructor ( fa ) ;
247+ {
248+ return Constructor ( fa ) ;
203249 }
204-
205- ArrayImpl cloneable = null ;
206- for ( int dim = dimensions . Length - 1 ; dim >= 0 ; dim -- )
250+
251+ // fail fast
252+ int size = 0 ;
253+ for ( int dim = 0 ; dim < dimensions . Length ; dim ++ )
207254 {
208255 if ( dimensions [ dim ] == null )
209- throw RuntimeException . InvalidNthArgumentType ( dim + 1 ) ;
210-
211- int bound = ( int ) dimensions [ dim ] . AsNumber ( ) ;
212- if ( bound <= 0 )
256+ throw RuntimeException . InvalidNthArgumentType ( dim + 1 ) ;
257+
258+ size = ( int ) dimensions [ dim ] . AsNumber ( ) ;
259+ if ( size <= 0 )
213260 throw RuntimeException . InvalidNthArgumentValue ( dim + 1 ) ;
214-
215- var newInst = new ArrayImpl ( ) ;
216- FillArray ( newInst , bound ) ;
217- if ( cloneable != null )
218- {
219- for ( int i = 0 ; i < bound ; i ++ )
220- {
221- newInst . _values [ i ] = CloneArray ( cloneable ) ;
222- }
223- }
224- cloneable = newInst ;
225-
261+ }
262+
263+ var newInst = CreateArray ( size ) ; // длина по последней размерности
264+
265+ for ( int dim = dimensions . Length - 2 ; dim >= 0 ; dim -- ) // если размерность >= 2
266+ {
267+ ArrayImpl nested = newInst ;
268+ int bound = ( int ) dimensions [ dim ] . AsNumber ( ) ;
269+
270+ newInst = new ArrayImpl ( bound ) ;
271+ for ( int i = 0 ; i < bound ; i ++ )
272+ {
273+ newInst . _values . Add ( CloneArray ( nested ) ) ;
274+ }
226275 }
227276
228- return cloneable ;
229-
277+ return newInst ;
230278 }
231279
232280 [ ScriptConstructor ( Name = "На основании фиксированного массива" ) ]
0 commit comments