Inheritance: IDuplicable, ISerializable
        internal static bool NormalizeSubstringRange(ConversionStorage<int>/*!*/ fixnumCast, Range/*!*/ range, int length, out int begin, out int count) {
            begin = Protocols.CastToFixnum(fixnumCast, range.Begin);
            int end = Protocols.CastToFixnum(fixnumCast, range.End);

            begin = IListOps.NormalizeIndex(length, begin);
            if (begin < 0 || begin > length) {
                count = 0;
                return false;
            }

            end = IListOps.NormalizeIndex(length, end); 

            count = range.ExcludeEnd ? end - begin : end - begin + 1;
            return true;
        }
Exemple #2
0
        internal static bool NormalizeRange(ConversionStorage<int>/*!*/ fixnumCast, int listCount, Range/*!*/ range, out int begin, out int count) {
            begin = Protocols.CastToFixnum(fixnumCast, range.Begin);
            int end = Protocols.CastToFixnum(fixnumCast, range.End);

            begin = NormalizeIndex(listCount, begin);

            if (begin < 0 || begin > listCount) {
                count = 0;
                return false;
            }

            end = NormalizeIndex(listCount, end);

            count = range.ExcludeEnd ? end - begin : end - begin + 1;
            return true;
        }
Exemple #3
0
        internal static bool NormalizeRange(RubyContext/*!*/ context, int listCount, Range/*!*/ range, out int begin, out int count) {
            bool excludeEnd;
            int end;
            Protocols.ConvertToIntegerRange(context, range, out begin, out end, out excludeEnd);
            
            begin = NormalizeIndex(listCount, begin);

            if (begin < 0 || begin > listCount) {
                count = 0;
                return false;
            }

            end = NormalizeIndex(listCount, end);

            count = excludeEnd ? end - begin : end - begin + 1;
            return true;
        }
Exemple #4
0
        public static object Step(StepStorage/*!*/ storage, [NotNull]BlockParam/*!*/ block, Range/*!*/ self, [Optional]object step) {
            if (step == Missing.Value) {
                step = ClrInteger.One;
            }

            // We attempt to cast step to Fixnum here even though if we were iterating over Floats, for instance, we use step as is.
            // This prevents cases such as (1.0..2.0).step(0x800000000000000) {|x| x } from working but that is what MRI does.
            if (self.Begin is int && self.End is int) {
                // self.begin is Fixnum; directly call item = item + 1 instead of succ
                var site = storage.FixnumCastSite;
                int intStep = site.Target(site, step);
                return StepFixnum(block, self, (int)self.Begin, (int)self.End, intStep);
            } else if (self.Begin is MutableString) {
                // self.begin is String; use item.succ and item <=> self.end but make sure you check the length of the strings
                var site = storage.FixnumCastSite;
                int intStep = site.Target(site, step);
                return StepString(storage, block, self, (MutableString)self.Begin, (MutableString)self.End, intStep);
            } else if (storage.Context.IsInstanceOf(self.Begin, storage.Context.GetClass(typeof(Numeric)))) {
                // self.begin is Numeric; invoke item = item + 1 instead of succ and invoke < or <= for compare
                return StepNumeric(storage, block, self, self.Begin, self.End, step);
            } else {
	            // self.begin is not Numeric or String; just invoke item.succ and item <=> self.end
                var site = storage.FixnumCastSite;
                int intStep = site.Target(site, step);
                return StepObject(storage, block, self, self.Begin, self.End, intStep);
            }
        }
Exemple #5
0
 public static int GetHashCode(UnaryOpStorage/*!*/ hashStorage, Range/*!*/ self) {
     // MRI: Ruby treatment of hash return value is inconsistent. 
     // No conversions happen here (unlike e.g. Array.hash).
     var hashSite = hashStorage.GetCallSite("hash");
     return unchecked(
         Protocols.ToHashCode(hashSite.Target(hashSite, self.Begin)) ^
         Protocols.ToHashCode(hashSite.Target(hashSite, self.End)) ^ 
         (self.ExcludeEnd ? 179425693 : 1794210891)
     );
 }
