diff options
author | mame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2019-04-03 08:11:41 +0000 |
---|---|---|
committer | mame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2019-04-03 08:11:41 +0000 |
commit | 95f7992b89efd35de6b28ac095c4d3477019c583 (patch) | |
tree | 5e38be092ece82da7a19a78af047598be1bf2079 /range.c | |
parent | dd2479bcea6cfbfb7656ef691ad5f9ff6ae543cd (diff) | |
download | bundler-95f7992b89efd35de6b28ac095c4d3477019c583.tar.gz |
Introduce beginless range [Feature#14799]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67422 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'range.c')
-rw-r--r-- | range.c | 49 |
1 files changed, 39 insertions, 10 deletions
@@ -35,7 +35,7 @@ static VALUE r_cover_p(VALUE, VALUE, VALUE, VALUE); static void range_init(VALUE range, VALUE beg, VALUE end, VALUE exclude_end) { - if ((!FIXNUM_P(beg) || !FIXNUM_P(end)) && !NIL_P(end)) { + if ((!FIXNUM_P(beg) || !FIXNUM_P(end)) && !NIL_P(beg) && !NIL_P(end)) { VALUE v; v = rb_funcall(beg, id_cmp, 1, end); @@ -704,8 +704,8 @@ range_bsearch(VALUE range) } #if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T) else if (RB_TYPE_P(beg, T_FLOAT) || RB_TYPE_P(end, T_FLOAT)) { - int64_t low = double_as_int64(RFLOAT_VALUE(rb_Float(beg))); - int64_t high = double_as_int64(NIL_P(end) ? HUGE_VAL : RFLOAT_VALUE(rb_Float(end))); + int64_t low = double_as_int64(NIL_P(beg) ? -HUGE_VAL : RFLOAT_VALUE(rb_Float(beg))); + int64_t high = double_as_int64(NIL_P(end) ? HUGE_VAL : RFLOAT_VALUE(rb_Float(end))); int64_t mid, org_high; BSEARCH(int64_as_double_to_num); } @@ -726,6 +726,18 @@ range_bsearch(VALUE range) diff = rb_funcall(diff, '*', 1, LONG2FIX(2)); } } + else if (NIL_P(beg) && is_integer_p(end)) { + VALUE diff = LONG2FIX(-1); + RETURN_ENUMERATOR(range, 0, 0); + while (1) { + VALUE mid = rb_funcall(end, '+', 1, diff); + BSEARCH_CHECK(mid); + if (!smaller) { + return bsearch_integer_range(mid, end, 0); + } + diff = rb_funcall(diff, '*', 1, LONG2FIX(2)); + } + } else { rb_raise(rb_eTypeError, "can't do binary search for %s", rb_obj_classname(beg)); } @@ -770,6 +782,9 @@ range_size(VALUE range) return DBL2NUM(HUGE_VAL); } } + else if (NIL_P(b)) { + return DBL2NUM(HUGE_VAL); + } return Qnil; } @@ -1230,7 +1245,7 @@ rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err) if (!rb_range_values(range, &b, &e, &excl)) return Qfalse; - beg = NUM2LONG(b); + beg = NIL_P(b) ? 0 : NUM2LONG(b); end = NIL_P(e) ? -1 : NUM2LONG(e); if (NIL_P(e)) excl = 0; origbeg = beg; @@ -1392,6 +1407,12 @@ range_include_internal(VALUE range, VALUE val) VALUE rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive); return rb_str_include_range_p(beg, end, val, RANGE_EXCL(range)); } + else if (NIL_P(beg)) { + VALUE r = rb_funcall(val, id_cmp, 1, end); + if (NIL_P(r)) return Qfalse; + if (rb_cmpint(r, val, end) <= 0) return Qtrue; + return Qfalse; + } else if (NIL_P(end)) { VALUE r = rb_funcall(beg, id_cmp, 1, val); if (NIL_P(r)) return Qfalse; @@ -1487,7 +1508,7 @@ r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val) static VALUE r_cover_p(VALUE range, VALUE beg, VALUE end, VALUE val) { - if (r_less(beg, val) <= 0) { + if (NIL_P(beg) || r_less(beg, val) <= 0) { int excl = EXCL(range); if (NIL_P(end) || r_less(val, end) <= -excl) return Qtrue; @@ -1550,9 +1571,15 @@ range_alloc(VALUE klass) * ('a'..'e').to_a #=> ["a", "b", "c", "d", "e"] * ('a'...'e').to_a #=> ["a", "b", "c", "d"] * - * == Endless Ranges + * == Beginless/Endless Ranges + * + * A "beginless range" and "endless range" represents a semi-infinite + * range. Literal notation for a beginless range is: + * + * (..1) + * # or + * (...1) * - * An "endless range" represents a semi-infinite range. * Literal notation for an endless range is: * * (1..) @@ -1564,14 +1591,16 @@ range_alloc(VALUE klass) * (1..nil) # or similarly (1...nil) * Range.new(1, nil) # or Range.new(1, nil, true) * - * Endless ranges are useful, for example, for idiomatic slicing of - * arrays: + * Beginless/endless ranges are useful, for example, for idiomatic + * slicing of arrays: * + * [1, 2, 3, 4, 5][...2] # => [1, 2] * [1, 2, 3, 4, 5][2...] # => [3, 4, 5] * * Some implementation details: * - * * +end+ of endless range is +nil+; + * * +begin+ of beginless range and +end+ of endless range are +nil+; + * * +each+ of beginless range raises an exception; * * +each+ of endless range enumerates infinite sequence (may be * useful in combination with Enumerable#take_while or similar * methods); |