Project

General

Profile

refinements-r29944-20101127.diff

a patch to support Refinements - shugo (Shugo Maeda), 11/27/2010 01:39 PM

View differences:

class.c
617 617
    return module;
618 618
}
619 619

  
620
static VALUE
621
include_class_new(VALUE module, VALUE super)
620
VALUE
621
rb_include_class_new(VALUE module, VALUE super)
622 622
{
623 623
    VALUE klass = class_alloc(T_ICLASS, rb_cClass);
624 624

  
......
685 685
		break;
686 686
	    }
687 687
	}
688
	c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c));
688
	c = RCLASS_SUPER(c) = rb_include_class_new(module, RCLASS_SUPER(c));
689 689
	if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries)
690 690
	    changed = 1;
691 691
      skip:
eval.c
23 23
VALUE rb_binding_new(void);
24 24
NORETURN(void rb_raise_jump(VALUE));
25 25

  
26
NODE *rb_vm_get_cref(const rb_iseq_t *, const VALUE *, const VALUE *);
27

  
26 28
ID rb_frame_callee(void);
27 29
VALUE rb_eLocalJumpError;
28 30
VALUE rb_eSysStackError;
......
858 860
}
859 861

  
860 862
void
863
rb_overlay_module(NODE *cref, VALUE klass, VALUE module)
864
{
865
    VALUE iclass, c, superclass = klass;
866

  
867
    Check_Type(klass, T_CLASS);
868
    Check_Type(module, T_MODULE);
869
    if (NIL_P(cref->nd_omod)) {
870
	cref->nd_omod = rb_hash_new();
871
	rb_funcall(cref->nd_omod, rb_intern("compare_by_identity"), 0);
872
    }
873
    else {
874
	if (cref->flags & NODE_FL_CREF_OMOD_SHARED) {
875
	    cref->nd_omod = rb_hash_dup(cref->nd_omod);
876
	    cref->flags &= ~NODE_FL_CREF_OMOD_SHARED;
877
	}
878
	if (!NIL_P(c = rb_hash_lookup(cref->nd_omod, klass))) {
879
	    superclass = c;
880
	    while (c && TYPE(c) == T_ICLASS) {
881
		if (RBASIC(c)->klass == module) {
882
		    /* already overlayed module */
883
		    return;
884
		}
885
		c = RCLASS_SUPER(c);
886
	    }
887
	}
888
    }
889
    FL_SET(module, RMODULE_IS_OVERLAYED);
890
    c = iclass = rb_include_class_new(module, superclass);
891
    module = RCLASS_SUPER(module);
892
    while (module) {
893
	FL_SET(module, RMODULE_IS_OVERLAYED);
894
	c = RCLASS_SUPER(c) = rb_include_class_new(module, RCLASS_SUPER(c));
895
	module = RCLASS_SUPER(module);
896
    }
897
    rb_hash_aset(cref->nd_omod, klass, iclass);
898
    rb_clear_cache_by_class(klass);
899
}
900

  
901
static int
902
using_module_i(VALUE klass, VALUE module, VALUE arg)
903
{
904
    NODE *cref = (NODE *) arg;
905
    int i;
906

  
907
    rb_overlay_module(cref, klass, module);
908
    return ST_CONTINUE;
909
}
910

  
911
void
912
rb_using_module(NODE *cref, VALUE module)
913
{
914
    ID id_overlayed_modules;
915
    VALUE overlayed_modules;
916

  
917
    Check_Type(module, T_MODULE);
918
    CONST_ID(id_overlayed_modules, "__overlayed_modules__");
919
    overlayed_modules = rb_attr_get(module, id_overlayed_modules);
920
    if (NIL_P(overlayed_modules)) return;
921
    rb_hash_foreach(overlayed_modules, using_module_i, (VALUE) cref);
922
}
923

  
924
/*
925
 *  call-seq:
926
 *     using(module)    -> self
927
 *
928
 *  Import class refinements from <i>module</i> into the receiver.
929
 */
930

  
931
static VALUE
932
rb_mod_using(VALUE self, VALUE module)
933
{
934
    NODE *cref = rb_vm_cref();
935
    ID id_using_modules;
936
    VALUE using_modules;
937

  
938
    CONST_ID(id_using_modules, "__using_modules__");
939
    using_modules = rb_attr_get(self, id_using_modules);
940
    if (NIL_P(using_modules)) {
941
	using_modules = rb_hash_new();
942
	rb_funcall(using_modules, rb_intern("compare_by_identity"), 0);
943
	rb_ivar_set(self, id_using_modules, using_modules);
944
    }
945
    rb_hash_aset(using_modules, module, Qtrue);
946
    rb_using_module(cref, module);
947
    rb_funcall(module, rb_intern("used"), 1, self);
948
    return self;
949
}
950

  
951
void rb_redefine_opt_method(VALUE, ID);
952

  
953
static VALUE
954
refinement_module_method_added(VALUE mod, VALUE mid)
955
{
956
    ID id = SYM2ID(mid);
957
    ID id_refined_class;
958
    VALUE klass;
959

  
960
    CONST_ID(id_refined_class, "__refined_class__");
961
    klass = rb_ivar_get(mod, id_refined_class);
962
    rb_redefine_opt_method(klass, id);
963
}
964

  
965
static VALUE
966
refinement_module_include(int argc, VALUE *argv, VALUE module)
967
{
968
    rb_thread_t *th = GET_THREAD();
969
    rb_control_frame_t *cfp = th->cfp;
970
    rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(th);
971
    VALUE result = rb_mod_include(argc, argv, module);
972
    NODE *cref;
973
    ID id_refined_class;
974
    VALUE klass, c;
975

  
976
    CONST_ID(id_refined_class, "__refined_class__");
977
    klass = rb_attr_get(module, id_refined_class);
978
    while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
979
	if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq) &&