Exemple #6
0
 public static object Each(EachStorage/*!*/ storage, [NotNull]BlockParam/*!*/ block, Range/*!*/ self) {
     if (self.Begin is int && self.End is int) {
         return StepFixnum(block, self, (int)self.Begin, (int)self.End, 1);
     } else if (self.Begin is MutableString) {
         return StepString(storage, block, self, (MutableString)self.Begin, (MutableString)self.End, 1);
     } else {
         return StepObject(storage, block, self, self.Begin, self.End, 1);
     }
 }
Exemple #7
0
        /// <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 object StepString(
            ConversionStorage<MutableString>/*!*/ stringCast, 
            BinaryOpStorage/*!*/ comparisonStorage,
            BinaryOpStorage/*!*/ lessThanStorage,
            BinaryOpStorage/*!*/ greaterThanStorage,
            UnaryOpStorage/*!*/ succStorage, 
            BlockParam block, Range/*!*/ self, MutableString begin, MutableString end, int step) {

            CheckStep(step);
            object result;
            MutableString item = begin;
            int comp;

            var succSite = succStorage.GetCallSite("succ");
            while ((comp = Protocols.Compare(comparisonStorage, lessThanStorage, greaterThanStorage, item, end)) < 0) {
                if (block == null) {
                    throw RubyExceptions.NoBlockGiven();
                }

                if (block.Yield(item, out result)) {
                    return result;
                }

                for (int i = 0; i < step; i++) {
                    item = Protocols.CastToString(stringCast, succSite.Target(succSite, item));
                }

                if (item.Length > end.Length) {
                    return self;
                }
            }

            if (comp == 0 && !self.ExcludeEnd) {
                if (block == null) {
                    throw RubyExceptions.NoBlockGiven();
                } 
                
                if (block.Yield(item, out result)) {
                    return result;
                }
            }
            return self;
        }
Exemple #8
0
        /// <summary>
        /// Step through a Range of objects that are not Numeric or String.
        /// </summary>
        private static object StepObject(EachStorage /*!*/ storage, BlockParam /*!*/ block, Range /*!*/ self, object begin, object end, int step)
        {
            Assert.NotNull(storage, block, self);
            CheckStep(storage, step);
            CheckBegin(storage, self.Begin);

            object item = begin, result;
            int    comp;

            var succSite = storage.SuccSite;

            while ((comp = Protocols.Compare(storage, item, end)) < 0)
            {
                if (block.Yield(item, out result))
                {
                    return(result);
                }

                for (int i = 0; i < step; ++i)
                {
                    item = succSite.Target(succSite, item);
                }
            }

            if (comp == 0 && !self.ExcludeEnd)
            {
                if (block.Yield(item, out result))
                {
                    return(result);
                }
            }
            return(self);
        }
Exemple #9
0
 public static MutableString/*!*/ ToS(ConversionStorage<MutableString>/*!*/ tosConversion, Range/*!*/ self) {
     return self.ToMutableString(tosConversion);
 }
Exemple #10
0
 public static int GetHashCode(Range/*!*/ self) {
     int hash = RubyUtils.GetHashCode(self.Begin);
     hash ^= RubyUtils.GetHashCode(self.End);
     hash ^= RubyUtils.GetHashCode(self.ExcludeEnd);
     return hash;
 }
Exemple #11
0
        public static bool Eql(BinaryOpStorage /*!*/ equalsStorage, Range /*!*/ self, [NotNull] Range /*!*/ other)
        {
            if (self == other)
            {
                return(true);
            }

            var site = equalsStorage.GetCallSite("eql?");

            return(Protocols.IsTrue(site.Target(site, self.Begin, other.Begin)) &&
                   Protocols.IsTrue(site.Target(site, self.End, other.End)) &&
                   self.ExcludeEnd == other.ExcludeEnd);
        }
