private static object GetExtreme(CallSiteStorage <EachSite> /*!*/ each, ComparisonStorage /*!*/ comparisonStorage, BlockParam comparer, object self, int comparisonValue) { bool firstItem = true; object result = null; Each(each, self, Proc.Create(each.Context, delegate(BlockParam /*!*/ selfBlock, object _, object item) { if (firstItem) { result = item; firstItem = false; return(null); } object blockResult; int?compareResult = CompareItems(comparisonStorage, item, result, comparer, out blockResult); if (compareResult == null) { result = blockResult; return(selfBlock.PropagateFlow(comparer, blockResult)); } // Check if we have found the new minimum or maximum (+1 to select max, -1 to select min) if (compareResult == comparisonValue) { result = item; } return(null); })); return(result); }
public static object Sort(ComparisonStorage /*!*/ comparisonStorage, BlockParam block, RubyArray /*!*/ self) { RubyArray result = self.CreateInstance(); IListOps.Replace(result, self); return(SortInPlace(comparisonStorage, block, result)); }
public static RubyArray /*!*/ SortInPlace(ComparisonStorage /*!*/ comparisonStorage, RubyArray /*!*/ self) { StrongBox <object> breakResult; RubyArray result = SortInPlace(comparisonStorage, null, self, out breakResult); Debug.Assert(result != null && breakResult == null); return(result); }
private static bool IsBeginGreatherThanEnd(ComparisonStorage comparisonStorage, Range self) { var compare = comparisonStorage.CompareSite; object result = compare.Target(compare, self.Begin, self.End); return(result == null || Protocols.ConvertCompareResult(comparisonStorage, result) > (self.ExcludeEnd ? -1 : 0)); }
internal static RubyArray SortInPlace(ComparisonStorage /*!*/ comparisonStorage, BlockParam block, RubyArray /*!*/ self, out StrongBox <object> breakResult) { breakResult = null; var context = comparisonStorage.Context; // TODO: this does more comparisons (and in a different order) than // Ruby's sort. Also, control flow won't work because List<T>.Sort wraps // exceptions from the comparer & rethrows. We need to rewrite a version of quicksort // that behaves like Ruby's sort. if (block == null) { self.Sort((x, y) => Protocols.Compare(comparisonStorage, x, y)); } else { object nonRefBreakResult = null; try { self.Sort((x, y) => { object result = null; if (block.Yield(x, y, out result)) { nonRefBreakResult = result; throw new BreakException(); } if (result == null) { throw RubyExceptions.MakeComparisonError(context, x, y); } return(Protocols.ConvertCompareResult(comparisonStorage, result)); }); } catch (InvalidOperationException e) { if (e.InnerException == null) { throw; } if (e.InnerException is BreakException) { breakResult = new StrongBox <object>(nonRefBreakResult); return(null); } else { throw e.InnerException; } } } return(self); }
/// <summary> /// Try to compare the lhs and rhs. Throws and exception if comparison returns null. Returns null on failure, -1/0/+1 otherwise. /// </summary> private static int?Compare(ComparisonStorage /*!*/ comparisonStorage, object lhs, object rhs) { // calls method_missing, doesn't catch any exception: var compare = comparisonStorage.CompareSite; object compareResult = compare.Target(compare, lhs, rhs); if (compareResult != null) { return(Protocols.ConvertCompareResult(comparisonStorage, compareResult)); } throw RubyExceptions.MakeComparisonError(comparisonStorage.Context, lhs, rhs); }
public static object SortInPlace(ComparisonStorage /*!*/ comparisonStorage, BlockParam block, RubyArray /*!*/ self) { StrongBox <object> breakResult; RubyArray result = SortInPlace(comparisonStorage, block, self, out breakResult); if (breakResult != null) { return(breakResult.Value); } else { return(result); } }
public static object SortBy(CallSiteStorage <EachSite> /*!*/ each, ComparisonStorage /*!*/ comparisonStorage, BlockParam keySelector, object self) { // collect key, value pairs List <KeyValuePair <object, object> > keyValuePairs = new List <KeyValuePair <object, object> >(); object result = null; // Collect the key, value pairs Each(each, self, Proc.Create(each.Context, delegate(BlockParam /*!*/ selfBlock, object _, object item) { if (keySelector == null) { throw RubyExceptions.NoBlockGiven(); } object key; if (keySelector.Yield(item, out key)) { keyValuePairs = null; result = key; return(selfBlock.PropagateFlow(keySelector, key)); } keyValuePairs.Add(new KeyValuePair <object, object>(key, item)); return(null); })); if (keyValuePairs == null) { return(result); } // sort by keys keyValuePairs.Sort(delegate(KeyValuePair <object, object> x, KeyValuePair <object, object> y) { return(Protocols.Compare(comparisonStorage, x.Key, y.Key)); }); // return values RubyArray results = new RubyArray(keyValuePairs.Count); foreach (KeyValuePair <object, object> pair in keyValuePairs) { results.Add(pair.Value); } return(results); }
public static bool CaseEquals(ComparisonStorage /*!*/ comparisonStorage, [NotNull] Range /*!*/ self, object value) { var compare = comparisonStorage.CompareSite; object result = compare.Target(compare, self.Begin, value); if (result == null || Protocols.ConvertCompareResult(comparisonStorage, result) > 0) { return(false); } result = compare.Target(compare, value, self.End); if (result == null) { return(false); } int valueToEnd = Protocols.ConvertCompareResult(comparisonStorage, result); return(valueToEnd < 0 || (!self.ExcludeEnd && valueToEnd == 0)); }
private static int?CompareItems(ComparisonStorage /*!*/ comparisonStorage, object left, object right, BlockParam comparer, out object blockResult) { if (comparer != null) { if (comparer.Yield(left, right, out blockResult)) { return(null); } if (blockResult == null) { throw RubyExceptions.MakeComparisonError(comparisonStorage.Context, left, right); } return(Protocols.ConvertCompareResult(comparisonStorage, blockResult)); } else { blockResult = null; return(Protocols.Compare(comparisonStorage, left, right)); } }
/// <summary> /// Step through a Range of Strings. /// </summary> /// <remarks> /// This method requires step to be a Fixnum. /// It uses a hybrid string comparison to prevent infinite loops and calls String#succ to get each item in the range. /// </remarks> private static IEnumerable <MutableString> EachStepString(ComparisonStorage /*!*/ storage, Range /*!*/ self, int step) { Assert.NotNull(storage, self); CheckStep(step); var begin = (MutableString)self.Begin; var end = (MutableString)self.End; MutableString item = begin; int comp; while ((comp = Protocols.Compare(storage, item, end)) < 0) { yield return(item.Clone()); if (ReferenceEquals(item, begin)) { item = item.Clone(); } // TODO: this can be optimized for (int i = 0; i < step; i++) { MutableStringOps.SuccInPlace(item); } if (item.Length > end.Length) { yield break; } } if (comp == 0 && !self.ExcludeEnd) { yield return(item.Clone()); } }
public static object GetMinimum(CallSiteStorage <EachSite> /*!*/ each, ComparisonStorage /*!*/ comparisonStorage, BlockParam comparer, object self) { return(GetExtreme(each, comparisonStorage, comparer, self, -1)); }
private static bool IsBeginGreatherThanEnd(ComparisonStorage comparisonStorage, Range self) { var compare = comparisonStorage.CompareSite; object result = compare.Target(compare, self.Begin, self.End); return result == null || Protocols.ConvertCompareResult(comparisonStorage, result) > (self.ExcludeEnd ? -1 : 0); }
public static bool Between(ComparisonStorage/*!*/ comparisonStorage, object self, object min, object max) { return !Less(comparisonStorage, self, min) && !Greater(comparisonStorage, self, max); }
public static bool GreaterOrEqual(ComparisonStorage/*!*/ comparisonStorage, object self, object other) { return Compare(comparisonStorage, self, other).GetValueOrDefault(-1) >= 0; }
public static bool LessOrEqual(ComparisonStorage /*!*/ comparisonStorage, object self, object other) { return(Compare(comparisonStorage, self, other).GetValueOrDefault(1) <= 0); }
public static object Sort(CallSiteStorage<EachSite>/*!*/ each, ComparisonStorage/*!*/ comparisonStorage, BlockParam keySelector, object self) { return ArrayOps.SortInPlace(comparisonStorage, keySelector, ToArray(each, self)); }
public static object GetExtremes(CallSiteStorage<EachSite>/*!*/ each, ComparisonStorage/*!*/ comparisonStorage, BlockParam comparer, object self) { bool hasOddItem = false, hasMinMax = false, blockJumped = false; object oddItem = null; object blockResult = null; object min = null, max = null; Func<IronRuby.Runtime.BlockParam,object,object,object> blockProc = delegate(BlockParam/*!*/ selfBlock, object _, object item) { if (hasOddItem) { hasOddItem = false; int? compareResult = CompareItems(comparisonStorage, oddItem, item, comparer, out blockResult); if (compareResult == null) { goto BlockJumped; } if (compareResult > 0) { // oddItem > item object obj = item; item = oddItem; oddItem = obj; } // oddItem <= item if (hasMinMax) { compareResult = CompareItems(comparisonStorage, oddItem, min, comparer, out blockResult); if (compareResult == null) { goto BlockJumped; } if (compareResult < 0) { // oddItem < min min = oddItem; } compareResult = CompareItems(comparisonStorage, item, max, comparer, out blockResult); if (compareResult == null) { goto BlockJumped; } if (compareResult > 0) { // item > max max = item; } } else { min = oddItem; max = item; hasMinMax = true; } } else { hasOddItem = true; oddItem = item; } return null; BlockJumped: blockJumped = true; return selfBlock.PropagateFlow(comparer, blockResult); }; Each(each, self, Proc.Create(each.Context, blockProc)); if (blockJumped) { return blockResult; } if (!hasMinMax) { return hasOddItem ? new RubyArray(2) { oddItem, oddItem } : new RubyArray(2) { null, null }; } if (hasOddItem) { int? compareResult = CompareItems(comparisonStorage, oddItem, min, comparer, out blockResult); if (compareResult == null) { return blockResult; } if (compareResult < 0) { min = oddItem; } compareResult = CompareItems(comparisonStorage, oddItem, max, comparer, out blockResult); if (compareResult == null) { return blockResult; } if (compareResult > 0) { max = oddItem; } } return new RubyArray(2) { min, max }; }
public static object GetMinimum(CallSiteStorage<EachSite>/*!*/ each, ComparisonStorage/*!*/ comparisonStorage, BlockParam comparer, object self) { return GetExtreme(each, comparisonStorage, comparer, self, -1); }
public static object SortInPlace(ComparisonStorage/*!*/ comparisonStorage, BlockParam block, IList/*!*/ self) { // this should always call ArrayOps.SortInPlace instead Debug.Assert(!(self is RubyArray)); // TODO: this is not optimal because it makes an extra array copy // (only affects sorting of .NET types, do we need our own quicksort?) StrongBox<object> breakResult; RubyArray result = ArrayOps.SortInPlace(comparisonStorage, block, ToArray(self), out breakResult); if (breakResult == null) { Replace(self, result); return self; } else { return breakResult.Value; } }
public static bool LessOrEqual(ComparisonStorage/*!*/ comparisonStorage, object self, object other) { return Compare(comparisonStorage, self, other).GetValueOrDefault(1) <= 0; }
/// <summary> /// Try to compare the lhs and rhs. Throws and exception if comparison returns null. Returns null on failure, -1/0/+1 otherwise. /// </summary> private static int? Compare(ComparisonStorage/*!*/ comparisonStorage, object lhs, object rhs) { // calls method_missing, doesn't catch any exception: var compare = comparisonStorage.CompareSite; object compareResult = compare.Target(compare, lhs, rhs); if (compareResult != null) { return Protocols.ConvertCompareResult(comparisonStorage, compareResult); } throw RubyExceptions.MakeComparisonError(comparisonStorage.Context, lhs, rhs); }
public static bool Cover(ComparisonStorage /*!*/ comparisonStorage, [NotNull] Range /*!*/ self, object value) { return(CaseEquals(comparisonStorage, self, value)); }
public static object GetExtremes(CallSiteStorage <EachSite> /*!*/ each, ComparisonStorage /*!*/ comparisonStorage, BlockParam comparer, object self) { bool hasOddItem = false, hasMinMax = false, blockJumped = false; object oddItem = null; object blockResult = null; object min = null, max = null; Func <IronRuby.Runtime.BlockParam, object, object, object> blockProc = delegate(BlockParam /*!*/ selfBlock, object _, object item) { if (hasOddItem) { hasOddItem = false; int?compareResult = CompareItems(comparisonStorage, oddItem, item, comparer, out blockResult); if (compareResult == null) { goto BlockJumped; } if (compareResult > 0) { // oddItem > item object obj = item; item = oddItem; oddItem = obj; } // oddItem <= item if (hasMinMax) { compareResult = CompareItems(comparisonStorage, oddItem, min, comparer, out blockResult); if (compareResult == null) { goto BlockJumped; } if (compareResult < 0) { // oddItem < min min = oddItem; } compareResult = CompareItems(comparisonStorage, item, max, comparer, out blockResult); if (compareResult == null) { goto BlockJumped; } if (compareResult > 0) { // item > max max = item; } } else { min = oddItem; max = item; hasMinMax = true; } } else { hasOddItem = true; oddItem = item; } return(null); BlockJumped: blockJumped = true; return(selfBlock.PropagateFlow(comparer, blockResult)); }; Each(each, self, Proc.Create(each.Context, blockProc)); if (blockJumped) { return(blockResult); } if (!hasMinMax) { return(hasOddItem ? new RubyArray(2) { oddItem, oddItem } : new RubyArray(2) { null, null }); } if (hasOddItem) { int?compareResult = CompareItems(comparisonStorage, oddItem, min, comparer, out blockResult); if (compareResult == null) { return(blockResult); } if (compareResult < 0) { min = oddItem; } compareResult = CompareItems(comparisonStorage, oddItem, max, comparer, out blockResult); if (compareResult == null) { return(blockResult); } if (compareResult > 0) { max = oddItem; } } return(new RubyArray(2) { min, max }); }
/// <summary> /// Try to compare the lhs and rhs. Throws and exception if comparison returns null. Returns -1/0/+1 otherwise. /// </summary> public static int Compare(ComparisonStorage/*!*/ comparisonStorage, object lhs, object rhs) { var compare = comparisonStorage.CompareSite; var result = compare.Target(compare, lhs, rhs); if (result != null) { return Protocols.ConvertCompareResult(comparisonStorage, result); } else { throw RubyExceptions.MakeComparisonError(comparisonStorage.Context, lhs, rhs); } }
public static object Sort(CallSiteStorage <EachSite> /*!*/ each, ComparisonStorage /*!*/ comparisonStorage, BlockParam keySelector, object self) { return(ArrayOps.SortInPlace(comparisonStorage, keySelector, ToArray(each, self))); }
public static int ConvertCompareResult(ComparisonStorage/*!*/ comparisonStorage, object/*!*/ result) { Debug.Assert(result != null); var greaterThanSite = comparisonStorage.GreaterThanSite; if (RubyOps.IsTrue(greaterThanSite.Target(greaterThanSite, result, 0))) { return 1; } var lessThanSite = comparisonStorage.LessThanSite; if (RubyOps.IsTrue(lessThanSite.Target(lessThanSite, result, 0))) { return -1; } return 0; }
public static object Sort(UnaryOpStorage/*!*/ allocateStorage, ComparisonStorage/*!*/ comparisonStorage, BlockParam block, IList/*!*/ self) { // TODO: this is not optimal because it makes an extra array copy // (only affects sorting of .NET types, do we need our own quicksort?) IList resultList = CreateResultArray(allocateStorage, self); StrongBox<object> breakResult; RubyArray result = ArrayOps.SortInPlace(comparisonStorage, block, ToArray(self), out breakResult); if (breakResult == null) { Replace(resultList, result); return resultList; } else { return breakResult.Value; } }
public static object Sort(ComparisonStorage/*!*/ comparisonStorage, BlockParam block, RubyArray/*!*/ self) { RubyArray result = self.CreateInstance(); IListOps.Replace(result, self); return SortInPlace(comparisonStorage, block, result); }
public static bool CaseEquals(ComparisonStorage/*!*/ comparisonStorage, [NotNull]Range/*!*/ self, object value) { var compare = comparisonStorage.CompareSite; object result = compare.Target(compare, self.Begin, value); if (result == null || Protocols.ConvertCompareResult(comparisonStorage, result) > 0) { return false; } result = compare.Target(compare, value, self.End); if (result == null) { return false; } int valueToEnd = Protocols.ConvertCompareResult(comparisonStorage, result); return valueToEnd < 0 || (!self.ExcludeEnd && valueToEnd == 0); }
public static object SortInPlace(ComparisonStorage/*!*/ comparisonStorage, BlockParam block, RubyArray/*!*/ self) { StrongBox<object> breakResult; RubyArray result = SortInPlace(comparisonStorage, block, self, out breakResult); if (breakResult != null) { return breakResult.Value; } else { return result; } }
private static object GetExtreme(CallSiteStorage<EachSite>/*!*/ each, ComparisonStorage/*!*/ comparisonStorage, BlockParam comparer, object self, int comparisonValue) { bool firstItem = true; object result = null; Each(each, self, Proc.Create(each.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) { if (firstItem) { result = item; firstItem = false; return null; } object blockResult; int? compareResult = CompareItems(comparisonStorage, item, result, comparer, out blockResult); if (compareResult == null) { result = blockResult; return selfBlock.PropagateFlow(comparer, blockResult); } // Check if we have found the new minimum or maximum (+1 to select max, -1 to select min) if (compareResult == comparisonValue) { result = item; } return null; })); return result; }
public static RubyArray/*!*/ SortInPlace(ComparisonStorage/*!*/ comparisonStorage, RubyArray/*!*/ self) { StrongBox<object> breakResult; RubyArray result = SortInPlace(comparisonStorage, null, self, out breakResult); Debug.Assert(result != null && breakResult == null); return result; }
private static int? CompareItems(ComparisonStorage/*!*/ comparisonStorage, object left, object right, BlockParam comparer, out object blockResult) { if (comparer != null) { if (comparer.Yield(left, right, out blockResult)) { return null; } if (blockResult == null) { throw RubyExceptions.MakeComparisonError(comparisonStorage.Context, left, right); } return Protocols.ConvertCompareResult(comparisonStorage, blockResult); } else { blockResult = null; return Protocols.Compare(comparisonStorage, left, right); } }
internal static RubyArray SortInPlace(ComparisonStorage/*!*/ comparisonStorage, BlockParam block, RubyArray/*!*/ self, out StrongBox<object> breakResult) { breakResult = null; var context = comparisonStorage.Context; // TODO: this does more comparisons (and in a different order) than // Ruby's sort. Also, control flow won't work because List<T>.Sort wraps // exceptions from the comparer & rethrows. We need to rewrite a version of quicksort // that behaves like Ruby's sort. if (block == null) { self.Sort((x, y) => Protocols.Compare(comparisonStorage, x, y)); } else { object nonRefBreakResult = null; try { self.Sort((x, y) => { object result = null; if (block.Yield(x, y, out result)) { nonRefBreakResult = result; throw new BreakException(); } if (result == null) { throw RubyExceptions.MakeComparisonError(context, x, y); } return Protocols.ConvertCompareResult(comparisonStorage, result); }); } catch (InvalidOperationException e) { if (e.InnerException == null) { throw; } if (e.InnerException is BreakException) { breakResult = new StrongBox<object>(nonRefBreakResult); return null; } else { throw e.InnerException; } } } return self; }
public static object SortBy(CallSiteStorage<EachSite>/*!*/ each, ComparisonStorage/*!*/ comparisonStorage, BlockParam keySelector, object self) { // collect key, value pairs List<KeyValuePair<object, object>> keyValuePairs = new List<KeyValuePair<object, object>>(); object result = null; // Collect the key, value pairs Each(each, self, Proc.Create(each.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) { if (keySelector == null) { throw RubyExceptions.NoBlockGiven(); } object key; if (keySelector.Yield(item, out key)) { keyValuePairs = null; result = key; return selfBlock.PropagateFlow(keySelector, key); } keyValuePairs.Add(new KeyValuePair<object, object>(key, item)); return null; })); if (keyValuePairs == null) { return result; } // sort by keys keyValuePairs.Sort(delegate(KeyValuePair<object, object> x, KeyValuePair<object, object> y) { return Protocols.Compare(comparisonStorage, x.Key, y.Key); }); // return values RubyArray results = new RubyArray(keyValuePairs.Count); foreach (KeyValuePair<object, object> pair in keyValuePairs) { results.Add(pair.Value); } return results; }
/// <summary> /// Step through a Range of Strings. /// </summary> /// <remarks> /// This method requires step to be a Fixnum. /// It uses a hybrid string comparison to prevent infinite loops and calls String#succ to get each item in the range. /// </remarks> private static IEnumerable<MutableString> EachStepString(ComparisonStorage/*!*/ storage, Range/*!*/ self, int step) { Assert.NotNull(storage, self); CheckStep(step); var begin = (MutableString)self.Begin; var end = (MutableString)self.End; MutableString item = begin; int comp; while ((comp = Protocols.Compare(storage, item, end)) < 0) { yield return item.Clone(); if (ReferenceEquals(item, begin)) { item = item.Clone(); } // TODO: this can be optimized for (int i = 0; i < step; i++) { MutableStringOps.SuccInPlace(item); } if (item.Length > end.Length) { yield break; } } if (comp == 0 && !self.ExcludeEnd) { yield return item.Clone(); } }
public static bool Greater(ComparisonStorage /*!*/ comparisonStorage, object self, object other) { return(Compare(comparisonStorage, self, other).GetValueOrDefault(0) > 0); }
public static bool Cover(ComparisonStorage/*!*/ comparisonStorage, [NotNull]Range/*!*/ self, object value) { return CaseEquals(comparisonStorage, self, value); }
public static bool Between(ComparisonStorage /*!*/ comparisonStorage, object self, object min, object max) { return(!Less(comparisonStorage, self, min) && !Greater(comparisonStorage, self, max)); }
public static object Sort(ComparisonStorage /*!*/ comparisonStorage, BlockParam block, IDictionary <object, object> /*!*/ self) { return(ArrayOps.SortInPlace(comparisonStorage, block, ToArray(self))); }