Permalink
Browse files

Check op overriden

  • Loading branch information...
junjis0203 committed Aug 8, 2012
1 parent 6b2e0b2 commit 048d2500b37a16c96e8cca53364adacd2ae7b471
Showing with 102 additions and 33 deletions.
  1. +2 −0 include/mruby/class.h
  2. +10 −0 include/mruby/numeric.h
  3. +1 −0 include/mruby/string.h
  4. +42 −0 src/class.c
  5. +47 −33 src/vm.c
View
@@ -63,6 +63,8 @@ void mrb_define_method_vm(mrb_state*, struct RClass*, mrb_sym, mrb_value);
void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, struct RProc *);
void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, int aspec);
+int mrb_check_op_overridden(mrb_state *mrb, mrb_value obj, mrb_sym op);
+
struct RClass *mrb_class_outer_module(mrb_state*, struct RClass *);
struct RProc *mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym);
struct RProc *mrb_method_search(mrb_state*, struct RClass*, mrb_sym);
View
@@ -17,6 +17,16 @@ extern "C" {
#define NEGFIXABLE(f) ((f) >= INT_MIN)
#define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f))
+#define MRB_NUM_OP_ADD (512 << 0)
+#define MRB_NUM_OP_SUB (512 << 1)
+#define MRB_NUM_OP_MUL (512 << 2)
+#define MRB_NUM_OP_DIV (512 << 3)
+#define MRB_NUM_OP_EQ (512 << 4)
+#define MRB_NUM_OP_LT (512 << 5)
+#define MRB_NUM_OP_LE (512 << 6)
+#define MRB_NUM_OP_GT (512 << 7)
+#define MRB_NUM_OP_GE (512 << 8)
+
mrb_value mrb_flt2big(mrb_state *mrb, mrb_float d);
mrb_value mrb_fix2str(mrb_state *mrb, mrb_value x, int base);
View
@@ -48,6 +48,7 @@ struct RString {
#define RSTRING_CAPA(s) (RSTRING(s)->aux.capa)
#define RSTRING_END(s) (RSTRING(s)->ptr + RSTRING(s)->len)
#define MRB_STR_SHARED 256
+#define MRB_STR_OP_ADD 512
void mrb_str_decref(mrb_state*, struct mrb_shared_string*);
mrb_value mrb_str_literal(mrb_state*, mrb_value);
View
@@ -323,6 +323,47 @@ mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t
mrb_define_method_id(mrb, c, mrb_intern(mrb, name), func, aspec);
}
+static int op2index(mrb_state *mrb, mrb_sym op)
+{
+ /* TODO: more efficient way */
+ if (op == mrb_intern2(mrb, "+", 1)) return 0;
+ if (op == mrb_intern2(mrb, "-", 1)) return 1;
+ if (op == mrb_intern2(mrb, "*", 1)) return 2;
+ if (op == mrb_intern2(mrb, "/", 1)) return 3;
+ if (op == mrb_intern2(mrb, "==", 2)) return 4;
+ if (op == mrb_intern2(mrb, "<", 1)) return 5;
+ if (op == mrb_intern2(mrb, "<=", 2)) return 6;
+ if (op == mrb_intern2(mrb, ">", 1)) return 7;
+ if (op == mrb_intern2(mrb, ">=", 2)) return 8;
+ return -1;
+}
+
+static void mrb_override_op(mrb_state *mrb, struct RClass *c, mrb_sym op)
+{
+ if (c == mrb->fixnum_class || c == mrb->float_class || c == mrb->string_class)
+ {
+ int index = op2index(mrb, op);
+ if (index != -1) {
+ /* MRB_NUM_OP_ADD and MRB_STR_OP_ADD are same value */
+ FL_SET(mrb_obj_value(c), MRB_NUM_OP_ADD << index);
+ }
+ }
+}
+
+int mrb_check_op_overridden(mrb_state *mrb, mrb_value obj, mrb_sym op)
+{
+ switch (mrb_type(obj)) {
+ case MRB_TT_FIXNUM:
+ return FL_TEST(mrb_obj_value(mrb->fixnum_class), MRB_NUM_OP_ADD << op2index(mrb, op));
+ case MRB_TT_FLOAT:
+ return FL_TEST(mrb_obj_value(mrb->float_class), MRB_NUM_OP_ADD << op2index(mrb, op));
+ case MRB_TT_STRING:
+ return FL_TEST(mrb_obj_value(mrb->string_class), MRB_STR_OP_ADD << op2index(mrb, op));
+ default:
+ return 0;
+ }
+}
+
void
mrb_define_method_vm(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_value body)
{
@@ -334,6 +375,7 @@ mrb_define_method_vm(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_value b
k = kh_put(mt, h, name);
p = mrb_proc_ptr(body);
kh_value(h, k) = p;
+ mrb_override_op(mrb, c, name);
}
static mrb_value
View
@@ -1197,29 +1197,36 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
#define OP_MATH(op,iop,s) do {\
int a = GETARG_A(i);\
/* need to check if op is overridden */\
- switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\
- case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\
- regs[a] = iop(mrb, regs[a], regs[a+1]);\
- break;\
- case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):\
- {\
- mrb_int x = regs[a].value.i;\
- mrb_float y = regs[a+1].value.f;\
- SET_FLOAT_VALUE(regs[a], (mrb_float)x op y);\
- }\
- break;\
- case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):\
- OP_MATH_BODY(op,f,i);\
- break;\
- case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\
- OP_MATH_BODY(op,f,f);\
- break;\
- s\
- default:\
+ if (mrb_check_op_overridden(mrb, regs[a], mrb_intern(mrb, #op))) {\
SET_NIL_VALUE(regs[a+2]);\
i = MKOP_ABC(OP_SEND, a, GETARG_B(i), GETARG_C(i));\
goto L_SEND;\
}\
+ else {\
+ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\
+ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\
+ regs[a] = iop(mrb, regs[a], regs[a+1]);\
+ break;\
+ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):\
+ {\
+ mrb_int x = regs[a].value.i;\
+ mrb_float y = regs[a+1].value.f;\
+ SET_FLOAT_VALUE(regs[a], (mrb_float)x op y);\
+ }\
+ break;\
+ case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):\
+ OP_MATH_BODY(op,f,i);\
+ break;\
+ case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\
+ OP_MATH_BODY(op,f,f);\
+ break;\
+ s\
+ default:\
+ SET_NIL_VALUE(regs[a+2]);\
+ i = MKOP_ABC(OP_SEND, a, GETARG_B(i), GETARG_C(i));\
+ goto L_SEND;\
+ }\
+ }\
} while (0)
CASE(OP_ADD) {
@@ -1304,24 +1311,31 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
#define OP_CMP(op) do {\
int a = GETARG_A(i);\
/* need to check if - is overridden */\
- switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\
- case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\
- OP_CMP_BODY(op,i,i); \
- break;\
- case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):\
- OP_CMP_BODY(op,i,f);\
- break;\
- case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):\
- OP_CMP_BODY(op,f,i);\
- break;\
- case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\
- OP_CMP_BODY(op,f,f);\
- break;\
- default:\
+ if (mrb_check_op_overridden(mrb, regs[a], mrb_intern(mrb, #op))) {\
SET_NIL_VALUE(regs[a+2]);\
i = MKOP_ABC(OP_SEND, a, GETARG_B(i), GETARG_C(i));\
goto L_SEND;\
}\
+ else {\
+ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\
+ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\
+ OP_CMP_BODY(op,i,i); \
+ break;\
+ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):\
+ OP_CMP_BODY(op,i,f);\
+ break;\
+ case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):\
+ OP_CMP_BODY(op,f,i);\
+ break;\
+ case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\
+ OP_CMP_BODY(op,f,f);\
+ break;\
+ default:\
+ SET_NIL_VALUE(regs[a+2]);\
+ i = MKOP_ABC(OP_SEND, a, GETARG_B(i), GETARG_C(i));\
+ goto L_SEND;\
+ }\
+ }\
} while (0)
CASE(OP_EQ) {

0 comments on commit 048d250

Please sign in to comment.