Exemple #12
0
 public static Enumerator /*!*/ GetEachEnumerator(EachStorage /*!*/ storage, Range /*!*/ self)
 {
     return(new Enumerator((_, block) => Each(storage, block, self)));
 }
Exemple #13
0
 public static MutableString /*!*/ ToS(ConversionStorage <MutableString> /*!*/ tosConversion, Range /*!*/ self)
 {
     return(self.ToMutableString(tosConversion));
 }
Exemple #14
0
 public static bool Equals(Range /*!*/ self, object other)
 {
     return(false);
 }
Exemple #15
0
 public static MutableString /*!*/ Inspect(RubyContext /*!*/ context, Range /*!*/ self)
 {
     return(self.Inspect(context));
 }
Exemple #16
0
 public static bool ExcludeEnd([NotNull] Range /*!*/ self)
 {
     return(self.ExcludeEnd);
 }
Exemple #17
0
 public static object End([NotNull] Range /*!*/ self)
 {
     return(self.End);
 }
Exemple #18
0
        /// <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 object StepString(EachStorage/*!*/ storage, BlockParam/*!*/ block, Range/*!*/ self, MutableString begin, MutableString end, int step) {
            Assert.NotNull(storage, block, self);
            CheckStep(step);
            object result;
            MutableString item = begin;
            int comp;

            var succSite = storage.SuccSite;
            while ((comp = Protocols.Compare(storage, item, end)) < 0) {
                if (block.Yield(item.Clone(), out result)) {
                    return result;
                }

                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) {
                    return self;
                }
            }

            if (comp == 0 && !self.ExcludeEnd) {
                if (block.Yield(item.Clone(), out result)) {
                    return result;
                }
            }
            return self;
        }
Exemple #19
0
        public static object Each(EachStorage /*!*/ storage, [NotNull] BlockParam /*!*/ block, Range /*!*/ self)
        {
            Assert.NotNull(block);
            CheckBegin(storage, self.Begin);

            var each = EachInRange(storage, self, 1);

            foreach (var item in each)
            {
                object result;
                if (block.Yield(item, out result))
                {
                    return(result);
                }
            }

            return(self);
        }
Exemple #20
0
        /// <summary>
        /// Step through a Range of objects that are not Numeric or String.
        /// </summary>
        private static object StepObject(EachStorage/*!*/ storage, BlockParam/*!*/ block, Range/*!*/ self, object begin, object end, int step) {
            Assert.NotNull(storage, block, self);
            CheckStep(storage, step);
            CheckBegin(storage, self.Begin);

            object item = begin, result;
            int comp;

            var succSite = storage.SuccSite;
            while ((comp = Protocols.Compare(storage, item, end)) < 0) {
                if (block.Yield(item, out result)) {
                    return result;
                }

                for (int i = 0; i < step; ++i) {
                    item = succSite.Target(succSite, item);
                }
            }

            if (comp == 0 && !self.ExcludeEnd) {
                if (block.Yield(item, out result)) {
                    return result;
                }
            }
            return self;
        }
Exemple #21
0
 public static Enumerator /*!*/ GetStepEnumerator(EachStorage /*!*/ storage, Range /*!*/ self, [Optional] object step)
 {
     return(new Enumerator((_, block) => Step(storage, block, self, step)));
 }
Exemple #22
0
 public static bool Equals(BinaryOpStorage/*!*/ equals, Range/*!*/ self, [NotNull]Range/*!*/ other) {
     if (self == other) {
         return true;
     }
     return Protocols.IsEqual(equals, self.Begin, other.Begin)
         && Protocols.IsEqual(equals, self.End, other.End)
         && self.ExcludeEnd == other.ExcludeEnd;
 }
Exemple #23
0
        public static object Step(EachStorage /*!*/ storage, [NotNull] BlockParam /*!*/ block, Range /*!*/ self, [Optional] object step)
        {
            if (step == Missing.Value)
            {
                step = ClrInteger.One;
            }

            Assert.NotNull(block);

            var each = EachInRange(storage, self, step);

            foreach (var item in each)
            {
                object result;
                if (block.Yield(item, out result))
                {
                    return(result);
                }
            }

            return(self);
        }
