From e0d6430f63c4cbe0c71ce82ee23284671389a818 Mon Sep 17 00:00:00 2001 From: mimaki Date: Fri, 20 Apr 2012 09:39:03 +0900 Subject: add mruby sources --- src/compar.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 src/compar.c (limited to 'src/compar.c') diff --git a/src/compar.c b/src/compar.c new file mode 100644 index 000000000..d66525c15 --- /dev/null +++ b/src/compar.c @@ -0,0 +1,144 @@ +#include "mruby.h" +#include "mruby/string.h" +#include "mruby/numeric.h" + +void +mrb_cmperr(mrb_state *mrb, mrb_value x, mrb_value y) +{ + const char *classname; + + if (SPECIAL_CONST_P(y)) { + y = mrb_inspect(mrb, y); + //classname = StringValuePtr(y); + classname = mrb_string_value_ptr(mrb, y); + } + else { + classname = mrb_obj_classname(mrb, y); + } + mrb_raise(mrb, E_ARGUMENT_ERROR, "comparison of %s with %s failed", + mrb_obj_classname(mrb, x), classname); +} + +int +mrb_cmpint(mrb_state *mrb, mrb_value val, mrb_value a, mrb_value b) +{ + if (mrb_nil_p(val)) { + mrb_cmperr(mrb, a, b); + } + if (FIXNUM_P(val)) { + long l = mrb_fixnum(val); + if (l > 0) return 1; + if (l < 0) return -1; + return 0; + } + if (mrb_test(mrb_funcall(mrb, val, ">", 1, mrb_fixnum_value(0)))) return 1; + if (mrb_test(mrb_funcall(mrb, val, "<", 1, mrb_fixnum_value(0)))) return -1; + return 0; +} + +static mrb_value +cmp_equal(mrb_state *mrb, mrb_value x) +{ + mrb_value y, c; + + /* *** TEMPORAL IMPLEMENT *** */ + + mrb_get_args(mrb, "o", &y); + if (mrb_obj_equal(mrb, x, y)) return mrb_true_value(); + + c = mrb_funcall(mrb, x, "<=>", 1, y); + + if (mrb_cmpint(mrb, c, x, y) == 0) return mrb_true_value(); + return mrb_false_value(); +} + +#include +static mrb_value +cmp_gt(mrb_state *mrb, mrb_value x, mrb_value y) +{ + mrb_value c; + + c = mrb_funcall(mrb, x, "<=>", 1, y); + + if (mrb_cmpint(mrb, c, x, y) > 0) return mrb_true_value(); + return mrb_false_value(); +} + +static mrb_value +cmp_gt_m(mrb_state *mrb, mrb_value x) +{ + mrb_value y; + + mrb_get_args(mrb, "o", &y); + return cmp_gt(mrb, x, y); +} + +static mrb_value +cmp_ge_m(mrb_state *mrb, mrb_value x) +{ + mrb_value y, c; + + mrb_get_args(mrb, "o", &y); + c = mrb_funcall(mrb, x, "<=>", 1, y); + + if (mrb_cmpint(mrb, c, x, y) >= 0) return mrb_true_value(); + return mrb_false_value(); +} + +static mrb_value +cmp_lt(mrb_state *mrb, mrb_value x, mrb_value y) +{ + mrb_value c; + + c = mrb_funcall(mrb, x, "<=>", 1, y); + + if (mrb_cmpint(mrb, c, x, y) < 0) return mrb_true_value(); + return mrb_false_value(); +} + +static mrb_value +cmp_lt_m(mrb_state *mrb, mrb_value x) +{ + mrb_value y; + + mrb_get_args(mrb, "o", &y); + return cmp_lt(mrb, x, y); +} + +static mrb_value +cmp_le_m(mrb_state *mrb, mrb_value x) +{ + mrb_value y, c; + + mrb_get_args(mrb, "o", &y); + c = mrb_funcall(mrb, x, "<=>", 1, y); + + if (mrb_cmpint(mrb, c, x, y) <= 0) return mrb_true_value(); + return mrb_false_value(); +} + +static mrb_value +cmp_between(mrb_state *mrb, mrb_value x) +{ + mrb_value min, max; + + mrb_get_args(mrb, "oo", &min, &max); + + if (mrb_test(cmp_lt(mrb, x, min))) return mrb_false_value(); + if (mrb_test(cmp_gt(mrb, x, max))) return mrb_false_value(); + return mrb_true_value(); +} + +void +mrb_init_comparable(mrb_state *mrb) +{ + struct RClass *comp; + + comp = mrb_define_module(mrb, "Comparable"); + mrb_define_method(mrb, comp, "<", cmp_lt_m, ARGS_REQ(1)); /* 15.3.3.2.1 */ + mrb_define_method(mrb, comp, "<=", cmp_le_m, ARGS_REQ(1)); /* 15.3.3.2.2 */ + mrb_define_method(mrb, comp, "==", cmp_equal, ARGS_REQ(1)); /* 15.3.3.2.3 */ + mrb_define_method(mrb, comp, ">", cmp_gt_m, ARGS_REQ(1)); /* 15.3.3.2.4 */ + mrb_define_method(mrb, comp, ">=", cmp_ge_m, ARGS_REQ(1)); /* 15.3.3.2.5 */ + mrb_define_method(mrb, comp, "between?", cmp_between, ARGS_REQ(2)); /* 15.3.3.2.6 */ +} -- cgit v1.2.3