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);
}
}