Exemple #24
0
        public static object Step(
            ConversionStorage<MutableString>/*!*/ stringCast, 
            ConversionStorage<int>/*!*/ fixnumCast, 
            RespondToStorage/*!*/ respondToStorage,
            BinaryOpStorage/*!*/ comparisonStorage,
            BinaryOpStorage/*!*/ lessThanStorage,
            BinaryOpStorage/*!*/ lessThanEqualsStorage,
            BinaryOpStorage/*!*/ greaterThanStorage,
            BinaryOpStorage/*!*/ equalsStorage,
            BinaryOpStorage/*!*/ addStorage,
            UnaryOpStorage/*!*/ succStorage,
            BlockParam block, Range/*!*/ self, [Optional]object step) {

            if (step == Missing.Value) {
                step = ClrInteger.One;
            }

            // We attempt to cast step to Fixnum here even though if we were iterating over Floats, for instance, we use step as is.
            // This prevents cases such as (1.0..2.0).step(0x800000000000000) {|x| x } from working but that is what MRI does.
            if (self.Begin is int && self.End is int) {
                // self.begin is Fixnum; directly call item = item + 1 instead of succ
                int intStep = Protocols.CastToFixnum(fixnumCast, step);
                return StepFixnum(block, self, (int)self.Begin, (int)self.End, intStep);
            } else if (self.Begin is MutableString ) {
                // self.begin is String; use item.succ and item <=> self.end but make sure you check the length of the strings
                int intStep = Protocols.CastToFixnum(fixnumCast, step);
                return StepString(stringCast, comparisonStorage, lessThanStorage, greaterThanStorage, succStorage, 
                    block, self, (MutableString)self.Begin, (MutableString)self.End, intStep
                );
            } else if (succStorage.Context.IsInstanceOf(self.Begin, succStorage.Context.GetClass(typeof(Numeric)))) {
                // self.begin is Numeric; invoke item = item + 1 instead of succ and invoke < or <= for compare
                return StepNumeric(lessThanStorage, lessThanEqualsStorage, equalsStorage, addStorage,  
                    block, self, self.Begin, self.End, step
                );
            } else {
                // self.begin is not Numeric or String; just invoke item.succ and item <=> self.end
                CheckBegin(respondToStorage, self.Begin);
                int intStep = Protocols.CastToFixnum(fixnumCast, step);
                return StepObject(comparisonStorage, lessThanStorage, greaterThanStorage, equalsStorage, succStorage, 
                    block, self, self.Begin, self.End, intStep
                );
            }
        }
Exemple #25
0
        /// <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());
            }
        }
Exemple #26
0
        /// <summary>
        /// Step through a Range of objects that are not Numeric or String.
        /// </summary>
        private static object StepObject(
            BinaryOpStorage/*!*/ comparisonStorage,
            BinaryOpStorage/*!*/ lessThanStorage,
            BinaryOpStorage/*!*/ greaterThanStorage,
            BinaryOpStorage/*!*/ equalsStorage,
            UnaryOpStorage/*!*/ succStorage,
            BlockParam block, Range/*!*/ self, object begin, object end, int step) {

            CheckStep(lessThanStorage.GetCallSite("<"), equalsStorage.GetCallSite("=="), step);

            object item = begin, result;
            int comp;

            var succSite = succStorage.GetCallSite("succ");
            while ((comp = Protocols.Compare(comparisonStorage, lessThanStorage, greaterThanStorage, item, end)) < 0) {
                if (block == null) {
                    throw RubyExceptions.NoBlockGiven();
                }

                if (block.Yield(item, out result)) {
                    return result;
                }

                for (int i = 0; i < step; ++i) {
                    item = succSite.Target(succSite, item);
                }
            }

            if (comp == 0 && !self.ExcludeEnd) {
                if (block == null) {
                    throw RubyExceptions.NoBlockGiven();
                }

                if (block.Yield(item, out result)) {
                    return result;
                }
            }
            return self;
        }
