From 9da9308c30a75cdea6bee45f20777d9289c979ef Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Sun, 5 Apr 2026 02:33:48 +0400 Subject: [PATCH 1/4] =?UTF-8?q?fix=20#1663:=20=D0=BA=D0=BB=D0=BE=D0=BD?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=BD?= =?UTF-8?q?=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D0=B9=20=D0=BC=D0=BD=D0=BE=D0=B3?= =?UTF-8?q?=D0=BE=D0=BC=D0=B5=D1=80=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BC=D0=B0?= =?UTF-8?q?=D1=81=D1=81=D0=B8=D0=B2=D0=B0=20+=D1=82=D0=B5=D1=81=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Collections/ArrayImpl.cs | 65 +++++++++++-------- tests/array.os | 65 +++++++++++++++++++ 2 files changed, 102 insertions(+), 28 deletions(-) create mode 100644 tests/array.os diff --git a/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs b/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs index 388125736..61ddf6e7d 100644 --- a/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs @@ -5,13 +5,14 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ -using System.Collections.Generic; using OneScript.Contexts; using OneScript.Exceptions; using OneScript.Types; using OneScript.Values; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; +using System; +using System.Collections.Generic; namespace OneScript.StandardLibrary.Collections { @@ -24,6 +25,11 @@ public ArrayImpl() { _values = new List(); } + + public ArrayImpl(int size) + { + _values = new List(size); + } public ArrayImpl(IEnumerable values) { @@ -165,20 +171,20 @@ private void Extend(int count) } } - private static void FillArray(ArrayImpl currentArray, int bound) + private static void FillArray(ArrayImpl array, int bound) { for (int i = 0; i < bound; i++) { - currentArray._values.Add(ValueFactory.Create()); + array._values.Add(ValueFactory.Create()); } } private static IValue CloneArray(ArrayImpl cloneable) { - ArrayImpl clone = new ArrayImpl(); + ArrayImpl clone = new ArrayImpl(cloneable._values.Count); foreach (var item in cloneable._values) { - clone._values.Add(item ?? ValueFactory.Create()); + clone._values.Add(item is ArrayImpl arr ? CloneArray(arr) : item ); } return clone; } @@ -198,35 +204,38 @@ public static ArrayImpl Constructor() public static ArrayImpl Constructor(IValue[] dimensions) { if (dimensions.Length == 1 && dimensions[0] is FixedArrayImpl fa) - { - return Constructor(fa); + { + return Constructor(fa); } - - ArrayImpl cloneable = null; - for (int dim = dimensions.Length - 1; dim >= 0; dim--) + + // fail fast + for (int dim = 0; dim < dimensions.Length; dim++) { if (dimensions[dim] == null) - throw RuntimeException.InvalidNthArgumentType(dim + 1); - - int bound = (int)dimensions[dim].AsNumber(); - if (bound <= 0) + throw RuntimeException.InvalidNthArgumentType(dim + 1); + + if ((int)dimensions[dim].AsNumber() <= 0) throw RuntimeException.InvalidNthArgumentValue(dim + 1); - - var newInst = new ArrayImpl(); - FillArray(newInst, bound); - if(cloneable != null) - { - for (int i = 0; i < bound; i++) - { - newInst._values[i] = CloneArray(cloneable); - } - } - cloneable = newInst; - + } + + int bound = (int)dimensions[^1].AsNumber(); + var newInst = new ArrayImpl(bound); + FillArray(newInst, bound); + + ArrayImpl nested; + for (int dim = dimensions.Length - 2; dim >= 0; dim--) // если размерность >= 2 + { + nested = newInst; + bound = (int)dimensions[dim].AsNumber(); + + newInst = new ArrayImpl(bound); + for (int i = 0; i < bound; i++) + { + newInst._values.Add(CloneArray(nested)); + } } - return cloneable; - + return newInst; } [ScriptConstructor(Name = "На основании фиксированного массива")] diff --git a/tests/array.os b/tests/array.os new file mode 100644 index 000000000..329955c6a --- /dev/null +++ b/tests/array.os @@ -0,0 +1,65 @@ +#Использовать asserts + +/////////////////////////////////////////////////////////////////////// +// Тест класса Массив +/////////////////////////////////////////////////////////////////////// + +Перем юТест; + +//////////////////////////////////////////////////////////////////// +// Программный интерфейс + +Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт + + юТест = ЮнитТестирование; + + ВсеТесты = Новый Массив; + + ВсеТесты.Добавить("ТестДолжен_СоздатьМногомерныйМассив"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьЗаписьВМногомерныйМассив"); // issue #1663 + ВсеТесты.Добавить("ТестДолжен_ПроверитьОшибкуРазмерности"); + + Возврат ВсеТесты; + +КонецФункции + +Процедура ТестДолжен_СоздатьМногомерныйМассив() Экспорт + + Массив = Новый Массив(2,4,6,8); + + Ожидаем.Что(Массив.Количество(), "1-я размерность").Равно(2); + Ожидаем.Что(Массив[0].Количество(), "2-я размерность").Равно(4); + Ожидаем.Что(Массив[1][1].Количество(), "3-я размерность").Равно(6); + Ожидаем.Что(Массив[1][1][2].Количество(), "4-я размерность").Равно(8); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьЗаписьВМногомерныйМассив() Экспорт + + Массив = Новый Массив(3,3,3); + Массив[0][0][0] = "Привет"; + Массив[1][0][0] = "Привет."; + Массив[1][1][0] = "Привет!"; + Массив[2][0][0] = "Привет!!!"; + + Ожидаем.Что(Массив[0][0][0]).Равно("Привет"); + Ожидаем.Что(Массив[1][0][0]).Равно("Привет."); + Ожидаем.Что(Массив[1][1][0]).Равно("Привет!"); + Ожидаем.Что(Массив[2][0][0]).Равно("Привет!!!"); + Ожидаем.Что(Массив[2][1][0]).Равно(Неопределено); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьОшибкуРазмерности() Экспорт + + Попытка + Массив = Новый Массив(-1,-2,-3); + Исключение + Ошибка = ИнформацияОбОшибке().Описание; + юТест.ПроверитьНеРавенство(Найти(Ошибка,"Неверное значение аргумента номер 1"), 0, "Неверный вид ошибки: "+Ошибка); // не "номер 3"! + Возврат; + КонецПопытки; + + ВызватьИсключение "Должно было быть выдано исключение, но его не было"; + +КонецПроцедуры \ No newline at end of file From f4264102d3682ee5429b59ba6f05235f2d2ae144 Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Sun, 5 Apr 2026 15:51:05 +0400 Subject: [PATCH 2/4] =?UTF-8?q?=D0=BA=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82?= =?UTF-8?q?=D0=BD=D0=BE=D0=B5=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=BC=D0=B0=D1=81=D1=81=D0=B8=D0=B2=D0=B0=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=B4=D0=B0=D0=BD=D0=BD=D0=BE=D0=B9=20=D0=B4=D0=BB=D0=B8?= =?UTF-8?q?=D0=BD=D1=8B;=20=D1=80=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Collections/ArrayImpl.cs | 39 +++++++------------ tests/array.os | 26 +++++++++++++ 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs b/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs index 61ddf6e7d..be80d9125 100644 --- a/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs @@ -11,7 +11,6 @@ This Source Code Form is subject to the terms of the using OneScript.Values; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; -using System; using System.Collections.Generic; namespace OneScript.StandardLibrary.Collections @@ -95,10 +94,7 @@ public override IEnumerator GetEnumerator() [ContextMethod("Добавить", "Add")] public void Add(IValue value = null) { - if (value == null) - _values.Add(ValueFactory.Create()); - else - _values.Add(value); + _values.Add(value ?? ValueFactory.Create()); } [ContextMethod("Вставить", "Insert")] @@ -110,24 +106,14 @@ public void Insert(int index, IValue value = null) if (index > _values.Count) Extend(index - _values.Count); - if (value == null) - _values.Insert(index, ValueFactory.Create()); - else - _values.Insert(index, value); + _values.Insert(index, value ?? ValueFactory.Create()); } [ContextMethod("Найти", "Find")] public IValue Find(IValue what) { var idx = _values.FindIndex(x => x.StrictEquals(what)); - if(idx < 0) - { - return ValueFactory.Create(); - } - else - { - return ValueFactory.Create(idx); - } + return idx>=0 ? ValueFactory.Create(idx) : ValueFactory.Create(); } [ContextMethod("Удалить", "Delete")] @@ -171,15 +157,17 @@ private void Extend(int count) } } - private static void FillArray(ArrayImpl array, int bound) + private static ArrayImpl CreateArray(int bound) { + var array = new ArrayImpl(bound); for (int i = 0; i < bound; i++) { array._values.Add(ValueFactory.Create()); } + return array; } - private static IValue CloneArray(ArrayImpl cloneable) + private static ArrayImpl CloneArray(ArrayImpl cloneable) { ArrayImpl clone = new ArrayImpl(cloneable._values.Count); foreach (var item in cloneable._values) @@ -209,24 +197,23 @@ public static ArrayImpl Constructor(IValue[] dimensions) } // fail fast + int size = 0; for (int dim = 0; dim < dimensions.Length; dim++) { if (dimensions[dim] == null) throw RuntimeException.InvalidNthArgumentType(dim + 1); - if ((int)dimensions[dim].AsNumber() <= 0) + size = (int)dimensions[dim].AsNumber(); + if (size <= 0) throw RuntimeException.InvalidNthArgumentValue(dim + 1); } - int bound = (int)dimensions[^1].AsNumber(); - var newInst = new ArrayImpl(bound); - FillArray(newInst, bound); + var newInst = CreateArray(size); // длина по последней размерности - ArrayImpl nested; for (int dim = dimensions.Length - 2; dim >= 0; dim--) // если размерность >= 2 { - nested = newInst; - bound = (int)dimensions[dim].AsNumber(); + ArrayImpl nested = newInst; + int bound = (int)dimensions[dim].AsNumber(); newInst = new ArrayImpl(bound); for (int i = 0; i < bound; i++) diff --git a/tests/array.os b/tests/array.os index 329955c6a..6d2bd49a2 100644 --- a/tests/array.os +++ b/tests/array.os @@ -15,6 +15,7 @@ ВсеТесты = Новый Массив; + ВсеТесты.Добавить("ТестДолжен_ПроверитьПоискВМассиве"); ВсеТесты.Добавить("ТестДолжен_СоздатьМногомерныйМассив"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЗаписьВМногомерныйМассив"); // issue #1663 ВсеТесты.Добавить("ТестДолжен_ПроверитьОшибкуРазмерности"); @@ -23,6 +24,31 @@ КонецФункции +Процедура ТестДолжен_ПроверитьПоискВМассиве() Экспорт + + Массив = Новый Массив(); + Массив.Добавить("1"); + Массив.Добавить("2"); + Массив.Добавить("3"); + + Если Массив.Найти("1") <> Неопределено Тогда + НашлиЗначение1 = Истина; + Иначе + НашлиЗначение1 = Ложь; + КонецЕсли; + + Если Массив.Найти("9") <> Неопределено Тогда + НашлиЗначение9 = Истина; + Иначе + НашлиЗначение9 = Ложь; + КонецЕсли; + + юТест.ПроверитьРавенство(НашлиЗначение1, Истина, "Нашли 1"); + юТест.ПроверитьРавенство(НашлиЗначение9, Ложь, "Не нашли 9"); + юТест.ПроверитьРавенство(Массив.Найти("2"), 1, "Индекс элемента по значению"); + +КонецПроцедуры + Процедура ТестДолжен_СоздатьМногомерныйМассив() Экспорт Массив = Новый Массив(2,4,6,8); From 24a9f27e7ffb51cc076f70f3ef441a021a51eb01 Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Sun, 5 Apr 2026 16:33:40 +0400 Subject: [PATCH 3/4] =?UTF-8?q?=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=BE=D0=B2=20=D0=BE?= =?UTF-8?q?=D0=B1=D1=8A=D0=B5=D0=BA=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Collections/ArrayImpl.cs | 84 +++++++++++++++---- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs b/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs index be80d9125..a0e6244d1 100644 --- a/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs @@ -15,6 +15,11 @@ This Source Code Form is subject to the terms of the namespace OneScript.StandardLibrary.Collections { + /// + /// Коллекция элементов произвольного типа. + /// Возможно обращение к значениям элементов по числовому индексу (нумерация начинается с 0). + /// Доступен обход в цикле Для Каждого Из. + /// [ContextClass("Массив", "Array")] public class ArrayImpl : AutoCollectionContext, IValueArray { @@ -61,16 +66,23 @@ public override void SetIndexedValue(IValue index, IValue val) Set((int)index.AsNumber(), val); else base.SetIndexedValue(index, val); - } - + } + #region ICollectionContext Members - + + /// + /// Получает количество элементов в массиве + /// + /// Количество элементов массива [ContextMethod("Количество", "Count")] public override int Count() { return _values.Count; - } - + } + + /// + /// Удаляет все элементы из массива + /// [ContextMethod("Очистить", "Clear")] public void Clear() { @@ -87,16 +99,27 @@ public override IEnumerator GetEnumerator() { yield return item; } - } - + } + #endregion - + + /// + /// Добавляет элемент в конец массива + /// + /// Произвольный: Добавляемое значение. Если не указано, то добавляется Неопределено [ContextMethod("Добавить", "Add")] public void Add(IValue value = null) { _values.Add(value ?? ValueFactory.Create()); - } - + } + + /// + /// Вставляет значение в массив по указанному индексу + /// + /// Число: Индекс вставляемого значения. + /// Если индекс превышает размер массива, то массив дополняется элементами Неопределено до указанного индекса. + /// Если индекс отрицательный, то выбрасывается исключение + /// Произвольный: Вставляемое значение. Если не указано, то вставляется Неопределено [ContextMethod("Вставить", "Insert")] public void Insert(int index, IValue value = null) { @@ -109,13 +132,24 @@ public void Insert(int index, IValue value = null) _values.Insert(index, value ?? ValueFactory.Create()); } + /// + /// Выполняет поиск элемента в массиве + /// + /// Произвольный: Искомое значение + /// Если элемент найден, возвращается его индекс, иначе Неопределено [ContextMethod("Найти", "Find")] public IValue Find(IValue what) { var idx = _values.FindIndex(x => x.StrictEquals(what)); return idx>=0 ? ValueFactory.Create(idx) : ValueFactory.Create(); - } - + } + + /// + /// Удаляет значение из массива + /// + /// Число: Индекс удаляемого элемента. + /// Если индекс находится за границами массива, то выбрасывается исключение + /// [ContextMethod("Удалить", "Delete")] public void Remove(int index) { @@ -125,12 +159,23 @@ public void Remove(int index) _values.RemoveAt(index); } + /// + /// Получает наибольший индекс элемента массива + /// + /// Наибольший индекс в массиве. Если количество элементов массива равно 0, возвращает -1 [ContextMethod("ВГраница", "UBound")] public int UpperBound() { return _values.Count - 1; - } - + } + + /// + /// Получает значение из массива по индексу + /// + /// Число: Индекс элемента. + /// Если индекс находится за границами массива, то выбрасывается исключение + /// + /// Значение элемента массива [ContextMethod("Получить", "Get")] public IValue Get(int index) { @@ -138,8 +183,15 @@ public IValue Get(int index) throw RuntimeException.IndexOutOfRange(); return _values[index]; - } - + } + + /// + /// Устанавливает значение в массиве по индексу + /// + /// Число: Индекс элемента. + /// Если индекс находится за границами массива, то выбрасывается исключение + /// + /// Произвольный: Устанавливаемое значение [ContextMethod("Установить", "Set")] public void Set(int index, IValue value) { From dedad2045f1b1210ca71121583f500cb7d0a5004 Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Sun, 5 Apr 2026 16:52:11 +0400 Subject: [PATCH 4/4] =?UTF-8?q?=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=BE=D0=BD=D1=81?= =?UTF-8?q?=D1=82=D1=80=D1=83=D0=BA=D1=82=D0=BE=D1=80=D0=B0=20=D0=BC=D0=B0?= =?UTF-8?q?=D1=81=D1=81=D0=B8=D0=B2=D0=B0=20=D1=81=20=D1=80=D0=B5=D0=B7?= =?UTF-8?q?=D0=B5=D1=80=D0=B2=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=D0=BC=20=D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/OneScript.StandardLibrary/Collections/ArrayImpl.cs | 4 ++-- .../Collections/ValueTable/ValueTable.cs | 2 +- .../Collections/ValueTree/ValueTreeRowCollection.cs | 2 +- src/OneScript.StandardLibrary/SystemEnvironmentContext.cs | 2 +- src/OneScript.StandardLibrary/Tasks/BackgroundTasksManager.cs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs b/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs index a0e6244d1..b3f3945bc 100644 --- a/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/ArrayImpl.cs @@ -30,9 +30,9 @@ public ArrayImpl() _values = new List(); } - public ArrayImpl(int size) + public ArrayImpl(int capacity) { - _values = new List(size); + _values = new List(capacity); } public ArrayImpl(IEnumerable values) diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs index 3fdbff358..f3cfcd92d 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs @@ -149,7 +149,7 @@ public void LoadColumn(IValue values, IValue columnIndex) [ContextMethod("ВыгрузитьКолонку", "UnloadColumn")] public ArrayImpl UnloadColumn(IValue column) { - var result = new ArrayImpl(); + var result = new ArrayImpl(_rows.Count); foreach (var row in _rows) { diff --git a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRowCollection.cs b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRowCollection.cs index 10a1c8259..077de1ae2 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRowCollection.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRowCollection.cs @@ -146,7 +146,7 @@ public void LoadColumn(ArrayImpl values, IValue columnIndex) [ContextMethod("ВыгрузитьКолонку", "UnloadColumn")] public ArrayImpl UnloadColumn(IValue column) { - ArrayImpl result = new ArrayImpl(); + ArrayImpl result = new ArrayImpl(_rows.Count); foreach (ValueTreeRow row in _rows) { diff --git a/src/OneScript.StandardLibrary/SystemEnvironmentContext.cs b/src/OneScript.StandardLibrary/SystemEnvironmentContext.cs index 57b74b6b2..57a3f4c81 100644 --- a/src/OneScript.StandardLibrary/SystemEnvironmentContext.cs +++ b/src/OneScript.StandardLibrary/SystemEnvironmentContext.cs @@ -172,8 +172,8 @@ public FixedArrayImpl GetLogicalDrives { get { - var arr = new ArrayImpl(); var data = Environment.GetLogicalDrives(); + var arr = new ArrayImpl(data.Length); foreach (var itm in data) { arr.Add(ValueFactory.Create(itm)); diff --git a/src/OneScript.StandardLibrary/Tasks/BackgroundTasksManager.cs b/src/OneScript.StandardLibrary/Tasks/BackgroundTasksManager.cs index 9999dd86c..98aec99f1 100644 --- a/src/OneScript.StandardLibrary/Tasks/BackgroundTasksManager.cs +++ b/src/OneScript.StandardLibrary/Tasks/BackgroundTasksManager.cs @@ -135,7 +135,7 @@ public void WaitCompletionOfTasks() public ArrayImpl GetBackgroundJobs(StructureImpl filter = default) { if(filter == default) - return new ArrayImpl(_tasks.ToArray()); + return new ArrayImpl(_tasks); var arr = new ArrayImpl(); foreach (var task in _tasks)