Commit 0d99856b authored by Yukihiro Matsumoto's avatar Yukihiro Matsumoto

proper type check when creating a range; #345

parent becb7e98
......@@ -21,6 +21,30 @@
#define RANGE_CLASS (mrb_class_obj_get(mrb, "Range"))
static void
range_check(mrb_state *mrb, mrb_value a, mrb_value b)
{
mrb_value ans;
switch (mrb_type(a)) {
case MRB_TT_FIXNUM:
case MRB_TT_FLOAT:
switch (mrb_type(b)) {
case MRB_TT_FIXNUM:
case MRB_TT_FLOAT:
return;
}
}
mrb_p(mrb, a);
mrb_p(mrb, b);
ans = mrb_funcall(mrb, a, "<=>", 1, b);
if (mrb_nil_p(ans)) {
/* can not be compared */
mrb_raise(mrb, E_ARGUMENT_ERROR, "bad value for range");
}
}
mrb_value
mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, int excl)
{
......@@ -28,6 +52,7 @@ mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, int excl)
r = (struct RRange*)mrb_obj_alloc(mrb, MRB_TT_RANGE, RANGE_CLASS);
r->edges = mrb_malloc(mrb, sizeof(struct mrb_range_edges));
range_check(mrb, beg, end);
r->edges->beg = beg;
r->edges->end = end;
r->excl = excl;
......@@ -82,39 +107,12 @@ mrb_range_excl(mrb_state *mrb, mrb_value range)
return r->excl ? mrb_true_value() : mrb_false_value();
}
/*
* call-seq:
* beg end
* args[0] <= args[1] => true
* args[0] > args[1] => false
*/
static int
range_check(mrb_state *mrb, mrb_value *args)
{
mrb_value ans = mrb_funcall(mrb, args[0], "<=>", 1, args[1]);
/* beg end
ans :args[0] < args[1] => -1
args[0] = args[1] => 0
args[0] > args[1] => +1 */
if (mrb_nil_p(ans)) return FALSE;
//if (mrb_obj_equal(mrb, ans, mrb_fixnum_value(1))) return FALSE;
if (mrb_fixnum(ans) == 1) return FALSE;
return TRUE;
}
static void
range_init(mrb_state *mrb, mrb_value range, mrb_value beg, mrb_value end, mrb_int exclude_end)
{
mrb_value args[2];
struct RRange *r = mrb_range_ptr(range);
if ((mrb_type(beg) != MRB_TT_FIXNUM) || (mrb_type(end) != MRB_TT_FIXNUM)) {
args[0] = beg;
args[1] = end;
if (!range_check(mrb, args)) {
printf("range_failed()\n");
}
}
range_check(mrb, beg, end);
r->excl = exclude_end;
r->edges->beg = beg;
r->edges->end = end;
......@@ -166,7 +164,6 @@ mrb_range_eq(mrb_state *mrb, mrb_value range)
if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
/* same class? */
// if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range)))
return mrb_false_value();
......@@ -199,12 +196,10 @@ r_le(mrb_state *mrb, mrb_value a, mrb_value b)
static int
r_gt(mrb_state *mrb, mrb_value a, mrb_value b)
{
//int c;
mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b);
/* output :a < b => -1, a = b => 0, a > b => +1 */
if (mrb_nil_p(r)) return FALSE;
if (mrb_obj_equal(mrb, r, mrb_fixnum_value(1))) return TRUE;
return FALSE;
}
......@@ -212,7 +207,6 @@ r_gt(mrb_state *mrb, mrb_value a, mrb_value b)
static int
r_ge(mrb_state *mrb, mrb_value a, mrb_value b)
{
//int c;
mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
/* output :a < b => -1, a = b => 0, a > b => +1 */
......
......@@ -62,7 +62,7 @@ end
assert('BS Block 7') do
ans = []
for m in 1..3
for n in 1..3
for n in 2..4
a = [m, n]
ans << a
end
......
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