mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
proper type check when creating a range; #345
This commit is contained in:
+26
-32
@@ -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 */
|
||||
|
||||
|
||||
+1
-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
|
||||
|
||||
Reference in New Issue
Block a user