Skip to content

Commit cfb39d9

Browse files
Implement System.Collections.Generic in TinyCoreLib (#1262)
* Implement System.Collections.Generic classes Signed-off-by: AnErrupTion <anerruption@disroot.org> * Add Mosa.UnitTests.TinyCoreLib project + tests Signed-off-by: AnErrupTion <anerruption@disroot.org> --------- Signed-off-by: AnErrupTion <anerruption@disroot.org> Co-authored-by: Stefan Charsley <charsleysa@gmail.com>
1 parent 747031b commit cfb39d9

29 files changed

+2776
-711
lines changed

Source/Mosa.Linux.sln

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Microsoft Visual Studio Solution File, Format Version 12.00
1+
Microsoft Visual Studio Solution File, Format Version 12.00
22
# Visual Studio Version 17
33
VisualStudioVersion = 17.0.31912.275
44
MinimumVisualStudioVersion = 12.0.31101.0
@@ -235,6 +235,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mosa.Utility.CreateCoreLib"
235235
EndProject
236236
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mosa.TinyCoreLib", "Mosa.TinyCoreLib\Mosa.TinyCoreLib.csproj", "{844037C4-B018-4AD0-8237-BAE46E024994}"
237237
EndProject
238+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mosa.UnitTests.TinyCoreLib", "Mosa.UnitTests.TinyCoreLib\Mosa.UnitTests.TinyCoreLib.csproj", "{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}"
239+
EndProject
238240
Global
239241
GlobalSection(SolutionConfigurationPlatforms) = preSolution
240242
Debug|Any CPU = Debug|Any CPU
@@ -1347,6 +1349,24 @@ Global
13471349
{844037C4-B018-4AD0-8237-BAE46E024994}.Release|Mixed Platforms.Build.0 = Release|Any CPU
13481350
{844037C4-B018-4AD0-8237-BAE46E024994}.Release|x86.ActiveCfg = Release|Any CPU
13491351
{844037C4-B018-4AD0-8237-BAE46E024994}.Release|x86.Build.0 = Release|Any CPU
1352+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1353+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
1354+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
1355+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
1356+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Debug|x86.ActiveCfg = Debug|Any CPU
1357+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Debug|x86.Build.0 = Debug|Any CPU
1358+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Description|Any CPU.ActiveCfg = Debug|Any CPU
1359+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Description|Any CPU.Build.0 = Debug|Any CPU
1360+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Description|Mixed Platforms.ActiveCfg = Debug|Any CPU
1361+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Description|Mixed Platforms.Build.0 = Debug|Any CPU
1362+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Description|x86.ActiveCfg = Debug|Any CPU
1363+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Description|x86.Build.0 = Debug|Any CPU
1364+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
1365+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Release|Any CPU.Build.0 = Release|Any CPU
1366+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
1367+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
1368+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Release|x86.ActiveCfg = Release|Any CPU
1369+
{F74513A5-E5B4-4ABC-9E8B-999EC55FCFC6}.Release|x86.Build.0 = Release|Any CPU
13501370
EndGlobalSection
13511371
GlobalSection(SolutionProperties) = preSolution
13521372
HideSolutionNode = FALSE

Source/Mosa.TinyCoreLib/Internal/Exceptions.cs

Lines changed: 70 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,79 @@ namespace Internal;
66

77
internal static class Exceptions
88
{
9-
public const string Exception = "An exception was thrown.";
10-
public const string PlatformNotSupportedException = "The platform is not supported.";
11-
public const string InvalidOperationException = "The requested operation cannot be performed.";
12-
public const string NotSupportedException = "The operation is not supported.";
13-
public const string NotImplementedException = "The operation is not implemented.";
14-
public const string RankException = "Attempted to operate on an array with an incorrect number of dimensions.";
15-
public const string ArgumentException = "The value does not fall within the expected range.";
16-
public const string ArithmeticException = "An arithmetic, casting, or conversion error occured.";
17-
public const string SystemException = "A system exception was thrown.";
18-
public const string OverflowException = "A checked arithmetic, casting, or conversion operation resulted in an overflow.";
19-
public const string FormatException = "An invalid format argument was passed, or a composite format string is malformed.";
20-
public const string IndexOutOfRangeException = "The index was outside the bounds of the array.";
21-
public const string ArgumentNullException = "The argument cannot be null.";
22-
public const string ArgumentOutOfRangeException = "The argument is out of range.";
23-
public const string ObjectDisposedException = "The object was used after being disposed.";
24-
public const string TypeLoadException = "A failure has occured while loading a type.";
9+
public const string Exception = "An exception was thrown.";
10+
public const string PlatformNotSupportedException = "The platform is not supported.";
11+
public const string InvalidOperationException = "The requested operation cannot be performed.";
12+
public const string NotSupportedException = "The operation is not supported.";
13+
public const string NotImplementedException = "The operation is not implemented.";
14+
public const string RankException = "Attempted to operate on an array with an incorrect number of dimensions.";
15+
public const string ArgumentException = "The value does not fall within the expected range.";
16+
public const string ArithmeticException = "An arithmetic, casting, or conversion error occured.";
17+
public const string SystemException = "A system exception was thrown.";
18+
public const string OverflowException = "A checked arithmetic, casting, or conversion operation resulted in an overflow.";
19+
public const string FormatException = "An invalid format argument was passed, or a composite format string is malformed.";
20+
public const string IndexOutOfRangeException = "The index was outside the bounds of the array.";
21+
public const string ArgumentNullException = "The argument cannot be null.";
22+
public const string ArgumentOutOfRangeException = "The argument is out of range.";
23+
public const string ObjectDisposedException = "The object was used after being disposed.";
24+
public const string TypeLoadException = "A failure has occured while loading a type.";
2525

2626
public static class Generic
2727
{
2828
[DoesNotReturn] public static void ParameterOutOfRange(string name) => throw new ArgumentOutOfRangeException(name);
29+
[DoesNotReturn] public static void ThrowMultiDimensionalArrayException(string name) => throw new ArgumentException("The array has more than one dimension.", name);
30+
[DoesNotReturn] public static void ThrowArrayNotZeroBasedIndexingException(string name) => throw new ArgumentException("The array doesn't use zero-based indexing.", name);
31+
[DoesNotReturn] public static void ThrowArrayTypeMismatchException(string name) => throw new ArgumentException("The array's element type doesn't match the collection's element type.", name);
32+
}
33+
34+
public static class LinkedList
35+
{
36+
public static class Enumerator
37+
{
38+
[DoesNotReturn] public static void ThrowListModifiedException() => throw new InvalidOperationException("The list was modified after the enumerator was created.");
39+
}
40+
41+
[DoesNotReturn] public static void ThrowNodeNotInListException() => throw new InvalidOperationException("The node is not in the list.");
42+
[DoesNotReturn] public static void ThrowNewNodeInAnotherListException() => throw new InvalidOperationException("The new node is already in another list.");
43+
[DoesNotReturn] public static void ThrowListTooBigException(string name) => throw new ArgumentException("The list is too big for the destination array.", name);
44+
[DoesNotReturn] public static void ThrowListEmptyException(string name) => throw new ArgumentException("The list is empty.", name);
45+
}
46+
47+
public static class Stack
48+
{
49+
public static class Enumerator
50+
{
51+
[DoesNotReturn] public static void ThrowStackModifiedException() => throw new InvalidOperationException("The stack was modified after the enumerator was created.");
52+
}
53+
54+
[DoesNotReturn] public static void ThrowStackTooBigException(string name) => throw new ArgumentException("The stack is too big for the destination array.", name);
55+
[DoesNotReturn] public static void ThrowStackEmptyException() => throw new InvalidOperationException("The stack is empty.");
56+
}
57+
58+
public static class Queue
59+
{
60+
public static class Enumerator
61+
{
62+
[DoesNotReturn] public static void ThrowQueueModifiedException() => throw new InvalidOperationException("The queue was modified after the enumerator was created.");
63+
}
64+
65+
[DoesNotReturn] public static void ThrowQueueTooBigException(string name) => throw new ArgumentException("The queue is too big for the destination array.", name);
66+
}
67+
68+
public static class List
69+
{
70+
public static class Enumerator
71+
{
72+
[DoesNotReturn] public static void ThrowListModifiedException() => throw new InvalidOperationException("The list was modified after the enumerator was created.");
73+
}
74+
75+
[DoesNotReturn] public static void ThrowValueIncorrectTypeException(string name) => throw new ArgumentException("The value's type is different from the list's element type.", name);
76+
[DoesNotReturn] public static void ThrowIndexOutOfBoundsException(string name) => throw new ArgumentException("The index is greater or equal to the list's element count.", name);
77+
[DoesNotReturn] public static void ThrowListTooBigException(string name) => throw new ArgumentException("The list is too big for the destination array.", name);
78+
}
79+
80+
public static class EqualityComparer
81+
{
82+
[DoesNotReturn] public static void ThrowInvalidTypeException(string name) => throw new ArgumentException("The parameter is of a type that cannot be cast to the compared type.", name);
2983
}
3084
}

Source/Mosa.TinyCoreLib/Internal/Impl.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,22 @@ public static class Object
8282
[MethodImpl(MethodImplOptions.InternalCall)]
8383
public static extern Type MemberwiseClone(object obj);
8484
}
85+
86+
public static class Queue
87+
{
88+
public const int InitialArraySize = 16;
89+
public const double NextCapacityMultiplySize = 1.1;
90+
}
91+
92+
public static class List
93+
{
94+
public const int InitialArraySize = 16;
95+
public const double NextCapacityMultiplySize = 1.1;
96+
public const double CapacityTrimThreshold = 0.9;
97+
}
98+
99+
public static class Stack
100+
{
101+
public const int InitialArraySize = 16;
102+
}
85103
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics.CodeAnalysis;
4+
5+
namespace Internal;
6+
7+
public class SimpleEqualityComparer<T> : EqualityComparer<T>
8+
{
9+
public override bool Equals(T? x, T? y)
10+
{
11+
if (x is null || y is null)
12+
return x is null && y is null;
13+
14+
if (x is IEquatable<T> xEq && y is IEquatable<T> yEq)
15+
return xEq.Equals(yEq);
16+
17+
return x.Equals(y);
18+
}
19+
20+
public override int GetHashCode([DisallowNull] T obj) => obj.GetHashCode();
21+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics.CodeAnalysis;
4+
5+
namespace Internal;
6+
7+
public class SpecificEqualityComparer<T>(Func<T, T, bool> equals, Func<T, int>? getHashCode) : EqualityComparer<T>
8+
{
9+
public override bool Equals(T? x, T? y) => equals(x, y);
10+
11+
public override int GetHashCode([DisallowNull] T obj) => getHashCode is null ? throw new NotSupportedException() : getHashCode(obj);
12+
}

Source/Mosa.TinyCoreLib/System.Collections.Generic/ByteEqualityComparer.cs

Lines changed: 0 additions & 26 deletions
This file was deleted.

Source/Mosa.TinyCoreLib/System.Collections.Generic/EnumEqualityComparer.cs

Lines changed: 0 additions & 31 deletions
This file was deleted.

Source/Mosa.TinyCoreLib/System.Collections.Generic/EqualityComparer.cs

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,13 @@ namespace System.Collections.Generic;
44

55
public abstract class EqualityComparer<T> : IEqualityComparer<T>, IEqualityComparer
66
{
7-
public static EqualityComparer<T> Default
8-
{
9-
get
10-
{
11-
throw null;
12-
}
13-
}
7+
public static EqualityComparer<T> Default { get; } = new Internal.SimpleEqualityComparer<T>();
148

159
public static EqualityComparer<T> Create(Func<T?, T?, bool> equals, Func<T, int>? getHashCode = null)
1610
{
17-
throw null;
11+
ArgumentNullException.ThrowIfNull(equals);
12+
13+
return new Internal.SpecificEqualityComparer<T>(equals, getHashCode);
1814
}
1915

2016
public abstract bool Equals(T? x, T? y);
@@ -23,11 +19,31 @@ public static EqualityComparer<T> Create(Func<T?, T?, bool> equals, Func<T, int>
2319

2420
bool IEqualityComparer.Equals(object? x, object? y)
2521
{
26-
throw null;
22+
if (x is null || y is null)
23+
return false;
24+
25+
if (x is T a)
26+
{
27+
if (y is T b)
28+
return a.Equals(b);
29+
30+
Internal.Exceptions.EqualityComparer.ThrowInvalidTypeException(nameof(y));
31+
return false;
32+
}
33+
34+
Internal.Exceptions.EqualityComparer.ThrowInvalidTypeException(nameof(x));
35+
return false;
2736
}
2837

2938
int IEqualityComparer.GetHashCode(object obj)
3039
{
31-
throw null;
40+
// Implementation detail: Even if "obj" is a value type, we accept null and just return 0.
41+
// This is different from the documentation which tells us to throw an exception if "obj"
42+
// is a reference type and "obj" is null.
43+
if (obj is null) return 0;
44+
if (obj is T value) return GetHashCode(value);
45+
46+
Internal.Exceptions.EqualityComparer.ThrowInvalidTypeException(nameof(obj));
47+
return 0;
3248
}
3349
}

Source/Mosa.TinyCoreLib/System.Collections.Generic/GenericComparer.cs

Lines changed: 0 additions & 21 deletions
This file was deleted.

Source/Mosa.TinyCoreLib/System.Collections.Generic/GenericEqualityComparer.cs

Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
 (0)