static VALUE range_each(VALUE range, SEL sel) { VALUE beg, end; RETURN_ENUMERATOR(range, 0, 0); beg = RANGE_BEG(range); end = RANGE_END(range); if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */ long lim = FIX2LONG(end); long i; if (!EXCL(range)) lim += 1; for (i = FIX2LONG(beg); i < lim; i++) { rb_yield(LONG2FIX(i)); RETURN_IF_BROKEN(); } } else if (SYMBOL_P(beg) && SYMBOL_P(end)) { /* symbols are special */ VALUE args[2]; args[0] = rb_sym_to_s(end); args[1] = EXCL(range) ? Qtrue : Qfalse; rb_objc_block_call(rb_sym_to_s(beg), selUpto, 2, args, sym_each_i, 0); } else { VALUE tmp = rb_check_string_type(beg); if (!NIL_P(tmp)) { VALUE args[2]; args[0] = end; args[1] = EXCL(range) ? Qtrue : Qfalse; rb_objc_block_call(beg, selUpto, 2, args, rb_yield, 0); } else { if (!discrete_object_p(beg)) { rb_raise(rb_eTypeError, "can't iterate from %s", rb_obj_classname(beg)); } range_each_func(range, each_i, NULL); } } return range; }
VALUE rb_block_call(VALUE obj, ID mid, int argc, VALUE *argv, VALUE (*bl_proc) (ANYARGS), VALUE data2) { SEL sel = rb_vm_id_to_sel(mid, argc); return rb_objc_block_call(obj, sel, argc, argv, bl_proc, data2); }
static VALUE range_first(VALUE range, SEL sel, int argc, VALUE *argv) { VALUE n, ary[2]; if (argc == 0) return RANGE_BEG(range); rb_scan_args(argc, argv, "1", &n); ary[0] = n; ary[1] = rb_ary_new2(NUM2LONG(n)); rb_objc_block_call(range, selEach, 0, 0, first_i, (VALUE)ary); return ary[1]; }
VALUE rb_block_call(VALUE obj, ID mid, int argc, VALUE *argv, VALUE (*bl_proc) (ANYARGS), VALUE data2) { SEL sel; if (argc == 0) { sel = sel_registerName(rb_id2name(mid)); } else { char buf[100]; snprintf(buf, sizeof buf, "%s:", rb_id2name(mid)); sel = sel_registerName(buf); } return rb_objc_block_call(obj, sel, NULL, argc, argv, bl_proc, data2); }
static VALUE enumerator_block_call(VALUE obj, VALUE (*func)(ANYARGS), VALUE arg) { struct enumerator *e; int argc = 0; const VALUE *argv = 0; e = enumerator_ptr(obj); if (e->args != 0) { argc = RARRAY_LEN(e->args); argv = RARRAY_PTR(e->args); } return rb_objc_block_call(e->obj, e->sel, argc, (VALUE *)argv, func, arg); }
static VALUE rb_set_initialize(VALUE set, SEL sel, int argc, VALUE *argv) { VALUE val; set = (VALUE)objc_msgSend((id)set, selInit); rb_scan_args(argc, argv, "01", &val); if (!NIL_P(val)) { rb_objc_block_call(val, selEach, cacheEach, 0, 0, initialize_i, (VALUE)set); } else if (rb_block_given_p()) { rb_warning("given block not used"); } return set; }
static VALUE range_step(VALUE range, SEL sel, int argc, VALUE *argv) { VALUE b, e, step, tmp; RETURN_ENUMERATOR(range, argc, argv); b = RANGE_BEG(range); e = RANGE_END(range); if (argc == 0) { step = INT2FIX(1); } else { rb_scan_args(argc, argv, "01", &step); if (!rb_obj_is_kind_of(step, rb_cNumeric)) { step = rb_to_int(step); } VALUE zero = INT2FIX(0); if (rb_vm_call(step, selLT, 1, &zero)) { rb_raise(rb_eArgError, "step can't be negative"); } else if (!rb_vm_call(step, selGT, 1, &zero)) { rb_raise(rb_eArgError, "step can't be 0"); } } if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */ long end = FIX2LONG(e); long i, unit = FIX2LONG(step); if (!EXCL(range)) end += 1; i = FIX2LONG(b); while (i < end) { rb_yield(LONG2NUM(i)); RETURN_IF_BROKEN(); if (i + unit < i) break; i += unit; } } else if (SYMBOL_P(b) && SYMBOL_P(e)) { /* symbols are special */ VALUE args[2]; VALUE iter[2]; args[0] = rb_sym_to_s(e); args[1] = EXCL(range) ? Qtrue : Qfalse; iter[0] = INT2FIX(1); iter[1] = step; rb_objc_block_call(rb_sym_to_s(b), selUpto, 2, args, sym_step_i, (VALUE)iter); } else if (ruby_float_step(b, e, step, EXCL(range))) { /* done */ } else if (rb_obj_is_kind_of(b, rb_cNumeric) || !NIL_P(rb_check_to_integer(b, "to_int")) || !NIL_P(rb_check_to_integer(e, "to_int"))) { SEL op = EXCL(range) ? selLT : selLE; VALUE v = b; int i = 0; while (RTEST(rb_vm_call(v, op, 1, &e))) { rb_yield(v); RETURN_IF_BROKEN(); i++; VALUE tmp = rb_vm_call(INT2NUM(i), selMULT, 1, &step); v = rb_vm_call(b, selPLUS, 1, &tmp); } } else { tmp = rb_check_string_type(b); if (!NIL_P(tmp)) { VALUE args[2], iter[2]; b = tmp; args[0] = e; args[1] = EXCL(range) ? Qtrue : Qfalse; iter[0] = INT2FIX(1); iter[1] = step; rb_objc_block_call(b, selUpto, 2, args, step_i, (VALUE)iter); } else { VALUE args[2]; if (!discrete_object_p(b)) { rb_raise(rb_eTypeError, "can't iterate from %s", rb_obj_classname(b)); } args[0] = INT2FIX(1); args[1] = step; return range_each_func(range, step_i, args); } } return range; }