예제 #1
0
        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);
        }
예제 #2
0
        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);
        }