980
	    (cref = rb_vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp)) &&
981
	    !NIL_P(cref->nd_omod) &&
982
	    !NIL_P(c = rb_hash_lookup(cref->nd_omod, klass))) {
983
	    while (argc--) {
984
		VALUE mod = argv[argc];
985
		if (rb_class_inherited_p(module, mod)) {
986
		    RCLASS_SUPER(c) =
987
			rb_include_class_new(mod, RCLASS_SUPER(c));
988
		}
989
	    }
990
	    break;
991
	}
992
	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
993
    }
994
    return result;
995
}
996

  
997
/*
998
 *  call-seq:
999
 *     refine(klass) { block }   -> self
1000
 *
1001
 *  Refine <i>klass</i> in the receiver.
1002
 */
1003

  
1004
static VALUE
1005
rb_mod_refine(VALUE module, VALUE klass)
1006
{
1007
    NODE *cref = rb_vm_cref();
1008
    VALUE mod;
1009
    ID id_overlayed_modules, id_refined_class;
1010
    VALUE overlayed_modules, modules;
1011

  
1012
    Check_Type(klass, T_CLASS);
1013
    CONST_ID(id_overlayed_modules, "__overlayed_modules__");
1014
    overlayed_modules = rb_attr_get(module, id_overlayed_modules);
1015
    if (NIL_P(overlayed_modules)) {
1016
	overlayed_modules = rb_hash_new();
1017
	rb_funcall(overlayed_modules, rb_intern("compare_by_identity"), 0);
1018
	rb_ivar_set(module, id_overlayed_modules, overlayed_modules);
1019
    }
1020
    mod = rb_hash_aref(overlayed_modules, klass);
1021
    if (NIL_P(mod)) {
1022
	mod = rb_module_new();
1023
	CONST_ID(id_refined_class, "__refined_class__");
1024
	rb_ivar_set(mod, id_refined_class, klass);
1025
	rb_define_singleton_method(mod, "method_added",
1026
				   refinement_module_method_added, 1);
1027
	rb_define_singleton_method(mod, "include",
1028
				   refinement_module_include, -1);
1029
	rb_overlay_module(cref, klass, mod);
1030
	rb_hash_aset(overlayed_modules, klass, mod);
1031
    }
1032
    rb_mod_module_eval(0, NULL, mod);
1033
    return mod;
1034
}
1035

  
1036
void
861 1037
rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
862 1038
{
863 1039
    PASS_PASSED_BLOCK();
......
969 1145
    return rb_mod_include(argc, argv, rb_cObject);
970 1146
}
971 1147

  
1148
/*
1149
 *  call-seq:
1150
 *     using(module)    -> self
1151
 *
1152
 *  Import class refinements from <i>module</i> into the scope where <code>use</code> is called.
1153
 */
1154

  
1155
static VALUE
1156
f_using(VALUE self, VALUE module)
1157
{
1158
    NODE *cref = rb_vm_cref();
1159

  
1160
    rb_using_module(cref, module);
1161
    return self;
1162
}
1163

  
972 1164
VALUE rb_f_trace_var();
973 1165
VALUE rb_f_untrace_var();
974 1166

  
......
1121 1313
    rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
1122 1314
    rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
1123 1315
    rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
1316
    rb_define_private_method(rb_cModule, "using", rb_mod_using, 1);
1317
    rb_define_private_method(rb_cModule, "refine", rb_mod_refine, 1);
1124 1318

  
1125 1319
    rb_undef_method(rb_cClass, "module_function");
1126 1320

  
......
1136 1330

  
1137 1331
    rb_define_singleton_method(rb_vm_top_self(), "include", top_include, -1);
1138 1332

  
1333
    rb_define_global_function("using", f_using, 1);
1334

  
1139 1335
    rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
1140 1336

  
1141 1337
    rb_define_global_function("trace_var", rb_f_trace_var, -1);	/* in variable.c */
gc.c
1684 1684
	    ptr = (VALUE)obj->as.node.u2.node;
1685 1685
	    goto again;
1686 1686

  
1687
	  case NODE_CREF:
1688
	    gc_mark(objspace, obj->as.node.u0.value, lev);
1689
	    gc_mark(objspace, (VALUE)obj->as.node.u1.node, lev);
1690
	    ptr = (VALUE)obj->as.node.u3.node;
1691
	    goto again;
1692

  
1687 1693
	  default:		/* unlisted NODE */