Exemple #27
0
        /// <summary>
        /// Step through a Range of Numerics.
        /// </summary>
        private static IEnumerable <object> EachStepNumeric(EachStorage /*!*/ storage, Range /*!*/ self, object step)
        {
            Assert.NotNull(storage, self);
            CheckStep(storage, step);

            object item = self.Begin;
            object end  = self.End;

            int comp;

            while ((comp = Protocols.Compare(storage, item, end)) < 0)
            {
                yield return(item);

                var add = storage.AddSite;
                item = add.Target(add, item, step);
            }

            if (comp == 0 && !self.ExcludeEnd)
            {
                yield return(item);
            }
        }
Exemple #28
0
 protected Range(Range/*!*/ range)
 {
     _begin = range._begin;
     _end = range._end;
     _excludeEnd = range._excludeEnd;
 }
Exemple #29
0
        /// <summary>
        /// Step through a Range of objects that are not Numeric or String.
        /// </summary>
        private static IEnumerable <object> EachStepObject(EachStorage /*!*/ storage, Range /*!*/ self, int step)
        {
            Assert.NotNull(storage, self);
            CheckStep(storage, step);

            int    comp;
            object begin = self.Begin;

            CheckBegin(storage, begin);

            object end      = self.End;
            object item     = begin;
            var    succSite = storage.SuccSite;

            while ((comp = Protocols.Compare(storage, item, end)) < 0)
            {
                yield return(item);

                for (int i = 0; i < step; ++i)
                {
                    item = succSite.Target(succSite, item);
                }
            }

            if (comp == 0 && !self.ExcludeEnd)
            {
                yield return(item);
            }
        }
Exemple #30
0
 public static Enumerator/*!*/ GetEachEnumerator(EachStorage/*!*/ storage, Range/*!*/ self) {
     return new Enumerator((_, block) => Each(storage, block, self));
 }
Exemple #31
0
 public static bool Cover(ComparisonStorage /*!*/ comparisonStorage, [NotNull] Range /*!*/ self, object value)
 {
     return(CaseEquals(comparisonStorage, self, value));
 }
Exemple #32
0
 public static Enumerator/*!*/ GetStepEnumerator(StepStorage/*!*/ storage, Range/*!*/ self, [Optional]object step) {
     return new Enumerator((_, block) => Step(storage, block, self, step));
 }
Exemple #33
0
        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));
        }
Exemple #34
0
        /// <summary>
        /// Step through a Range of Fixnums.
        /// </summary>
        /// <remarks>
        /// This method is optimized for direct integer operations using &lt; and + directly.
        /// It is not used if either begin or end are outside Fixnum bounds.
        /// </remarks>
        private static object StepFixnum(BlockParam/*!*/ block, Range/*!*/ self, int begin, int end, int step) {
            Assert.NotNull(block, self);
            CheckStep(step);

            object result;
            int item = begin;
            while (item < end) {
                if (block.Yield(item, out result)) {
                    return result;
                }
                item += step;
            }

            if (item == end && !self.ExcludeEnd) {
                if (block.Yield(item, out result)) {
                    return result;
                }
            }
            return self;
        }
Exemple #35
0
        public static object GetMinimumBy(EachStorage /*!*/ comparisonStorage, BlockParam /*!*/ block, Range /*!*/ self)
        {
            if (IsBeginGreatherThanEnd(comparisonStorage, self))
            {
                return(null);
            }

            var each = EachInRange(comparisonStorage, self, 1);

            return(each.Aggregate((x, y) => {
                object blockResult;
                if (block.Yield(y, x, out blockResult))
                {
                    return blockResult;
                }

                int r = Protocols.ConvertCompareResult(comparisonStorage, blockResult);

                return r < 0 ? y : x;
            }));
        }
