Skip to content

Commit

Permalink
Implement System.Array constructor with base arg
Browse files Browse the repository at this point in the history
  • Loading branch information
BCSharp authored and slozier committed Dec 5, 2024
1 parent 8504f29 commit 84de081
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 10 deletions.
16 changes: 10 additions & 6 deletions Src/IronPython/Runtime/Operations/ArrayOps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,23 @@ public static object __new__(CodeContext context, PythonType pythonType, ICollec
}

[StaticExtensionMethod]
public static object __new__(CodeContext context, PythonType pythonType, object items) {
public static object __new__(CodeContext context, PythonType pythonType, object items)
=> __new__(context, pythonType, items, @base: 0);

[StaticExtensionMethod]
public static object __new__(CodeContext context, PythonType pythonType, object items, /*[KeywordOnly]*/ int @base) {
Type type = pythonType.UnderlyingSystemType.GetElementType()!;

object? lenFunc;
if (!PythonOps.TryGetBoundAttr(items, "__len__", out lenFunc))
if (!PythonOps.TryGetBoundAttr(items, "__len__", out object? lenFunc))
throw PythonOps.TypeErrorForBadInstance("expected object with __len__ function, got {0}", items);

int len = context.LanguageContext.ConvertToInt32(PythonOps.CallWithContext(context, lenFunc));

Array res = Array.CreateInstance(type, len);
Array res = @base == 0 ?
Array.CreateInstance(type, len) : Array.CreateInstance(type, [len], [@base]);

IEnumerator ie = PythonOps.GetEnumerator(items);
int i = 0;
int i = @base;
while (ie.MoveNext()) {
res.SetValue(Converter.Convert(ie.Current, type), i++);
}
Expand Down Expand Up @@ -277,7 +281,7 @@ public static string __repr__(CodeContext/*!*/ context, [NotNone] Array/*!*/ sel
}
ret.Append(')');
if (self.GetLowerBound(0) != 0) {
ret.Append(", base: ");
ret.Append(", base=");
ret.Append(self.GetLowerBound(0));
}
ret.Append(')');
Expand Down
26 changes: 22 additions & 4 deletions Tests/test_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,26 @@ def test_constructor(self):
for y in range(array3.GetLength(1)):
self.assertEqual(array3[x, y], 0)

def test_constructor_nonzero_lowerbound(self):
# 1-based
arr = System.Array[int]((1, 2), base=1)
self.assertEqual(arr.Rank, 1)
self.assertEqual(arr.Length, 2)
self.assertEqual(arr.GetLowerBound(0), 1)
self.assertEqual(arr.GetUpperBound(0), 2)
self.assertEqual(arr[1], 1)
self.assertEqual(arr[2], 2)
for i in range(1, 3):
self.assertEqual(arr[i], i)

def test_repr(self):
from System import Array
arr = Array[int]((5, 1), base=1)
s = repr(arr)
self.assertEqual(s, "Array[int]((5, 1), base=1)")
array4eval = eval(s, globals(), locals())
self.assertEqual(arr, array4eval)

def test_nonzero_lowerbound(self):
a = System.Array.CreateInstance(int, (5,), (5,))
for i in range(5, 5 + a.Length): a[i] = i
Expand All @@ -210,7 +230,7 @@ def test_nonzero_lowerbound(self):
self.assertEqual(a[-1:-3:-1], System.Array[int]((9,8)))
self.assertEqual(a[-1], 9)

self.assertEqual(repr(a), 'Array[int]((5, 6, 7, 8, 9), base: 5)')
self.assertEqual(repr(a), 'Array[int]((5, 6, 7, 8, 9), base=5)')

a = System.Array.CreateInstance(int, (5,), (15,))
b = System.Array.CreateInstance(int, (5,), (20,))
Expand Down Expand Up @@ -322,9 +342,7 @@ def test_base_negative(self):

# test slice indexing
# 1-dim array [-1, 0, 1]
arr1 = System.Array.CreateInstance(int, (3,), (-1,))
for i in range(-1, 2):
arr1[i] = i
arr1 = System.Array[int]((-1, 0, 1), base=-1)
self.assertEqual(arr1[-1:1], System.Array[int]((-1, 0)))
self.assertEqual(arr1[-2:1], System.Array[int]((-1, 0)))
self.assertEqual(arr1[0:], System.Array[int]((0, 1)))
Expand Down

0 comments on commit 84de081

Please sign in to comment.