1688 1694
	    if (is_pointer_to_heap(objspace, obj->as.node.u1.node)) {
1689 1695
		gc_mark(objspace, (VALUE)obj->as.node.u1.node, lev);
include/ruby/intern.h
169 169
VALUE rb_module_new(void);
170 170
VALUE rb_define_module_id(ID);
171 171
VALUE rb_define_module_id_under(VALUE, ID);
172
VALUE rb_include_class_new(VALUE, VALUE);
172 173
VALUE rb_mod_included_modules(VALUE);
173 174
VALUE rb_mod_include_p(VALUE, VALUE);
174 175
VALUE rb_mod_ancestors(VALUE);
include/ruby/ruby.h
629 629
#define RMODULE_CONST_TBL(m) RCLASS_CONST_TBL(m)
630 630
#define RMODULE_M_TBL(m) RCLASS_M_TBL(m)
631 631
#define RMODULE_SUPER(m) RCLASS_SUPER(m)
632
#define RMODULE_IS_OVERLAYED FL_USER2
632 633

  
633 634
struct RFloat {
634 635
    struct RBasic basic;
insns.def
183 183
()
184 184
(VALUE val)
185 185
{
186
    NODE * const cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
187
    val = rb_cvar_get(vm_get_cvar_base(cref), id);
186
    NODE * const cref = rb_vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
187
    val = rb_cvar_get(vm_get_cvar_base(cref, GET_CFP()), id);
188 188
}
189 189

  
190 190
/**
......
198 198
(VALUE val)
199 199
()
200 200
{
201
    NODE * const cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
202
    rb_cvar_set(vm_get_cvar_base(cref), id, val);
201
    NODE * const cref = rb_vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
202
    rb_cvar_set(vm_get_cvar_base(cref, GET_CFP()), id, val);
203 203
}
204 204

  
205 205
/**
......
967 967
		  VM_FRAME_MAGIC_CLASS, klass, 0, (VALUE) GET_BLOCK_PTR(),
968 968
		  class_iseq->iseq_encoded, GET_SP(), 0,
969 969
		  class_iseq->local_size);
970
    rb_vm_using_modules(class_iseq->cref_stack, klass);
970 971
    RESTORE_REGS();
971 972

  
972 973
    INC_VM_STATE_VERSION();
......
1041 1042
    while (ip && !ip->klass) {
1042 1043
	ip = ip->parent_iseq;
1043 1044
    }
1044
  again:
1045 1045
    me = rb_method_entry(klass, id, &klass);
1046 1046
    if (me && me->def->type == VM_METHOD_TYPE_ISEQ &&
1047 1047
	me->def->body.iseq == ip) {
1048 1048
	klass = RCLASS_SUPER(klass);
1049
	goto again;
1049
	me = rb_method_entry_get_with_omod(Qnil, klass, id, &klass);
1050 1050
    }
1051 1051

  
1052 1052
    CALL_METHOD(num, blockptr, flag, id, me, recv, klass);
iseq.c
182 182
    /* set class nest stack */
183 183
    if (type == ISEQ_TYPE_TOP) {
184 184
	/* toplevel is private */
185
	iseq->cref_stack = NEW_BLOCK(rb_cObject);
186
	iseq->cref_stack->nd_file = 0;
185
	iseq->cref_stack = NEW_CREF(rb_cObject);
186
	iseq->cref_stack->nd_omod = Qnil;
187 187
	iseq->cref_stack->nd_visi = NOEX_PRIVATE;
188 188
	if (th->top_wrapper) {
189
	    NODE *cref = NEW_BLOCK(th->top_wrapper);
190
	    cref->nd_file = 0;
189
	    NODE *cref = NEW_CREF(th->top_wrapper);
190
	    cref->nd_omod = Qnil;
191 191
	    cref->nd_visi = NOEX_PRIVATE;
192 192
	    cref->nd_next = iseq->cref_stack;
193 193
	    iseq->cref_stack = cref;
194 194
	}
195 195
    }
196 196
    else if (type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
197
	iseq->cref_stack = NEW_BLOCK(0); /* place holder */
198
	iseq->cref_stack->nd_file = 0;
197
	iseq->cref_stack = NEW_CREF(0); /* place holder */
198
	iseq->cref_stack->nd_omod = Qnil;
199 199
    }
200 200
    else if (RTEST(parent)) {
201 201
	rb_iseq_t *piseq;
......
1368 1368
	iseq1->local_iseq = iseq1;
1369 1369
    }
1370 1370
    if (newcbase) {
1371
	iseq1->cref_stack = NEW_BLOCK(newcbase);
1371
	iseq1->cref_stack = NEW_CREF(newcbase);
1372
	iseq1->cref_stack->nd_omod = iseq0->cref_stack->nd_omod;
1373
	iseq1->cref_stack->nd_visi = iseq0->cref_stack->nd_visi;
1372 1374
	if (iseq0->cref_stack->nd_next) {
1373 1375
	    iseq1->cref_stack->nd_next = iseq0->cref_stack->nd_next;
1374 1376
	}
method.h
91 91
rb_method_entry_t *rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_flag_t noex);
92 92
rb_method_entry_t *rb_method_entry(VALUE klass, ID id, VALUE *define_class_ptr);
93 93

  
94
rb_method_entry_t *rb_method_entry_get_without_cache(VALUE klass, ID id, VALUE *define_class_ptr);
94
rb_method_entry_t *rb_method_entry_get_with_omod(VALUE omod, VALUE klass, ID id, VALUE *define_class_ptr);
95
rb_method_entry_t *rb_method_entry_get_without_cache(VALUE klass, VALUE omod, ID id, VALUE *define_class_ptr);
95 96
rb_method_entry_t *rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *, rb_method_flag_t noex);
96 97

  
97 98
int rb_method_entry_arity(const rb_method_entry_t *me);
node.h
188 188
#define NODE_COLON2      NODE_COLON2
189 189
    NODE_COLON3,
190 190
#define NODE_COLON3      NODE_COLON3
191
    NODE_CREF,
192
#define NODE_CREF        NODE_CREF
191 193
    NODE_DOT2,
192 194
#define NODE_DOT2        NODE_DOT2
193 195
    NODE_DOT3,
......
234 236

  
235 237
typedef struct RNode {
236 238
    unsigned long flags;
237
    char *nd_file;
239
    union {
240
	char *file;
241
	VALUE value;
242
    } u0;
238 243
    union {
239 244
	struct RNode *node;
240 245
	ID id;
......
260 265

  
261 266
#define RNODE(obj)  (R_CAST(RNode)(obj))
262 267

  
263
/* 0..4:T_TYPES, 5:FL_MARK, 6:reserved, 7:NODE_FL_NEWLINE */
268
/* 0..4:T_TYPES, 5:FL_MARK, 6:NODE_FL_CREF_OMOD_SHARED, 7:NODE_FL_NEWLINE */
264 269
#define NODE_FL_NEWLINE (((VALUE)1)<<7)
265 270
#define NODE_FL_CREF_PUSHED_BY_EVAL NODE_FL_NEWLINE
271
#define NODE_FL_CREF_OMOD_SHARED (((VALUE)1)<<6)
266 272

  
267 273
#define NODE_TYPESHIFT 8
268 274
#define NODE_TYPEMASK  (((VALUE)0x7f)<<NODE_TYPESHIFT)
......
277 283
#define nd_set_line(n,l) \
278 284
    RNODE(n)->flags=((RNODE(n)->flags&~(-1<<NODE_LSHIFT))|(((l)&NODE_LMASK)<<NODE_LSHIFT))
279 285

  
286
#define nd_file  u0.file
287
#define nd_omod  u0.value
288

  
280 289
#define nd_head  u1.node
281 290
#define nd_alen  u2.argc
282 291
#define nd_next  u3.node
......
433 442
#define NEW_MODULE(n,b) NEW_NODE(NODE_MODULE,n,NEW_SCOPE(0,b),0)
434 443
#define NEW_COLON2(c,i) NEW_NODE(NODE_COLON2,c,i,0)
435 444
#define NEW_COLON3(i) NEW_NODE(NODE_COLON3,0,i,0)
445
#define NEW_CREF(a) NEW_NODE(NODE_CREF,a,0,0)
436 446
#define NEW_DOT2(b,e) NEW_NODE(NODE_DOT2,b,e,0)
437 447
#define NEW_DOT3(b,e) NEW_NODE(NODE_DOT3,b,e,0)
438 448
#define NEW_SELF() NEW_NODE(NODE_SELF,0,0,0)
object.c
2531 2531
    rb_define_private_method(rb_cClass, "inherited", rb_obj_dummy, 1);
2532 2532
    rb_define_private_method(rb_cModule, "included", rb_obj_dummy, 1);
2533 2533
    rb_define_private_method(rb_cModule, "extended", rb_obj_dummy, 1);
2534
    rb_define_private_method(rb_cModule, "used", rb_obj_dummy, 1);
2534 2535
    rb_define_private_method(rb_cModule, "method_added", rb_obj_dummy, 1);
2535 2536
    rb_define_private_method(rb_cModule, "method_removed", rb_obj_dummy, 1);
2536 2537
    rb_define_private_method(rb_cModule, "method_undefined", rb_obj_dummy, 1);
test/ruby/test_refinement.rb
1
require 'test/unit'
2

  
3
class TestRefinement < Test::Unit::TestCase
4
  class Foo
5
    def x
6
      return "Foo#x"
7
    end
8

  
9
    def y
10
      return "Foo#y"
11
    end
12

  
13
    def call_x
14
      return x
15
    end
16
  end
17

  
18
  module FooExt
19
    refine Foo do
20
      def x
21
        return "FooExt#x"
22
      end
23

  
24
      def y
25
        return "FooExt#y " + super
26
      end
27

  
28
      def z
29
        return "FooExt#z"
30
      end
31
    end
32
  end
33

  
34
  module FooExt2
35
    refine Foo do
36
      def x
37
        return "FooExt2#x"
38
      end
39

  
40
      def y
41
        return "FooExt2#y " + super
42
      end
43

  
44
      def z
45
        return "FooExt2#z"
46
      end
47
    end
48
  end
49

  
50
  class FooSub < Foo
51
    def x
52
      return "FooSub#x"
53
    end
54

  
55
    def y
56
      return "FooSub#y " + super
57
    end
58
  end
59

  
60
  class FooExtClient
61
    using FooExt
62

  
63
    def self.invoke_x_on(foo)
64
      return foo.x
65
    end
66

  
67
    def self.invoke_y_on(foo)
68
      return foo.y
69
    end
70

  
71
    def self.invoke_z_on(foo)
72
      return foo.z
73
    end
74

  
75
    def self.invoke_call_x_on(foo)
76
      return foo.call_x
77
    end
78
  end
79

  
80
  class FooExtClient2
81
    using FooExt
82
    using FooExt2
83

  
84
    def self.invoke_y_on(foo)
85
      return foo.y
86
    end
87
  end
88

  
89
  def test_override
90
    foo = Foo.new
91
    assert_equal("Foo#x", foo.x)
92
    assert_equal("FooExt#x", FooExtClient.invoke_x_on(foo))
93
    assert_equal("Foo#x", foo.x)
94
  end
95

  
96
  def test_super
97
    foo = Foo.new
98
    assert_equal("Foo#y", foo.y)
99
    assert_equal("FooExt#y Foo#y", FooExtClient.invoke_y_on(foo))
100
    assert_equal("Foo#y", foo.y)
101
  end
102

  
103
  def test_super_chain
104
    foo = Foo.new
105
    assert_equal("Foo#y", foo.y)
106
    assert_equal("FooExt2#y FooExt#y Foo#y", FooExtClient2.invoke_y_on(foo))
107
    assert_equal("Foo#y", foo.y)
108
  end
109

  
110
  def test_new_method
111
    foo = Foo.new
112
    assert_raise(NoMethodError) { foo.z }
113
    assert_equal("FooExt#z", FooExtClient.invoke_z_on(foo))
114
    assert_raise(NoMethodError) { foo.z }
115
  end
116

  
117
  def test_no_local_rebinding
118
    foo = Foo.new
119
    assert_equal("Foo#x", foo.call_x)
120
    assert_equal("Foo#x", FooExtClient.invoke_call_x_on(foo))
121
    assert_equal("Foo#x", foo.call_x)
122
  end
123

  
124
  def test_subclass_is_prior
125
    sub = FooSub.new
126
    assert_equal("FooSub#x", sub.x)
127
    assert_equal("FooSub#x", FooExtClient.invoke_x_on(sub))
128
    assert_equal("FooSub#x", sub.x)
129
  end
130

  
131
  def test_subclass_is_prior
132
    sub = FooSub.new
133
    assert_equal("FooSub#x", sub.x)
134
    assert_equal("FooSub#x", FooExtClient.invoke_x_on(sub))
135
    assert_equal("FooSub#x", sub.x)
136
  end
137

  
138
  def test_super_in_subclass
139
    sub = FooSub.new
140
    assert_equal("FooSub#y Foo#y", sub.y)
141
    # not "FooSub#y FooExt#y Foo#y"
142
    assert_equal("FooSub#y Foo#y", FooExtClient.invoke_y_on(sub))
143
    assert_equal("FooSub#y Foo#y", sub.y)
144
  end
145

  
146
  def test_new_method_on_subclass
147
    sub = FooSub.new
148
    assert_raise(NoMethodError) { sub.z }
149
    assert_equal("FooExt#z", FooExtClient.invoke_z_on(sub))
150
    assert_raise(NoMethodError) { sub.z }
151
  end
152

  
153
  def test_module_eval
154
    foo = Foo.new
155
    assert_equal("Foo#x", foo.x)
156
    assert_equal("FooExt#x", FooExt.module_eval { foo.x })
157
    assert_equal("Foo#x", foo.x)
158
  end
159

  
160
  def test_instance_eval
161
    foo = Foo.new
162
    ext_client = FooExtClient.new
163
    assert_equal("Foo#x", foo.x)
164
    assert_equal("FooExt#x", ext_client.instance_eval { foo.x })
165
    assert_equal("Foo#x", foo.x)
166
  end
167

  
168
  def test_override_builtin_method
169
    m = Module.new {
170
      refine Fixnum do
171
        def /(other) quo(other) end
172
      end
173
    }
174
    assert_equal(0, 1 / 2)
175
    assert_equal(Rational(1, 2), m.module_eval { 1 / 2 })
176
    assert_equal(0, 1 / 2)
177
  end
178

  
179
  def test_return_value_of_refine
180
    mod = nil
181
    result = nil
182
    m = Module.new {
183
      result = refine(Object) {
184
        mod = self
185
      }
186
    }
187
    assert_equal mod, result
188
  end
189

  
190
  def test_refine_same_class_twice
191
    result1 = nil
192
    result2 = nil
193
    result3 = nil
194
    m = Module.new {
195
      result1 = refine(Fixnum) {
196
        def foo; return "foo" end
197
      }
198
      result2 = refine(Fixnum) {
199
        def bar; return "bar" end
200
      }
201
      result3 = refine(String) {
202
        def baz; return "baz" end
203
      }
204
    }
205
    assert_equal("foo", m.module_eval { 1.foo })
206
    assert_equal("bar", m.module_eval { 1.bar })
207
    assert_equal(result1, result2)
208
    assert_not_equal(result1, result3)
209
  end
210

  
211
  def test_respond_to?
212
    m = Module.new {
213
      refine Fixnum do
214
        def foo; "foo"; end
215
      end
216
    }
217
    assert_equal(false, 1.respond_to?(:foo))
218
    assert_equal(true, m.module_eval { 1.respond_to?(:foo) })
219
    assert_equal(false, 1.respond_to?(:foo))
220
  end
221

  
222
  def test_builtin_method_no_local_rebinding
223
    m = Module.new {
224
      refine String do
225
        def <=>(other) return 0 end
226
      end
227
    }
228
    assert_equal(false, m.module_eval { "1" >= "2" })
229

  
230
    m2 = Module.new {
231
      refine Array do
232
        def each
233
          super do |i|
234
            yield 2 * i
235
          end
236
        end
237
      end
238
    }
239
    a = [1, 2, 3]
240
    assert_equal(1, m2.module_eval { a.min })
241
  end
242

  
243
  def test_module_inclusion
244
    m1 = Module.new {
245
      def foo
246
        "m1#foo"
247
      end
248

  
249
      def bar
250
        "m1#bar"
251
      end
252
    }
253
    m2 = Module.new {
254
      def bar
255
        "m2#bar"
256
      end
257

  
258
      def baz
259
        "m2#baz"
260
      end
261
    }
262
    m3 = Module.new {
263
      def baz
264
        "m3#baz"
265
      end
266
    }
267
    include_proc = Proc.new {
268
      include m3, m2
269
    }
270
    m = Module.new {
271
      refine String do
272
        include m1
273
        module_eval(&include_proc)
274

  
275
        def call_foo
276
          foo
277
        end
278

  
279
        def call_bar
280
          bar
281
        end
282

  
283
        def call_baz
284
          baz
285
        end
286
      end
287

  
288
      def self.call_foo(s)
289
        s.foo
290
      end
291

  
292
      def self.call_bar(s)
293
        s.bar
294
      end
295

  
296
      def self.call_baz(s)
297
        s.baz
298
      end
299
    }
300
    assert_equal("m1#foo", m.module_eval { "abc".foo })
301
    assert_equal("m2#bar", m.module_eval { "abc".bar })
302
    assert_equal("m3#baz", m.module_eval { "abc".baz })
303
    assert_equal("m1#foo", m.module_eval { "abc".call_foo })
304
    assert_equal("m2#bar", m.module_eval { "abc".call_bar })
305
    assert_equal("m3#baz", m.module_eval { "abc".call_baz })
306
    assert_equal("m1#foo", m.call_foo("abc"))
307
    assert_equal("m2#bar", m.call_bar("abc"))
308
    assert_equal("m3#baz", m.call_baz("abc"))
309
  end
310
end
311

  
vm.c
819 819
{
820 820
    rb_thread_t *th = GET_THREAD();
821 821
    rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
822
    return vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
822
    if (!cfp) return NULL;
823
    return rb_vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
823 824
}
824 825

  
825 826
#if 0
vm_eval.c
372 372
                         rb_id2name(mid), type, (void *)recv, flags, klass);
373 373
        }
374 374
    }
375
    return rb_method_entry(klass, mid, defined_class_ptr);
375
    return rb_method_entry_get_with_omod(Qnil, klass, mid, defined_class_ptr);
376 376
}
377 377

  
378 378
static inline int
......
1213 1213
    }
1214 1214
    cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
1215 1215
    cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
1216
    rb_vm_using_modules(cref, under);
1216 1217

  
1217 1218
    if (values == Qundef) {
1218 1219
	return vm_yield_with_cref(th, 1, &self, cref);
......
1234 1235
    else {
1235 1236
	SafeStringValue(src);
1236 1237
    }
1238
    rb_vm_using_modules(cref, under);
1237 1239

  
1238 1240
    return eval_string_with_cref(self, src, Qnil, cref, file, line);
1239 1241
}
vm_insnhelper.c
1091 1091
    }
1092 1092
}
1093 1093

  
1094
static NODE *
1095
vm_get_cref(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
1094
NODE *
1095
rb_vm_get_cref(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
1096 1096
{
1097 1097
    NODE *cref = vm_get_cref0(iseq, lfp, dfp);
1098 1098

  
1099 1099
    if (cref == 0) {
1100
	rb_bug("vm_get_cref: unreachable");
1100
	rb_bug("rb_vm_get_cref: unreachable");
1101 1101
    }
1102 1102
    return cref;
1103 1103
}
......
1106 1106
vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr)
1107 1107
{
1108 1108
    rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
1109
    NODE *cref = NEW_BLOCK(klass);
1110
    cref->nd_file = 0;
1109
    NODE *cref = NEW_CREF(klass);
1110
    cref->nd_omod = Qnil;
1111 1111
    cref->nd_visi = noex;
1112 1112

  
1113 1113
    if (blockptr) {
......
1116 1116
    else if (cfp) {
1117 1117
	cref->nd_next = vm_get_cref0(cfp->iseq, cfp->lfp, cfp->dfp);
1118 1118
    }
1119
    /* TODO: why cref->nd_next is 1? */
1120
    if (cref->nd_next && cref->nd_next != (void *) 1 &&
1121
	!NIL_P(cref->nd_next->nd_omod)) {
1122
	COPY_CREF_OMOD(cref, cref->nd_next);
1123
    }
1119 1124

  
1120 1125
    return cref;
1121 1126
}
......
1123 1128
static inline VALUE
1124 1129
vm_get_cbase(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
1125 1130
{
1126
    NODE *cref = vm_get_cref(iseq, lfp, dfp);
1131
    NODE *cref = rb_vm_get_cref(iseq, lfp, dfp);
1127 1132
    VALUE klass = Qundef;
1128 1133

  
1129 1134
    while (cref) {
......
1139 1144
static inline VALUE
1140 1145
vm_get_const_base(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
1141 1146
{
1142
    NODE *cref = vm_get_cref(iseq, lfp, dfp);
1147
    NODE *cref = rb_vm_get_cref(iseq, lfp, dfp);
1143 1148
    VALUE klass = Qundef;
1144 1149

  
1145 1150
    while (cref) {
......
1167 1172
}
1168 1173

  
1169 1174
static inline VALUE
1175
vm_get_iclass(rb_control_frame_t *cfp, VALUE klass)
1176
{
1177
    if (TYPE(klass) == T_MODULE &&
1178
	FL_TEST(klass, RMODULE_IS_OVERLAYED) &&
1179
	TYPE(cfp->klass) == T_ICLASS &&
1180
	RBASIC(cfp->klass)->klass == klass) {
1181
	return cfp->klass;
1182
    }
1183
    else {
1184
	return klass;
1185
    }
1186
}
1187

  
1188
static inline VALUE
1170 1189
vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
1171 1190
		VALUE orig_klass, ID id, int is_defined)
1172 1191
{
......
1174 1193

  
1175 1194
    if (orig_klass == Qnil) {
1176 1195
	/* in current lexical scope */
1177
	const NODE *cref = vm_get_cref(iseq, th->cfp->lfp, th->cfp->dfp);
1196
	const NODE *cref = rb_vm_get_cref(iseq, th->cfp->lfp, th->cfp->dfp);
1178 1197
	const NODE *root_cref = NULL;
1179 1198
	VALUE klass = orig_klass;
1180 1199

  
......
1213 1232

  
1214 1233
	/* search self */
1215 1234
	if (root_cref && !NIL_P(root_cref->nd_clss)) {
1216
	    klass = root_cref->nd_clss;
1235
	    klass = vm_get_iclass(th->cfp, root_cref->nd_clss);
1217 1236
	}
1218 1237
	else {
1219 1238
	    klass = CLASS_OF(th->cfp->self);
......
1238 1257
}
1239 1258

  
1240 1259
static inline VALUE
1241
vm_get_cvar_base(NODE *cref)
1260
vm_get_cvar_base(NODE *cref, rb_control_frame_t *cfp)
1242 1261
{
1243 1262
    VALUE klass;
1244 1263

  
......
1252 1271
	}
1253 1272
    }
1254 1273

  
1255
    klass = cref->nd_clss;
1274
    klass = vm_get_iclass(cfp, cref->nd_clss);
1256 1275

  
1257 1276
    if (NIL_P(klass)) {
1258 1277
	rb_raise(rb_eTypeError, "no class variables available");
......
1727 1746
    return Qundef;
1728 1747
}
1729 1748

  
1749
void rb_using_module(NODE *cref, VALUE module);
1750

  
1751
static int
1752
vm_using_module_i(VALUE module, VALUE value, VALUE arg)
1753
{
1754
    NODE *cref = (NODE *) arg;
1755

  
1756
    rb_using_module(cref, module);
1757
    return ST_CONTINUE;
1758
}
1759

  
1760
static void
1761
rb_vm_using_modules(NODE *cref, VALUE klass)
1762
{
1763
    ID id_using_modules;
1764
    VALUE using_modules;
1765

  
1766
    CONST_ID(id_using_modules, "__using_modules__");
1767
    using_modules = rb_attr_get(klass, id_using_modules);
1768
    switch (TYPE(klass)) {
1769
    case T_CLASS:
1770
	if (NIL_P(using_modules)) {
1771
	    VALUE super = rb_class_real(RCLASS_SUPER(klass));
1772
	    using_modules = rb_attr_get(super, id_using_modules);
1773
	    if (!NIL_P(using_modules)) {
1774
		using_modules = rb_hash_dup(using_modules);
1775
		rb_ivar_set(klass, id_using_modules, using_modules);
1776
	    }
1777
	}
1778
	break;
1779
    case T_MODULE:
1780
	rb_using_module(cref, klass);
1781
	break;
1782
    }
1783
    if (!NIL_P(using_modules)) {
1784
	rb_hash_foreach(using_modules, vm_using_module_i,
1785
		       	(VALUE) cref);
1786
    }
1787
}
1788

  
vm_insnhelper.h
149 149
/* deal with control flow 2: method/iterator              */
150 150
/**********************************************************/
151 151

  
152
#define COPY_CREF_OMOD(c1, c2) do {  \
153
  c1->nd_omod = c2->nd_omod; \
154
  if (!NIL_P(c2->nd_omod)) { \
155
      c1->flags |= NODE_FL_CREF_OMOD_SHARED; \
156
      c2->flags |= NODE_FL_CREF_OMOD_SHARED; \
157
  } \
158
} while (0)
159

  
152 160
#define COPY_CREF(c1, c2) do {  \
153 161
  NODE *__tmp_c2 = (c2); \
162
  COPY_CREF_OMOD(c1, __tmp_c2); \
154 163
  c1->nd_clss = __tmp_c2->nd_clss; \
155 164
  c1->nd_visi = __tmp_c2->nd_visi;\
156 165
  c1->nd_next = __tmp_c2->nd_next; \
vm_method.c
4 4

  
5 5
#define CACHE_SIZE 0x800
6 6
#define CACHE_MASK 0x7ff
7
#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK)
7
#define EXPR1(c,o,m) ((((c)>>3)^((o)>>3)^(m))&CACHE_MASK)
8 8

  
9 9
static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me);
10 10

  
......
15 15
struct cache_entry {		/* method hash table. */
16 16
    ID mid;			/* method's id */
17 17
    VALUE klass;		/* receiver's class */
18
    VALUE omod;			/* overlay modules */
18 19
    rb_method_entry_t *me;
19 20
    VALUE defined_class;
20 21
};
......
393 394
}
394 395

  
395 396
static rb_method_entry_t*
396
search_method(VALUE klass, ID id, VALUE *defined_class_ptr)
397
search_method(VALUE klass, ID id, VALUE omod, VALUE *defined_class_ptr)
397 398
{
398 399
    st_data_t body;
400
    VALUE iclass, skipped_class = Qnil;
401

  
399 402
    if (!klass) {
400 403
	return 0;
401 404
    }
402 405

  
406
    if (!NIL_P(omod) && !NIL_P(iclass = rb_hash_lookup(omod, klass))) {
407
	klass = iclass;
408
    }
403 409
    while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) {
404 410
	klass = RCLASS_SUPER(klass);
411
	if (!NIL_P(omod) && klass != skipped_class &&
412
	    !NIL_P(iclass = rb_hash_lookup(omod, klass))) {
413
	    skipped_class = klass;
414
	    klass = iclass;
415
	}
405 416
	if (!klass) {
406 417
	    return 0;
407 418
	}
......
419 430
 * rb_method_entry() simply.
420 431
 */
421 432
rb_method_entry_t *
422
rb_method_entry_get_without_cache(VALUE klass, ID id, VALUE *defined_class_ptr)
433
rb_method_entry_get_without_cache(VALUE klass, VALUE omod, ID id, VALUE *defined_class_ptr)
423 434
{
424
    VALUE defined_class;
435
    VALUE iclass, defined_class;
425 436
    rb_method_entry_t *me;
426 437

  
427
    me = search_method(klass, id, &defined_class);
438
    me = search_method(klass, id, omod, &defined_class);
428 439

  
429 440
    if (ruby_running) {
430 441
	struct cache_entry *ent;
431
	ent = cache + EXPR1(klass, id);
442
	ent = cache + EXPR1(klass, omod, id);
432 443
	ent->klass = klass;
444
	ent->omod = omod;
433 445
	ent->defined_class = defined_class;
434 446

  
435 447
	if (UNDEFINED_METHOD_ENTRY_P(me)) {
......
449 461
}
450 462

  
451 463
rb_method_entry_t *
452
rb_method_entry(VALUE klass, ID id, VALUE *defined_class_ptr)
464
rb_method_entry_get_with_omod(VALUE omod, VALUE klass, ID id,
465
			      VALUE *defined_class_ptr)
453 466
{
454 467
    struct cache_entry *ent;
455 468

  
456
    ent = cache + EXPR1(klass, id);
457
    if (ent->mid == id && ent->klass == klass) {
469
    ent = cache + EXPR1(klass, omod, id);
470
    if (ent->mid == id && ent->klass == klass && ent->omod == omod) {
458 471
	if (defined_class_ptr)
459 472
	    *defined_class_ptr = ent->defined_class;
460 473
	return ent->me;
461 474
    }
462 475

  
463
    return rb_method_entry_get_without_cache(klass, id, defined_class_ptr);
476
    return rb_method_entry_get_without_cache(klass, omod, id,
477
					     defined_class_ptr);
478
}
479

  
480
rb_method_entry_t *
481
rb_method_entry(VALUE klass, ID id, VALUE *defined_class_ptr)
482
{
483
    struct cache_entry *ent;
484
    NODE *cref = rb_vm_cref();
485
    VALUE omod = Qnil;
486

  
487
    if (cref && !NIL_P(cref->nd_omod)) {
488
	omod = cref->nd_omod;
489
    }
490
    return rb_method_entry_get_with_omod(omod, klass, id, defined_class_ptr);
464 491
}
465 492

  
466 493
static void
......
552 579
	rb_secure(4);
553 580
    }
554 581

  
555
    me = search_method(klass, name, &defined_class);
582
    me = search_method(klass, name, Qnil, &defined_class);
556 583
    if (!me && TYPE(klass) == T_MODULE) {
557
	me = search_method(rb_cObject, name, &defined_class);
584
	me = search_method(rb_cObject, name, Qnil, &defined_class);
558 585
    }
559 586

  
560 587
    if (UNDEFINED_METHOD_ENTRY_P(me)) {
......
640 667
rb_undef(VALUE klass, ID id)
641 668
{
642 669
    rb_method_entry_t *me;
670
    NODE *cref = rb_vm_cref();
671
    VALUE omod = Qnil;
643 672

  
644 673
    if (NIL_P(klass)) {
645 674
	rb_raise(rb_eTypeError, "no class to undef method");
......
655 684
	rb_warn("undefining `%s' may cause serious problems", rb_id2name(id));
656 685
    }
657 686

  
658
    me = search_method(klass, id, 0);
687
    if (cref && !NIL_P(cref->nd_omod)) {
688
	omod = cref->nd_omod;
689
    }
690
    me = search_method(klass, id, omod, 0);
659 691

  
660 692
    if (UNDEFINED_METHOD_ENTRY_P(me)) {
661 693
	const char *s0 = " class";
......
678 710
		      rb_id2name(id), s0, rb_class2name(c));
679 711
    }
680 712

  
713
    if (!RTEST(rb_class_inherited_p(klass, me->klass))) {
714
	VALUE mod = rb_module_new();
715
	rb_overlay_module(cref, klass, mod);
716
	klass = mod;
717
    }
681 718
    rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, NOEX_PUBLIC);
682 719

  
683 720
    CALL_METHOD_HOOK(klass, undefined, id);
......
939 976
    }
940 977

  
941 978
  again:
942
    orig_me = search_method(klass, def, 0);
979
    orig_me = search_method(klass, def, Qnil, 0);
943 980

  
944 981
    if (UNDEFINED_METHOD_ENTRY_P(orig_me)) {
945 982
	if ((TYPE(klass) != T_MODULE) ||
946
	    (orig_me = search_method(rb_cObject, def, 0),
983
	    (orig_me = search_method(rb_cObject, def, Qnil, 0),
947 984
				     UNDEFINED_METHOD_ENTRY_P(orig_me))) {
948 985
	    rb_print_undef(klass, def, 0);
949 986
	}
......
1205 1242

  
1206 1243
	id = rb_to_id(argv[i]);
1207 1244
	for (;;) {
1208
	    me = search_method(m, id, 0);
1245
	    me = search_method(m, id, Qnil, 0);
1209 1246
	    if (me == 0) {
1210
		me = search_method(rb_cObject, id, 0);
1247
		me = search_method(rb_cObject, id, Qnil, 0);
1211 1248
	    }
1212 1249
	    if (UNDEFINED_METHOD_ENTRY_P(me)) {
1213 1250
		rb_print_undef(module, id, 0);
......
1313 1350
}
1314 1351

  
1315 1352
void
1353
rb_redefine_opt_method(VALUE klass, ID mid)
1354
{
1355
    st_data_t key, data;
1356
    rb_method_entry_t *me = 0;
1357

  
1358
    if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) ||
1359
	!(me = (rb_method_entry_t *)data) ||
1360
	(!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) {
1361
	return;
1362
    }
1363
    rb_vm_check_redefinition_opt_method(me);
1364
}
1365

  
1366
void
1316 1367
Init_eval_method(void)
1317 1368
{
1318 1369
#undef rb_intern