Exemple #36
0
        /// <summary>
        /// Step through a Range of Numerics.
        /// </summary>
        private static object StepNumeric(StepStorage/*!*/ storage, BlockParam/*!*/ block, Range/*!*/ self, object begin, object end, object step) {
            Assert.NotNull(storage, block, self);
            CheckStep(storage, step);

            object item = begin;
            object result;

            var site = self.ExcludeEnd ? storage.LessThanSite : storage.LessThanEqualsSite;
            while (RubyOps.IsTrue(site.Target(site, item, end))) {
                if (block.Yield(item, out result)) {
                    return result;
                }

                var add = storage.AddSite;
                item = add.Target(add, item, step);
            }

            return self;
        }
Exemple #37
0
 public static Range /*!*/ Reinitialize(BinaryOpStorage /*!*/ comparisonStorage,
                                        RubyContext /*!*/ context, Range /*!*/ self, object begin, object end, [Optional] bool excludeEnd)
 {
     self.Initialize(comparisonStorage, context, begin, end, excludeEnd);
     return(self);
 }
Exemple #38
0
 public static MutableString/*!*/ Inspect(RubyContext/*!*/ context, Range/*!*/ self) {
     return self.Inspect(context);
 }
Exemple #39
0
 public static object Begin([NotNull] Range /*!*/ self)
 {
     return(self.Begin);
 }
Exemple #40
0
 public static bool Equals(Range/*!*/ self, object other) {
     return false;
 }
Exemple #41
0
        public static RubyArray GetGroup(ConversionStorage <int> /*!*/ fixnumCast, MatchData /*!*/ self, [NotNull] Range /*!*/ range)
        {
            int begin, count;

            if (!IListOps.NormalizeRange(fixnumCast, self.GroupCount, range, out begin, out count))
            {
                return(null);
            }
            return(GetGroup(self, begin, count));
        }
Exemple #42
0
        public static bool Eql(BinaryOpStorage/*!*/ equalsStorage, Range/*!*/ self, [NotNull]Range/*!*/ other) {

            if (self == other) {
                return true;
            }

            var site = equalsStorage.GetCallSite("eql?");
            return Protocols.IsTrue(site.Target(site, self.Begin, other.Begin))
                && Protocols.IsTrue(site.Target(site, self.End, other.End))
                && self.ExcludeEnd == other.ExcludeEnd;
        }
Exemple #43
0
 protected Range(Range /*!*/ range)
 {
     _begin      = range._begin;
     _end        = range._end;
     _excludeEnd = range._excludeEnd;
 }
Exemple #44
0
        public static object Each(
            ConversionStorage<MutableString>/*!*/ stringCast, 
            RespondToStorage/*!*/ respondToStorage,
            BinaryOpStorage/*!*/ comparisonStorage,
            BinaryOpStorage/*!*/ lessThanStorage,
            BinaryOpStorage/*!*/ greaterThanStorage,
            BinaryOpStorage/*!*/ equalsStorage,
            UnaryOpStorage/*!*/ succStorage,
            BlockParam block, Range/*!*/ self) {

            // We check that self.begin responds to "succ" even though some of the implementations don't use it.
            CheckBegin(respondToStorage, self.Begin);

            if (self.Begin is int && self.End is int) {
                return StepFixnum(block, self, (int)self.Begin, (int)self.End, 1);
            } else if (self.Begin is MutableString) {
                return StepString(stringCast, comparisonStorage, lessThanStorage, greaterThanStorage, succStorage,  
                    block, self, (MutableString)self.Begin, (MutableString)self.End, 1
                );
            } else {
                return StepObject(comparisonStorage, lessThanStorage, greaterThanStorage, equalsStorage, succStorage,  
                    block, self, self.Begin, self.End, 1
                );
            }
        }
