internal static RubyArray SortInPlace( BinaryOpStorage /*!*/ comparisonStorage, BinaryOpStorage /*!*/ lessThanStorage, BinaryOpStorage /*!*/ greaterThanStorage, 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, lessThanStorage, greaterThanStorage, 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(lessThanStorage, greaterThanStorage, 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 RubyArray /*!*/ SortInPlace(RubyContext /*!*/ context, BlockParam block, RubyArray /*!*/ self) { RubyUtils.RequiresNotFrozen(context, self); // 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(delegate(object x, object y) { return(Protocols.Compare(context, x, y)); }); } else { try { self.Sort(delegate(object x, object y) { object result; if (block.Yield(x, y, out result)) { // TODO: this doesn't work throw new BreakException(); } if (result == null) { throw RubyExceptions.MakeComparisonError(context, x, y); } return(Protocols.ConvertCompareResult(context, result)); }); } catch (BreakException) { } } return(self); }