summaryrefslogtreecommitdiffhomepage
path: root/src/compar.c
diff options
context:
space:
mode:
authormimaki <[email protected]>2012-04-20 09:39:03 +0900
committermimaki <[email protected]>2012-04-20 09:39:03 +0900
commite0d6430f63c4cbe0c71ce82ee23284671389a818 (patch)
tree41abad7f12eced98d9ac14d141cea62464c3332f /src/compar.c
parent54ad561098ed353ada70205c39b2c42a2a2eb9e5 (diff)
downloadmruby-e0d6430f63c4cbe0c71ce82ee23284671389a818.tar.gz
mruby-e0d6430f63c4cbe0c71ce82ee23284671389a818.zip
add mruby sources
Diffstat (limited to 'src/compar.c')
-rw-r--r--src/compar.c144
1 files changed, 144 insertions, 0 deletions
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 <stdio.h>
+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 */
+}