Merge branch 'work_for_merge' of https://github.com/zubycz/mruby into zubycz-work_for_merge

parents c779413d bec4d053
......@@ -2190,10 +2190,18 @@ arg : lhs '=' arg_rhs
{
$$ = new_dot2(p, $1, $3);
}
| arg tDOT2
{
$$ = new_dot2(p, $1, new_nil(p));
}
| arg tDOT3 arg
{
$$ = new_dot3(p, $1, $3);
}
| arg tDOT3
{
$$ = new_dot3(p, $1, new_nil(p));
}
| arg '+' arg
{
$$ = call_bin_op(p, $1, "+", $3);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -27,10 +27,12 @@ class Range
end
def max(&block)
val = self.first
last = self.last
val = self.begin
last = self.end
return super if block
raise RangeError, "cannot get the maximum of endless range" if last.nil?
# fast path for numerics
if val.kind_of?(Numeric) && last.kind_of?(Numeric)
raise TypeError if exclude_end? && !last.kind_of?(Integer)
......@@ -47,9 +49,13 @@ class Range
end
def min(&block)
val = self.first
last = self.last
return super if block
val = self.begin
last = self.end
if block
raise RangeError, "cannot get the minimum of endless range with custom comparison method" if last.nil?
return super
end
return val if last.nil?
# fast path for numerics
if val.kind_of?(Numeric) && last.kind_of?(Numeric)
......
......@@ -42,6 +42,9 @@ range_cover(mrb_state *mrb, mrb_value range)
end = RANGE_END(r);
if (r_le(mrb, beg, val)) {
if (mrb_nil_p(end)) {
return mrb_true_value();
}
if (RANGE_EXCL(r)) {
if (r_lt(mrb, val, end))
return mrb_true_value();
......@@ -76,6 +79,11 @@ range_last(mrb_state *mrb, mrb_value range)
{
mrb_value num;
mrb_value array;
struct RRange *r = mrb_range_ptr(mrb, range);
if (mrb_nil_p(RANGE_END(r))) {
mrb_raise(mrb, E_RANGE_ERROR, "cannot get the last element of endless range");
}
if (mrb_get_args(mrb, "|o", &num) == 0) {
return mrb_range_end(mrb, range);
......@@ -108,6 +116,10 @@ range_size(mrb_state *mrb, mrb_value range)
beg = RANGE_BEG(r);
end = RANGE_END(r);
if ((mrb_fixnum_p(beg) || mrb_float_p(beg)) && mrb_nil_p(end)) {
return mrb_float_value(mrb, INFINITY);
}
excl = RANGE_EXCL(r);
if (mrb_integer_p(beg)) {
beg_f = (mrb_float)mrb_integer(beg);
......@@ -159,6 +171,10 @@ range_size(mrb_state *mrb, mrb_value range)
beg = RANGE_BEG(r);
end = RANGE_END(r);
if (mrb_fixnum_p(beg) && mrb_nil_p(end)) {
return mrb_nil_value();
}
excl = RANGE_EXCL(r) ? 0 : 1;
if (mrb_integer_p(beg) && mrb_integer_p(end)) {
......
......@@ -5,11 +5,16 @@ assert('Range#cover?') do
assert_true ("a".."z").cover?("c")
assert_true !("a".."z").cover?("5")
assert_true ("a".."z").cover?("cc")
assert_true ("a"..).cover?("c")
assert_false ("a"..).cover?("5")
assert_true ("a"..).cover?("cc")
end
assert('Range#first') do
assert_equal 10, (10..20).first
assert_equal [10, 11, 12], (10..20).first(3)
assert_equal 10, (10..).first
assert_equal [10, 11, 12], (10..).first(3)
skip unless Object.const_defined?(:Float)
assert_equal [0, 1, 2], (0..Float::INFINITY).first(3)
......@@ -18,6 +23,8 @@ end
assert('Range#last') do
assert_equal 20, (10..20).last
assert_equal 20, (10...20).last
assert_raise(RangeError) { (10..).last }
assert_raise(RangeError) { (10...).last }
assert_equal [18, 19, 20], (10..20).last(3)
assert_equal [17, 18, 19], (10...20).last(3)
end
......@@ -26,6 +33,9 @@ assert('Range#size') do
assert_equal 42, (1..42).size
assert_equal 41, (1...42).size
assert_nil ('a'..'z').size
assert_nil ('a'..).size
assert_nil (1..).size unless Object.const_defined?(:Float)
skip unless Object.const_defined?(:Float)
assert_equal 6, (1...6.3).size
......@@ -33,6 +43,10 @@ assert('Range#size') do
assert_equal 5, (1.1...6).size
assert_equal 15, (1.0..15.9).size
assert_equal Float::INFINITY, (0..Float::INFINITY).size
assert_equal Float::INFINITY, (1..).size
assert_equal Float::INFINITY, (1...).size
assert_equal Float::INFINITY, (1.0..).size
end
assert('Range#max') do
......@@ -50,6 +64,10 @@ assert('Range#max') do
# returns the endpoint when the endpoint equals the start point and the range is inclusive
assert_equal 5, (5..5).max
# raises RangeError when called on an endless range
assert_raise(RangeError) { (10..).max }
assert_raise(RangeError) { (10...).max }
skip unless Object.const_defined?(:Float)
# returns the maximum value in the Float range when called with no arguments
......@@ -94,6 +112,7 @@ assert('Range#min') do
# returns the minimum value in the range when called with no arguments
assert_equal 1, (1..10).min
assert_equal 1, (1...10).min
assert_equal 1, (1..).min
# returns nil when the start point is greater than the endpoint
assert_equal nil, (100..10).min
......@@ -108,12 +127,16 @@ assert('Range#min') do
# returns the minimum value in the Float range when called with no arguments
assert_equal 303.20, (303.20..908.1111).min
assert_equal 1, (1.0..).min
# returns nil when the start point is greater than the endpoint in a Float range
assert_equal nil, (3003.20..908.1111).min
end
assert('Range#min given a block') do
# raise when called with a block in endless range
assert_raise(RangeError) { (1..).min{} }
# passes each pair of values in the range to the block
acc = []
(1..10).min do |a, b|
......
......@@ -443,4 +443,27 @@ class String
end
self
end
def __upto_endless(&block)
return to_enum(:__upto_endless) unless block
len = self.length
# both edges are all digits
bi = self.to_i(10)
if bi > 0 or bi == "0"*len
while true
s = bi.to_s
s = s.rjust(len, "0") if s.length < len
yield s
bi += 1
end
return self
end
bs = self
while true
yield bs
bs = bs.succ
end
self
end
end
......@@ -12,8 +12,25 @@ class Range
def each(&block)
return to_enum :each unless block
val = self.first
last = self.last
val = self.begin
last = self.end
if val.kind_of?(Fixnum) && last.nil?
i = val
while true
block.call(i)
i += 1
end
return self
end
if val.kind_of?(String) && last.nil?
if val.respond_to? :__upto_endless
return val.__upto_endless(&block)
else
str_each = true
end
end
if val.kind_of?(Integer) && last.kind_of?(Integer) # fixnums are special
lim = last
......@@ -56,6 +73,11 @@ class Range
h += 1 if self.exclude_end?
h
end
def to_a
raise RangeError, "cannot convert endless range to an array" if self.last.nil?
super
end
end
##
......
......@@ -32,6 +32,8 @@ r_check(mrb_state *mrb, mrb_value a, mrb_value b)
return;
}
if (mrb_nil_p(b)) return;
n = mrb_cmp(mrb, a, b);
if (n == -2) { /* can not be compared */
mrb_raise(mrb, E_ARGUMENT_ERROR, "bad value for range");
......@@ -212,15 +214,19 @@ range_include(mrb_state *mrb, mrb_value range)
mrb_value val = mrb_get_arg1(mrb);
struct RRange *r = mrb_range_ptr(mrb, range);
mrb_value beg, end;
mrb_bool include_p;
beg = RANGE_BEG(r);
end = RANGE_END(r);
include_p = r_le(mrb, beg, val) && /* beg <= val */
(RANGE_EXCL(r) ? r_gt(mrb, end, val) /* end > val */
: r_ge(mrb, end, val)); /* end >= val */
return mrb_bool_value(include_p);
if (r_le(mrb, beg, val)) { /* beg <= val */
if (mrb_nil_p(end)) {
return mrb_true_value();
}
if (RANGE_EXCL(r) ? r_gt(mrb, end, val) /* end > val */
: r_ge(mrb, end, val)) { /* end >= val */
return mrb_true_value();
}
}
return mrb_false_value();
}
/* 15.2.14.4.12(x) */
......@@ -261,10 +267,10 @@ range_inspect(mrb_state *mrb, mrb_value range)
struct RRange *r = mrb_range_ptr(mrb, range);
str = mrb_inspect(mrb, RANGE_BEG(r));
str2 = mrb_inspect(mrb, RANGE_END(r));
if (!mrb_nil_p(RANGE_END(r))) str2 = mrb_inspect(mrb, RANGE_END(r));
str = mrb_str_dup(mrb, str);
mrb_str_cat(mrb, str, "...", RANGE_EXCL(r) ? 3 : 2);
mrb_str_cat_str(mrb, str, str2);
if (!mrb_nil_p(RANGE_END(r))) mrb_str_cat_str(mrb, str, str2);
return str;
}
......@@ -381,13 +387,15 @@ MRB_API enum mrb_range_beg_len
mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc)
{
mrb_int beg, end;
mrb_bool excl;
struct RRange *r;
if (!mrb_range_p(range)) return MRB_RANGE_TYPE_MISMATCH;
r = mrb_range_ptr(mrb, range);
beg = mrb_int(mrb, RANGE_BEG(r));
end = mrb_int(mrb, RANGE_END(r));
end = mrb_nil_p(RANGE_END(r)) ? -1 : mrb_int(mrb, RANGE_END(r));
excl = mrb_nil_p(RANGE_END(r)) ? 0 : RANGE_EXCL(r);
if (beg < 0) {
beg += len;
......@@ -400,7 +408,7 @@ mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp,
}
if (end < 0) end += len;
if (!RANGE_EXCL(r) && (!trunc || end < len)) end++; /* include end point */
if (!excl && (!trunc || end < len)) end++; /* include end point */
len = end - beg;
if (len < 0) len = 0;
......
......@@ -57,6 +57,7 @@ assert('Array#[]', '15.2.12.5.4') do
a = [ "a", "b", "c", "d", "e" ]
assert_equal(["b", "c"], a[1,2])
assert_equal(["b", "c", "d"], a[1..-2])
assert_equal(["b", "c", "d", "e"], a[1..])
skip unless Object.const_defined?(:Float)
assert_equal("b", a[1.1])
end
......@@ -92,6 +93,10 @@ assert('Array#[]=', '15.2.12.5.5') do
a[2...4] = 6
assert_equal([1,2,6,5], a)
a = [1,2,3,4,5]
a[2...] = 6
assert_equal([1,2,6], a)
# passing self (#3274)
a = [1,2,3]
a[1,0] = a
......
......@@ -8,19 +8,30 @@ end
assert('Range#==', '15.2.14.4.1') do
assert_true (1..10) == (1..10)
assert_false (1..10) == (1..100)
assert_false (1..10) == (1..)
assert_true (1..) == (1..nil)
assert_true (1..) == (1..)
assert_false (1..) == (1...)
skip unless Object.const_defined?(:Float)
assert_true (1..10) == Range.new(1.0, 10.0)
end
assert('Range#===', '15.2.14.4.2') do
a = (1..10)
b = (1..)
assert_true a === 5
assert_false a === 20
assert_true b === 20
assert_false b === 0
end
assert('Range#begin', '15.2.14.4.3') do
assert_equal 1, (1..10).begin
assert_equal 1, (1..).begin
end
assert('Range#each', '15.2.14.4.4') do
......@@ -28,27 +39,38 @@ assert('Range#each', '15.2.14.4.4') do
b = 0
a.each {|i| b += i}
assert_equal 6, b
c = []
(1..).each { |i| c << i; break if c.size == 10 }
assert_equal [1, 2, 3, 4, 5, 6, 7, 8 ,9, 10], c
end
assert('Range#end', '15.2.14.4.5') do
assert_equal 10, (1..10).end
assert_nil (1..).end
end
assert('Range#exclude_end?', '15.2.14.4.6') do
assert_true (1...10).exclude_end?
assert_false (1..10).exclude_end?
assert_true (1...).exclude_end?
assert_false (1..).exclude_end?
end
assert('Range#first', '15.2.14.4.7') do
assert_equal 1, (1..10).first
assert_equal 1, (1..).first
end
assert('Range#include?', '15.2.14.4.8') do
assert_true (1..10).include?(10)
assert_false (1..10).include?(11)
assert_true (1..).include?(10)
assert_false (1..).include?(0)
assert_true (1...10).include?(9)
assert_false (1...10).include?(10)
assert_true (1...).include?(10)
assert_false (1...).include?(0)
end
assert('Range#initialize', '15.2.14.4.9') do
......@@ -61,17 +83,29 @@ assert('Range#initialize', '15.2.14.4.9') do
assert_false b.exclude_end?
assert_raise(NameError) { (0..1).__send__(:initialize, 1, 3) }
c = Range.new(1, nil, true)
d = Range.new(1, nil, false)
assert_equal (1...nil), c
assert_true c.exclude_end?
assert_equal (1..nil), d
assert_false d.exclude_end?
end
assert('Range#last', '15.2.14.4.10') do
assert_equal 10, (1..10).last
assert_nil (1..).last
end
assert('Range#member?', '15.2.14.4.11') do
a = (1..10)
b = (1..)
assert_true a.member?(5)
assert_false a.member?(20)
assert_true b.member?(20)
assert_false b.member?(0)
end
assert('Range#to_s', '15.2.14.4.12') do
......@@ -79,6 +113,10 @@ assert('Range#to_s', '15.2.14.4.12') do
assert_equal "0...1", (0...1).to_s
assert_equal "a..b", ("a".."b").to_s
assert_equal "a...b", ("a"..."b").to_s
assert_equal "0..", (0..).to_s
assert_equal "0...", (0...).to_s
assert_equal "a..", ("a"..).to_s
assert_equal "a...", ("a"...).to_s
end
assert('Range#inspect', '15.2.14.4.13') do
......@@ -86,19 +124,36 @@ assert('Range#inspect', '15.2.14.4.13') do
assert_equal "0...1", (0...1).inspect
assert_equal "\"a\"..\"b\"", ("a".."b").inspect
assert_equal "\"a\"...\"b\"", ("a"..."b").inspect
assert_equal "0..", (0..).inspect
assert_equal "0...", (0...).inspect
assert_equal "\"a\"..", ("a"..).inspect
assert_equal "\"a\"...", ("a"...).inspect
end
assert('Range#eql?', '15.2.14.4.14') do
assert_true (1..10).eql? (1..10)
assert_false (1..10).eql? (1..100)
assert_false (1..10).eql? (Range.new(1.0, 10.0))
assert_false (1..10).eql? "1..10"
assert_true (1..).eql? (1..)
assert_false (1..).eql? (2..)
assert_false (1..).eql? "1.."
skip unless Object.const_defined?(:Float)
assert_false (1..10).eql? (Range.new(1.0, 10.0))
assert_false (1..).eql? (Range.new(1.0, nil))
end
assert('Range#initialize_copy', '15.2.14.4.15') do
assert_raise(NameError) { (0..1).__send__(:initialize_copy, 1..3) }
end
assert('Range#hash', '15.3.1.3.15') do
assert_kind_of(Integer, (1..10).hash)
assert_equal (1..10).hash, (1..10).hash
assert_not_equal (1..10).hash, (1...10).hash
assert_equal (1..).hash, (1..).hash
assert_not_equal (1..).hash, (1...).hash
end
assert('Range#dup') do
r = (1..3).dup
assert_equal 1, r.begin
......@@ -109,4 +164,15 @@ assert('Range#dup') do
assert_equal "a", r.begin
assert_equal "z", r.end
assert_true r.exclude_end?
r = (1..).dup
assert_equal 1, r.begin
assert_nil r.end
assert_false r.exclude_end?
end
assert('Range#to_a') do
assert_equal([1, 2, 3, 4, 5], (1..5).to_a)
assert_equal([1, 2, 3, 4], (1...5).to_a)
assert_raise(RangeError) { (1..).to_a }
end
......@@ -90,6 +90,7 @@ assert('String#[] with Range') do
h1 = 'abc'[3..4]
i1 = 'abc'[4..5]
j1 = 'abcdefghijklmnopqrstuvwxyz'[1..3]
k1 = 'abcdefghijklmnopqrstuvwxyz'[-3..]
a2 = 'abc'[1...0]
b2 = 'abc'[1...1]
c2 = 'abc'[1...2]
......@@ -100,6 +101,7 @@ assert('String#[] with Range') do
h2 = 'abc'[3...4]
i2 = 'abc'[4...5]
j2 = 'abcdefghijklmnopqrstuvwxyz'[1...3]
k2 = 'abcdefghijklmnopqrstuvwxyz'[-3...]
assert_equal '', a1
assert_equal 'b', b1
......@@ -111,6 +113,7 @@ assert('String#[] with Range') do
assert_equal '', h1
assert_nil i2
assert_equal 'bcd', j1
assert_equal 'xyz', k1
assert_equal '', a2
assert_equal '', b2
assert_equal 'b', c2
......@@ -121,6 +124,7 @@ assert('String#[] with Range') do
assert_equal '', h2
assert_nil i2
assert_equal 'bc', j2
assert_equal 'xyz', k2
end
assert('String#[]=') do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment