diff --git a/src/Runtime/Collections/RuntimeEzrObjectDictionary.cs b/src/Runtime/Collections/RuntimeEzrObjectDictionary.cs index 64589a4..4a1c8bf 100644 --- a/src/Runtime/Collections/RuntimeEzrObjectDictionary.cs +++ b/src/Runtime/Collections/RuntimeEzrObjectDictionary.cs @@ -1,4 +1,6 @@ using EzrSquared.Runtime.Types; +using EzrSquared.Runtime.Types.Collections; +using EzrSquared.Runtime.Types.Core.Errors; using EzrSquared.Runtime.WrapperAttributes; using System.Collections.Generic; @@ -113,10 +115,47 @@ public bool RemoveHash(int key) /// Merges a to the current . /// /// The other to be merged. - public void Merge(RuntimeEzrObjectDictionary other) + /// The object for returning errors. + public void Merge(RuntimeEzrObjectDictionary other, RuntimeResult result) { foreach (KeyValuePair> pair in other._items) - _items[pair.Key] = pair.Value; + { + IEzrObject keyObject = pair.Value.Key; + if (keyObject is IEzrMutableObject mutableElement) + { + IEzrObject? keyCopy = (IEzrObject?)mutableElement.DeepCopy(result); + if (result.ShouldReturn) + return; + + keyObject = keyCopy!; + } + + _items[pair.Key] = new KeyValuePair(keyObject, pair.Value.Value); + } + } + + /// + /// Merges an to the current . + /// + /// The other to be merged. + /// The context under which this operation is being executed. + /// The object for returning errors. + public void Merge(IEzrDictionary other, Context executionContext, RuntimeResult result) + { + foreach (IEzrIndexedCollection pair in other) + { + if (pair.Count is > 2 or < 2) + { + result.Failure(new EzrUnexpectedTypeError($"Object of type \"{other.TypeName}\" is in an unexpected format and cannot be merged into this dictionary!", executionContext, other.StartPosition, other.EndPosition)); + return; + } + + (IEzrObject keyObject, IEzrObject valueObject) = (pair.At(0), pair.At(1)); + + Update(keyObject, valueObject, result); + if (result.ShouldReturn) + return; + } } /// @@ -172,6 +211,44 @@ public bool IsEqual(RuntimeEzrObjectDictionary other, RuntimeResult result) return true; } + /// + /// Checks if the current dictionary is equal to the given keyed collection. + /// + /// The other keyed collection. + /// The context under which this operation is being executed. + /// The object for returning errors. + /// The comparison result. + public bool IsEqual(IEzrDictionary other, Context executionContext, RuntimeResult result) + { + if (other.Count != _items.Count) + return false; + + foreach (IEzrIndexedCollection pair in other) + { + if (pair.Count is > 2 or < 2) + { + result.Failure(new EzrUnexpectedTypeError($"Object of type \"{other.TypeName}\" is in an unexpected format and cannot be compared with this dictionary!", executionContext, other.StartPosition, other.EndPosition)); + return false; + } + + (IEzrObject keyObject, IEzrObject valueObject) = (pair.At(0), pair.At(1)); + + int keyHashCode = keyObject.ComputeHashCode(result); + if (result.ShouldReturn || !_items.TryGetValue(keyHashCode, out KeyValuePair thisPair)) + return false; + + bool keyEquals = keyObject.StrictEquals(thisPair.Key, result); + if (result.ShouldReturn || !keyEquals) + return false; + + bool valueEquals = valueObject.StrictEquals(thisPair.Value.Object, result); + if (result.ShouldReturn || !valueEquals) + return false; + } + + return true; + } + /// /// Retrieves all keys from the . /// diff --git a/src/Runtime/Interpreter.cs b/src/Runtime/Interpreter.cs index 4a7ef2c..f3255fa 100644 --- a/src/Runtime/Interpreter.cs +++ b/src/Runtime/Interpreter.cs @@ -440,7 +440,7 @@ private void AssignValuesToVariables(VariableAssignmentNode node, Reference[] va switch (value) { - case IEzrIndexedCollection otherCollection when otherCollection.Length != variables.Length: + case IEzrIndexedCollection otherCollection when otherCollection.Count != variables.Length: RuntimeResult.Failure(new EzrIllegalOperationError("Mismatched number of variables and values in assignment!", executionContext, node.StartPosition, node.EndPosition)); return; @@ -1037,13 +1037,13 @@ private void VisitForEachNode(ForEachNode node, Context executionContext, Contex return; Reference iterableObjectReference = RuntimeResult.Reference; - if (iterableObjectReference.Object is not IEzrIndexedCollection iterableObject) + if (iterableObjectReference.Object is not IReadOnlyCollection iterableObject) { RuntimeResult.Failure(new EzrUnexpectedTypeError($"Expected an iterable object to iterate, but got object of type \"{iterableObjectReference.Object.TypeName}\"!", executionContext, node.Expression.Right.StartPosition, node.Expression.Right.EndPosition)); return; } - List returns = new(iterableObject.Length); + List returns = new(iterableObject.Count); foreach (IEzrObject ezrObject in iterableObject) { ezrObject.Update(executionContext, node.Expression.StartPosition, node.Expression.EndPosition); diff --git a/src/Runtime/Types/Collections/EzrArray.cs b/src/Runtime/Types/Collections/EzrArray.cs index 67b5983..35ce71d 100644 --- a/src/Runtime/Types/Collections/EzrArray.cs +++ b/src/Runtime/Types/Collections/EzrArray.cs @@ -26,7 +26,7 @@ public class EzrArray : EzrObject, IEzrIndexedCollection public readonly IEzrObject[] Value; /// - public int Length { get; } + public int Count { get; } /// /// Creates a new . @@ -38,9 +38,9 @@ public class EzrArray : EzrObject, IEzrIndexedCollection public EzrArray(IEzrObject[] elements, Context parentContext, Position startPosition, Position endPosition) : base(parentContext, startPosition, endPosition) { Value = elements; - Length = elements.Length; + Count = elements.Length; - Context.Set(null, "length", ReferencePool.Get(new EzrSharpCompatibilityProperty(GetMemberInfo(nameof(Length))!, this, Context, StartPosition, EndPosition), AccessMod.Constant)); + Context.Set(null, "length", ReferencePool.Get(new EzrSharpCompatibilityProperty(GetMemberInfo(nameof(Count))!, this, Context, StartPosition, EndPosition), AccessMod.Constant)); } /// @@ -51,7 +51,7 @@ public EzrArray(IEzrObject[] elements, Context parentContext, Position startPosi /// The result of the comparison. private bool Compare(IEzrIndexedCollection other, RuntimeResult result) { - if (Value.Length != other.Length) + if (Value.Length != other.Count) return false; for (int i = 0; i < Value.Length; i++) @@ -154,10 +154,10 @@ public override void ComparisonLessThan(IEzrObject other, RuntimeResult result) case EzrInteger: result.Failure(new EzrValueOutOfRangeError("The value is too large for this operation!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: < 2 }: + case IEzrIndexedCollection { Count: < 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: > 2 }: + case IEzrIndexedCollection { Count: > 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must only contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; case IEzrIndexedCollection otherCollection: @@ -231,10 +231,10 @@ public override void Addition(IEzrObject other, RuntimeResult result) switch (other) { case EzrArray otherArray: - newArray = new IEzrObject[Value.Length + otherArray.Length]; + newArray = new IEzrObject[Value.Length + otherArray.Count]; Array.Copy(Value, newArray, Value.Length); - Array.Copy(otherArray.Value, 0, newArray, Value.Length, otherArray.Length); + Array.Copy(otherArray.Value, 0, newArray, Value.Length, otherArray.Count); break; @@ -279,10 +279,10 @@ public override void Subtraction(IEzrObject other, RuntimeResult result) case EzrInteger: result.Failure(new EzrValueOutOfRangeError("The value is too large for this operation!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: < 2 }: + case IEzrIndexedCollection { Count: < 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: > 2 }: + case IEzrIndexedCollection { Count: > 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must only contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; case IEzrIndexedCollection otherCollection: diff --git a/src/Runtime/Types/Collections/EzrDictionary.cs b/src/Runtime/Types/Collections/EzrDictionary.cs index f9a1e0a..a107f7a 100644 --- a/src/Runtime/Types/Collections/EzrDictionary.cs +++ b/src/Runtime/Types/Collections/EzrDictionary.cs @@ -7,6 +7,7 @@ using EzrSquared.Runtime.Types.CSharpWrappers.SourceWrappers; using EzrSquared.Runtime.WrapperAttributes; using System; +using System.Collections; using System.Collections.Generic; using System.Reflection; @@ -15,7 +16,7 @@ namespace EzrSquared.Runtime.Types.Collections; /// /// The mutable dictionary type object. /// -public class EzrDictionary : EzrObject, IEzrMutableObject +public class EzrDictionary : EzrObject, IEzrMutableObject, IEzrDictionary { /// public override string TypeName { get; protected internal set; } = "dictionary"; @@ -28,6 +29,9 @@ public class EzrDictionary : EzrObject, IEzrMutableObject /// public readonly RuntimeEzrObjectDictionary Value; + /// + public int Count => Value.Length; + /// /// Creates a new . /// @@ -44,6 +48,36 @@ public EzrDictionary(RuntimeEzrObjectDictionary value, Context parentContext, Po Context.Set(null, "has_key", ReferencePool.Get(new EzrSharpSourceFunctionWrapper(DictionaryExists, Context, StartPosition, EndPosition), AccessMod.Constant)); } + /// + /// Thrown if the key could not be hashed or was not found. + public IEzrObject At(IEzrObject key, RuntimeResult result) + { + Reference value = Value.Get(key, result); + return !value.IsEmpty + ? value.Object + : throw new KeyNotFoundException("The key could not be hashed or was not found in the dictionary!"); + } + + /// + public IEzrObject? TryAt(IEzrObject key, RuntimeResult result) + { + Reference value = Value.Get(key, result); + return !value.IsEmpty ? value.Object : null; + } + + /// + public IEnumerator GetEnumerator() + { + EzrArray[] pairs = Array.ConvertAll(Value.GetPairs(), pair => new EzrArray([pair.Key, pair.Value], _executionContext, StartPosition, EndPosition)); + return ((IEnumerable)pairs).GetEnumerator(); + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + /// /// Basic key checking function. Implements . /// @@ -78,11 +112,18 @@ public override void ComparisonEqual(IEzrObject other, RuntimeResult result) switch (other) { case EzrDictionary otherDictionary: - bool equal = Value.IsEqual(otherDictionary.Value, result); + bool equalDictionaries = Value.IsEqual(otherDictionary.Value, result); if (result.ShouldReturn) return; - result.Success(NewBooleanConstant(equal)); break; + result.Success(NewBooleanConstant(equalDictionaries)); break; + + case IEzrDictionary otherIDictionary: + bool equalIDictionaries = Value.IsEqual(otherIDictionary, _executionContext, result); + if (result.ShouldReturn) + break; + + result.Success(NewBooleanConstant(equalIDictionaries)); break; default: result.Success(NewBooleanConstant(false)); break; @@ -95,11 +136,19 @@ public override void ComparisonNotEqual(IEzrObject other, RuntimeResult result) switch (other) { case EzrDictionary otherDictionary: - bool equal = Value.IsEqual(otherDictionary.Value, result); + bool equalDictionaries = Value.IsEqual(otherDictionary.Value, result); if (result.ShouldReturn) return; - result.Success(NewBooleanConstant(!equal)); break; + result.Success(NewBooleanConstant(!equalDictionaries)); break; + + + case IEzrDictionary otherIDictionary: + bool equalIDictionaries = Value.IsEqual(otherIDictionary, _executionContext, result); + if (result.ShouldReturn) + break; + + result.Success(NewBooleanConstant(!equalIDictionaries)); break; default: result.Success(NewBooleanConstant(true)); break; @@ -136,24 +185,32 @@ public override void Addition(IEzrObject other, RuntimeResult result) { switch (other) { - case IEzrIndexedCollection { Length: < 2 }: + case IEzrIndexedCollection { Count: < 2 }: result.Failure(new EzrIllegalOperationError($"The {other.TypeName} must contain two values, the key and value!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: > 2 }: + case IEzrIndexedCollection { Count: > 2 }: result.Failure(new EzrIllegalOperationError($"The {other.TypeName} must only contain two values, the key and value!", _executionContext, other.StartPosition, other.EndPosition)); break; case IEzrIndexedCollection otherCollection: Value.Update(otherCollection.At(0), otherCollection.At(1), result); if (result.ShouldReturn) - return; + break; result.Success(NewNothingConstant()); break; case EzrDictionary otherDictionary: - Value.Merge(otherDictionary.Value); - result.Success(NewNothingConstant()); + Value.Merge(otherDictionary.Value, result); + if (result.ShouldReturn) + break; - break; + result.Success(NewNothingConstant()); break; + + case IEzrDictionary otherIDictionary: + Value.Merge(otherIDictionary, _executionContext, result); + if (result.ShouldReturn) + break; + + result.Success(NewNothingConstant()); break; default: result.Failure(IllegalOperation(other)); break; diff --git a/src/Runtime/Types/Collections/EzrList.cs b/src/Runtime/Types/Collections/EzrList.cs index 2389e3e..7e0fa98 100644 --- a/src/Runtime/Types/Collections/EzrList.cs +++ b/src/Runtime/Types/Collections/EzrList.cs @@ -29,7 +29,7 @@ public class EzrList : EzrObject, IEzrMutableObject, IEzrIndexedCollection /// [SharpAutoWrapper(isReadOnly: true)] - public int Length => Value.Count; + public int Count => Value.Count; /// The base value. /// The parent context. @@ -39,7 +39,7 @@ public EzrList(RuntimeEzrObjectList elements, Context parentContext, Position st { Value = elements; - Context.Set(null, "length", ReferencePool.Get(new EzrSharpCompatibilityProperty(GetMemberInfo(nameof(Length))!, this, Context, StartPosition, EndPosition), AccessMod.Constant)); + Context.Set(null, "length", ReferencePool.Get(new EzrSharpCompatibilityProperty(GetMemberInfo(nameof(Count))!, this, Context, StartPosition, EndPosition), AccessMod.Constant)); } /// @@ -50,7 +50,7 @@ public EzrList(RuntimeEzrObjectList elements, Context parentContext, Position st /// The result of the comparison. private bool Compare(IEzrIndexedCollection other, RuntimeResult result) { - if (Value.Count != other.Length) + if (Value.Count != other.Count) return false; for (int i = 0; i < Value.Count; i++) @@ -153,10 +153,10 @@ public override void ComparisonLessThan(IEzrObject other, RuntimeResult result) case EzrInteger: result.Failure(new EzrValueOutOfRangeError("The value is too large for this operation!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: < 2 }: + case IEzrIndexedCollection { Count: < 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: > 2 }: + case IEzrIndexedCollection { Count: > 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must only contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; case IEzrIndexedCollection otherCollection: @@ -266,10 +266,10 @@ public override void Subtraction(IEzrObject other, RuntimeResult result) case EzrInteger: result.Failure(new EzrValueOutOfRangeError("The value is too large for this operation!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: < 2 }: + case IEzrIndexedCollection { Count: < 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: > 2 }: + case IEzrIndexedCollection { Count: > 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must only contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; case IEzrIndexedCollection otherCollection: diff --git a/src/Runtime/Types/Collections/IEzrDictionary.cs b/src/Runtime/Types/Collections/IEzrDictionary.cs new file mode 100644 index 0000000..c79a6f1 --- /dev/null +++ b/src/Runtime/Types/Collections/IEzrDictionary.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace EzrSquared.Runtime.Types.Collections; + +/// +/// Interface for a keyed collection of ezr² objects. +/// +public interface IEzrDictionary : IEzrObject, IReadOnlyCollection +{ + /// + /// Gets the object at the specified key. + /// + /// The key. + /// Runtime result for operations on the . + /// The object at the key. + public IEzrObject At(IEzrObject key, RuntimeResult result); + + /// + /// Tries to get the object at the specified key. + /// + /// The key. + /// Runtime result for operations on the . + /// The object at the key or if not found or something went wrong. + public IEzrObject? TryAt(IEzrObject key, RuntimeResult result); +} diff --git a/src/Runtime/Types/Collections/IEzrIndexedCollection.cs b/src/Runtime/Types/Collections/IEzrIndexedCollection.cs index 62e0a11..200619a 100644 --- a/src/Runtime/Types/Collections/IEzrIndexedCollection.cs +++ b/src/Runtime/Types/Collections/IEzrIndexedCollection.cs @@ -5,15 +5,10 @@ namespace EzrSquared.Runtime.Types.Collections; /// /// Interface for an indexed collection of ezr² objects. /// -public interface IEzrIndexedCollection : IEzrObject, IEnumerable +public interface IEzrIndexedCollection : IEzrObject, IReadOnlyCollection { /// - /// The length of the collection. - /// - public int Length { get; } - - /// - /// Gets the object at the specified index/ + /// Gets the object at the specified index. /// /// The index. /// The object at the index. diff --git a/src/Runtime/Types/Core/Text/EzrCharacterList.cs b/src/Runtime/Types/Core/Text/EzrCharacterList.cs index 15d1d38..fb00545 100644 --- a/src/Runtime/Types/Core/Text/EzrCharacterList.cs +++ b/src/Runtime/Types/Core/Text/EzrCharacterList.cs @@ -35,7 +35,7 @@ public class EzrCharacterList : EzrObject, IEzrMutableObject, IEzrString, IEzrIn /// [SharpAutoWrapper(isReadOnly: true)] - public int Length => Value.Length; + public int Count => Value.Length; /// /// Creates a new . @@ -48,7 +48,7 @@ public EzrCharacterList(string value, Context parentContext, Position startPosit { Value = new(value); - Context.Set(null, "length", ReferencePool.Get(new EzrSharpCompatibilityProperty(GetMemberInfo(nameof(Length))!, this, Context, StartPosition, EndPosition), AccessMod.Constant)); + Context.Set(null, "length", ReferencePool.Get(new EzrSharpCompatibilityProperty(GetMemberInfo(nameof(Count))!, this, Context, StartPosition, EndPosition), AccessMod.Constant)); } /// @@ -58,7 +58,7 @@ public EzrCharacterList(string value, Context parentContext, Position startPosit /// The result of the comparison. private bool Compare(IEzrIndexedCollection other) { - if (Value.Length != other.Length) + if (Value.Length != other.Count) return false; for (int i = 0; i < Value.Length; i++) @@ -140,10 +140,10 @@ public override void ComparisonLessThan(IEzrObject other, RuntimeResult result) case EzrInteger: result.Failure(new EzrValueOutOfRangeError("The value is too large for this operation!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: < 2 }: + case IEzrIndexedCollection { Count: < 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: > 2 }: + case IEzrIndexedCollection { Count: > 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must only contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; case IEzrIndexedCollection otherCollection: @@ -289,10 +289,10 @@ public override void Subtraction(IEzrObject other, RuntimeResult result) case EzrInteger: result.Failure(new EzrValueOutOfRangeError("The value is too large for this operation!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: < 2 }: + case IEzrIndexedCollection { Count: < 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: > 2 }: + case IEzrIndexedCollection { Count: > 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must only contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; case IEzrIndexedCollection otherCollection: diff --git a/src/Runtime/Types/Core/Text/EzrString.cs b/src/Runtime/Types/Core/Text/EzrString.cs index 62bee3e..ef0c7a5 100644 --- a/src/Runtime/Types/Core/Text/EzrString.cs +++ b/src/Runtime/Types/Core/Text/EzrString.cs @@ -31,7 +31,7 @@ public class EzrString : EzrObject, IEzrString, IEzrIndexedCollection public string StringValue => Value; /// - public int Length { get; } + public int Count { get; } /// /// Creates a new . @@ -43,9 +43,9 @@ public class EzrString : EzrObject, IEzrString, IEzrIndexedCollection public EzrString(string value, Context parentContext, Position startPosition, Position endPosition) : base(parentContext, startPosition, endPosition) { Value = value; - Length = value.Length; + Count = value.Length; - Context.Set(null, "length", ReferencePool.Get(new EzrSharpCompatibilityProperty(GetMemberInfo(nameof(Length))!, this, Context, StartPosition, EndPosition), AccessMod.Constant)); + Context.Set(null, "length", ReferencePool.Get(new EzrSharpCompatibilityProperty(GetMemberInfo(nameof(Count))!, this, Context, StartPosition, EndPosition), AccessMod.Constant)); } /// @@ -55,7 +55,7 @@ public EzrString(string value, Context parentContext, Position startPosition, Po /// The result of the comparison. private bool Compare(IEzrIndexedCollection other) { - if (Value.Length != other.Length) + if (Value.Length != other.Count) return false; for (int i = 0; i < Value.Length; i++) @@ -137,10 +137,10 @@ public override void ComparisonLessThan(IEzrObject other, RuntimeResult result) case EzrInteger: result.Failure(new EzrValueOutOfRangeError("The value is too large for this operation!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: < 2 }: + case IEzrIndexedCollection { Count: < 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: > 2 }: + case IEzrIndexedCollection { Count: > 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must only contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; case IEzrIndexedCollection otherCollection: @@ -284,10 +284,10 @@ public override void Subtraction(IEzrObject other, RuntimeResult result) case EzrInteger: result.Failure(new EzrValueOutOfRangeError("The value is too large for this operation!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: < 2 }: + case IEzrIndexedCollection { Count: < 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; - case IEzrIndexedCollection { Length: > 2 }: + case IEzrIndexedCollection { Count: > 2 }: result.Failure(new EzrIllegalOperationError($"The indices {other.TypeName} must only contain two values, the starting index and the ending index!", _executionContext, other.StartPosition, other.EndPosition)); break; case IEzrIndexedCollection otherCollection: