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; }
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; }
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; }
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); } }
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) ); }
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); } }
/// <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; }
/// <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); }
public static MutableString/*!*/ ToS(ConversionStorage<MutableString>/*!*/ tosConversion, Range/*!*/ self) { return self.ToMutableString(tosConversion); }
public static int GetHashCode(Range/*!*/ self) { int hash = RubyUtils.GetHashCode(self.Begin); hash ^= RubyUtils.GetHashCode(self.End); hash ^= RubyUtils.GetHashCode(self.ExcludeEnd); return hash; }
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); }
public static Enumerator /*!*/ GetEachEnumerator(EachStorage /*!*/ storage, Range /*!*/ self) { return(new Enumerator((_, block) => Each(storage, block, self))); }
public static MutableString /*!*/ ToS(ConversionStorage <MutableString> /*!*/ tosConversion, Range /*!*/ self) { return(self.ToMutableString(tosConversion)); }
public static bool Equals(Range /*!*/ self, object other) { return(false); }
public static MutableString /*!*/ Inspect(RubyContext /*!*/ context, Range /*!*/ self) { return(self.Inspect(context)); }
public static bool ExcludeEnd([NotNull] Range /*!*/ self) { return(self.ExcludeEnd); }
public static object End([NotNull] Range /*!*/ self) { return(self.End); }
/// <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; }
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); }
/// <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; }
public static Enumerator /*!*/ GetStepEnumerator(EachStorage /*!*/ storage, Range /*!*/ self, [Optional] object step) { return(new Enumerator((_, block) => Step(storage, block, self, step))); }
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; }
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); }
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 ); } }
/// <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()); } }
/// <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; }
/// <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); } }
protected Range(Range/*!*/ range) { _begin = range._begin; _end = range._end; _excludeEnd = range._excludeEnd; }
/// <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); } }
public static Enumerator/*!*/ GetEachEnumerator(EachStorage/*!*/ storage, Range/*!*/ self) { return new Enumerator((_, block) => Each(storage, block, self)); }
public static bool Cover(ComparisonStorage /*!*/ comparisonStorage, [NotNull] Range /*!*/ self, object value) { return(CaseEquals(comparisonStorage, self, value)); }
public static Enumerator/*!*/ GetStepEnumerator(StepStorage/*!*/ storage, Range/*!*/ self, [Optional]object step) { return new Enumerator((_, block) => Step(storage, block, self, step)); }
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)); }
/// <summary> /// Step through a Range of Fixnums. /// </summary> /// <remarks> /// This method is optimized for direct integer operations using < 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; }
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; })); }
/// <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; }
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); }
public static MutableString/*!*/ Inspect(RubyContext/*!*/ context, Range/*!*/ self) { return self.Inspect(context); }
public static object Begin([NotNull] Range /*!*/ self) { return(self.Begin); }
public static bool Equals(Range/*!*/ self, object other) { return false; }
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)); }
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; }
protected Range(Range /*!*/ range) { _begin = range._begin; _end = range._end; _excludeEnd = range._excludeEnd; }
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 ); } }
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); }
/// <summary> /// Step through a Range of Fixnums. /// </summary> /// <remarks> /// This method is optimized for direct integer operations using < 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; }
/// <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); }
/// <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; }
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)); } }
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; }
/// <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); }
public static Range/*!*/ Reinitialize(RubyContext/*!*/ context, Range/*!*/ self, object begin, object end, [Optional]bool excludeEnd) { self.Initialize(context, begin, end, excludeEnd); return self; }
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); }
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); }
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)); } }