Exemple #45
0
        public static Node/*!*/ ToYaml(UnaryOpStorage/*!*/ beginStorage, UnaryOpStorage/*!*/ endStorage, UnaryOpStorage/*!*/ exclStorage, 
            Range/*!*/ self, [NotNull]RubyRepresenter/*!*/ rep) {

            var begin = beginStorage.GetCallSite("begin");
            var end = endStorage.GetCallSite("end");

            var map = new Dictionary<MutableString, object>() {
                { MutableString.Create("begin"), begin.Target(begin, rep.Context, self) },
                { MutableString.Create("end"), end.Target(end, rep.Context, self) },
                { MutableString.Create("excl"), self.ExcludeEnd },
            };

            rep.AddYamlProperties(self, map);
            return rep.Map(self, map);
        }
Exemple #46
0
        /// <summary>
        /// Step through a Range of Fixnums.
        /// </summary>
        /// <remarks>
        /// This method is optimized for direct integer operations using &lt; and + directly.
        /// It is not used if either begin or end are outside Fixnum bounds.
        /// </remarks>
        private static object StepFixnum(BlockParam block, Range/*!*/ self, int begin, int end, int step) {
            CheckStep(step);

            // throw only if there is at least one item that will be enumerated:
            if (block == null && begin != end && !self.ExcludeEnd) {
                throw RubyExceptions.NoBlockGiven();
            }
            
            object result;
            int item = begin;
            while (item < end) {
                if (block.Yield(item, out result)) {
                    return result;
                }
                item += step;
            }

            if (item == end && !self.ExcludeEnd) {
                if (block.Yield(item, out result)) {
                    return result;
                }
            }
            return self;
        }
Exemple #47
0
        /// <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 object StepString(EachStorage /*!*/ storage, BlockParam /*!*/ block, Range /*!*/ self, MutableString begin, MutableString end, int step)
        {
            Assert.NotNull(storage, block, self);
            CheckStep(step);
            object        result;
            MutableString item = begin;
            int           comp;

            while ((comp = Protocols.Compare(storage, item, end)) < 0)
            {
                if (block.Yield(item.Clone(), out result))
                {
                    return(result);
                }

                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)
                {
                    return(self);
                }
            }

            if (comp == 0 && !self.ExcludeEnd)
            {
                if (block.Yield(item.Clone(), out result))
                {
                    return(result);
                }
            }
            return(self);
        }
Exemple #48
0
        /// <summary>
        /// Step through a Range of Numerics.
        /// </summary>
        private static object StepNumeric(
            BinaryOpStorage/*!*/ lessThanStorage,
            BinaryOpStorage/*!*/ lessThanEqualsStorage,
            BinaryOpStorage/*!*/ equalsStorage,
            BinaryOpStorage/*!*/ addStorage,
            BlockParam block, Range/*!*/ self, object begin, object end, object step) {

            var lessThan = lessThanStorage.GetCallSite("<");
            var equals = equalsStorage.GetCallSite("==");
            CheckStep(lessThan, equals, step);

            object item = begin;
            object result;

            var site = self.ExcludeEnd ? lessThan : lessThanEqualsStorage.GetCallSite("<=");
            while (RubyOps.IsTrue(site.Target(site, item, end))) {
                if (block == null) {
                    throw RubyExceptions.NoBlockGiven();
                }

                if (block.Yield(item, out result)) {
                    return result;
                }

                var add = addStorage.GetCallSite("+");
                item = add.Target(add, item, step);
            }

            return self;
        }
Exemple #49
0
        public static object Step(StepStorage /*!*/ storage, [NotNull] BlockParam /*!*/ block, Range /*!*/ self, [Optional] object step)
        {
            if (step == Missing.Value)
            {
                step = ClrInteger.One;
            }

            // We attempt to cast step to Fixnum here even though if we were iterating over Floats, for instance, we use step as is.
            // This prevents cases such as (1.0..2.0).step(0x800000000000000) {|x| x } from working but that is what MRI does.
            if (self.Begin is int && self.End is int)
            {
                // self.begin is Fixnum; directly call item = item + 1 instead of succ
                var site    = storage.FixnumCastSite;
                int intStep = site.Target(site, step);
                return(StepFixnum(block, self, (int)self.Begin, (int)self.End, intStep));
            }
            else if (self.Begin is MutableString)
            {
                // self.begin is String; use item.succ and item <=> self.end but make sure you check the length of the strings
                var site    = storage.FixnumCastSite;
                int intStep = site.Target(site, step);
                return(StepString(storage, block, self, (MutableString)self.Begin, (MutableString)self.End, intStep));
            }
            else if (storage.Context.IsInstanceOf(self.Begin, storage.Context.GetClass(typeof(Numeric))))
            {
                // self.begin is Numeric; invoke item = item + 1 instead of succ and invoke < or <= for compare
                return(StepNumeric(storage, block, self, self.Begin, self.End, step));
            }
            else
            {
                // self.begin is not Numeric or String; just invoke item.succ and item <=> self.end
                var site    = storage.FixnumCastSite;
                int intStep = site.Target(site, step);
                return(StepObject(storage, block, self, self.Begin, self.End, intStep));
            }
        }
Exemple #50
0
 public static Range/*!*/ Reinitialize(BinaryOpStorage/*!*/ comparisonStorage, 
     RubyContext/*!*/ context, Range/*!*/ self, object begin, object end, [Optional]bool excludeEnd) {
     self.Initialize(comparisonStorage, context, begin, end, excludeEnd);
     return self;
 }
Exemple #51
0
        /// <summary>
        /// Step through a Range of Numerics.
        /// </summary>
        private static object StepNumeric(StepStorage /*!*/ storage, BlockParam /*!*/ block, Range /*!*/ self, object begin, object end, object step)
        {
            Assert.NotNull(storage, block, self);
            CheckStep(storage, step);

            object item = begin;
            object result;

            var site = self.ExcludeEnd ? storage.LessThanSite : storage.LessThanEqualsSite;

            while (RubyOps.IsTrue(site.Target(site, item, end)))
            {
                if (block.Yield(item, out result))
                {
                    return(result);
                }

                var add = storage.AddSite;
                item = add.Target(add, item, step);
            }

            return(self);
        }
Exemple #52
0
 public static Range/*!*/ Reinitialize(RubyContext/*!*/ context, Range/*!*/ self, object begin, object end, [Optional]bool excludeEnd) {
     self.Initialize(context, begin, end, excludeEnd);
     return self;
 }
Exemple #53
0
        public static IList/*!*/ Fill(ConversionStorage<int>/*!*/ fixnumCast, IList/*!*/ self, object obj, Range/*!*/ range) {
            int begin = NormalizeIndex(self, Protocols.CastToFixnum(fixnumCast, range.Begin));
            int end = NormalizeIndex(self, Protocols.CastToFixnum(fixnumCast, range.End));
            int length = Math.Max(0, end - begin + (range.ExcludeEnd ? 0 : 1));

            return Fill(fixnumCast.Context, self, obj, begin, length);
        }
Exemple #54
0
        public static object Fill(ConversionStorage<int>/*!*/ fixnumCast, [NotNull]BlockParam/*!*/ block, IList/*!*/ self, Range/*!*/ range) {
            int begin = NormalizeIndex(self, Protocols.CastToFixnum(fixnumCast, range.Begin));
            int end = NormalizeIndex(self, Protocols.CastToFixnum(fixnumCast, range.End));
            int length = Math.Max(0, end - begin + (range.ExcludeEnd ? 0 : 1));

            return Fill(block, self, begin, length);
        }
Exemple #55
0
 public static object Each(EachStorage /*!*/ storage, [NotNull] BlockParam /*!*/ block, Range /*!*/ self)
 {
     if (self.Begin is int && self.End is int)
     {
         return(StepFixnum(block, self, (int)self.Begin, (int)self.End, 1));
     }
     else if (self.Begin is MutableString)
     {
         return(StepString(storage, block, self, (MutableString)self.Begin, (MutableString)self.End, 1));
     }
     else
     {
         return(StepObject(storage, block, self, self.Begin, self.End, 1));
     }
 }