refinement-r29837-20101124.diff
| b/bootstraptest/test_method.rb | ||
|---|---|---|
| 287 | 287 |
assert_equal '1', %q( class C |
| 288 | 288 |
def m |
| 289 | 289 |
def mm() 1 end |
| 290 |
mm |
|
| 290 | 291 |
end |
| 291 | 292 |
end |
| 292 |
C.new.m |
|
| 293 |
C.new.mm ) |
|
| 293 |
C.new.m ) |
|
| 294 | 294 |
assert_equal '1', %q( class C |
| 295 | 295 |
def m |
| 296 | 296 |
def mm() 1 end |
| 297 |
mm |
|
| 297 | 298 |
end |
| 298 | 299 |
end |
| 299 |
instance_eval "C.new.m; C.new.mm" )
|
|
| 300 |
instance_eval "C.new.m" ) |
|
| 300 | 301 | |
| 301 | 302 |
# method_missing |
| 302 | 303 |
assert_equal ':m', %q( class C |
| b/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: |
| ... | ... | |
| 1387 | 1387 |
int |
| 1388 | 1388 |
rb_obj_basic_to_s_p(VALUE obj) |
| 1389 | 1389 |
{
|
| 1390 |
const rb_method_entry_t *me = rb_method_entry(CLASS_OF(obj), rb_intern("to_s"));
|
|
| 1390 |
const rb_method_entry_t *me = rb_method_entry(CLASS_OF(obj), rb_intern("to_s"), 0);
|
|
| 1391 | 1391 |
if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC && |
| 1392 | 1392 |
me->def->body.cfunc.func == rb_any_to_s) |
| 1393 | 1393 |
return 1; |
| b/compile.c | ||
|---|---|---|
| 4575 | 4575 |
ADD_INSN1(ret, nd_line(node), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE)); |
| 4576 | 4576 |
ADD_INSN1(ret, nd_line(node), putobject, ID2SYM(node->nd_mid)); |
| 4577 | 4577 |
ADD_INSN1(ret, nd_line(node), putiseq, iseqval); |
| 4578 |
ADD_SEND (ret, nd_line(node), ID2SYM(id_core_define_method), INT2FIX(3)); |
|
| 4578 |
ADD_INSN1(ret, nd_line(node), putobject, |
|
| 4579 |
node->flags & NODE_FL_NESTED_DEF ? Qtrue : Qfalse); |
|
| 4580 |
ADD_SEND (ret, nd_line(node), ID2SYM(id_core_define_method), INT2FIX(4)); |
|
| 4579 | 4581 | |
| 4580 | 4582 |
if (poped) {
|
| 4581 | 4583 |
ADD_INSN(ret, nd_line(node), pop); |
| b/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 |
/* |
|
| 966 |
* call-seq: |
|
| 967 |
* refine(klass) { block } -> self
|
|
| 968 |
* |
|
| 969 |
* Refine <i>klass</i> in the receiver. |
|
| 970 |
*/ |
|
| 971 | ||
| 972 |
static VALUE |
|
| 973 |
rb_mod_refine(VALUE module, VALUE klass) |
|
| 974 |
{
|
|
| 975 |
NODE *cref = rb_vm_cref(); |
|
| 976 |
VALUE mod; |
|
| 977 |
ID id_overlayed_modules, id_refined_class; |
|
| 978 |
VALUE overlayed_modules, modules; |
|
| 979 | ||
| 980 |
Check_Type(klass, T_CLASS); |
|
| 981 |
CONST_ID(id_overlayed_modules, "__overlayed_modules__"); |
|
| 982 |
overlayed_modules = rb_attr_get(module, id_overlayed_modules); |
|
| 983 |
if (NIL_P(overlayed_modules)) {
|
|
| 984 |
overlayed_modules = rb_hash_new(); |
|
| 985 |
rb_funcall(overlayed_modules, rb_intern("compare_by_identity"), 0);
|
|
| 986 |
rb_ivar_set(module, id_overlayed_modules, overlayed_modules); |
|
| 987 |
} |
|
| 988 |
mod = rb_hash_aref(overlayed_modules, klass); |
|
| 989 |
if (NIL_P(mod)) {
|
|
| 990 |
mod = rb_module_new(); |
|
| 991 |
CONST_ID(id_refined_class, "__refined_class__"); |
|
| 992 |
rb_ivar_set(mod, id_refined_class, klass); |
|
| 993 |
rb_define_singleton_method(mod, "method_added", |
|
| 994 |
refinement_module_method_added, 1); |
|
| 995 |
rb_overlay_module(cref, klass, mod); |
|
| 996 |
rb_hash_aset(overlayed_modules, klass, mod); |
|
| 997 |
} |
|
| 998 |
rb_mod_module_eval(0, NULL, mod); |
|
| 999 |
return mod; |
|
| 1000 |
} |
|
| 1001 | ||
| 1002 |
void |
|
| 861 | 1003 |
rb_obj_call_init(VALUE obj, int argc, VALUE *argv) |
| 862 | 1004 |
{
|
| 863 | 1005 |
PASS_PASSED_BLOCK(); |
| ... | ... | |
| 969 | 1111 |
return rb_mod_include(argc, argv, rb_cObject); |
| 970 | 1112 |
} |
| 971 | 1113 | |
| 1114 |
/* |
|
| 1115 |
* call-seq: |
|
| 1116 |
* using(module) -> self |
|
| 1117 |
* |
|
| 1118 |
* Import class refinements from <i>module</i> into the scope where <code>use</code> is called. |
|
| 1119 |
*/ |
|
| 1120 | ||
| 1121 |
static VALUE |
|
| 1122 |
f_using(VALUE self, VALUE module) |
|
| 1123 |
{
|
|
| 1124 |
NODE *cref = rb_vm_cref(); |
|
| 1125 | ||
| 1126 |
rb_using_module(cref, module); |
|
| 1127 |
return self; |
|
| 1128 |
} |
|
| 1129 | ||
| 972 | 1130 |
VALUE rb_f_trace_var(); |
| 973 | 1131 |
VALUE rb_f_untrace_var(); |
| 974 | 1132 | |
| ... | ... | |
| 1121 | 1279 |
rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1); |
| 1122 | 1280 |
rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1); |
| 1123 | 1281 |
rb_define_private_method(rb_cModule, "include", rb_mod_include, -1); |
| 1282 |
rb_define_private_method(rb_cModule, "using", rb_mod_using, 1); |
|
| 1283 |
rb_define_private_method(rb_cModule, "refine", rb_mod_refine, 1); |
|
| 1124 | 1284 | |
| 1125 | 1285 |
rb_undef_method(rb_cClass, "module_function"); |
| 1126 | 1286 | |
| ... | ... | |
| 1136 | 1296 | |
| 1137 | 1297 |
rb_define_singleton_method(rb_vm_top_self(), "include", top_include, -1); |
| 1138 | 1298 | |
| 1299 |
rb_define_global_function("using", f_using, 1);
|
|
| 1300 | ||
| 1139 | 1301 |
rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1); |
| 1140 | 1302 | |
| 1141 | 1303 |
rb_define_global_function("trace_var", rb_f_trace_var, -1); /* in variable.c */
|
| b/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); |
| b/include/ruby/intern.h | ||
|---|---|---|
| 164 | 164 |
VALUE rb_make_metaclass(VALUE, VALUE); |
| 165 | 165 |
void rb_check_inheritable(VALUE); |
| 166 | 166 |
VALUE rb_class_inherited(VALUE, VALUE); |
| 167 |
VALUE rb_mod_opened(VALUE); |
|
| 167 | 168 |
VALUE rb_define_class_id(ID, VALUE); |
| 168 | 169 |
VALUE rb_define_class_id_under(VALUE, ID, VALUE); |
| 169 | 170 |
VALUE rb_module_new(void); |
| 170 | 171 |
VALUE rb_define_module_id(ID); |
| 171 | 172 |
VALUE rb_define_module_id_under(VALUE, ID); |
| 173 |
VALUE rb_include_class_new(VALUE, VALUE); |
|
| 172 | 174 |
VALUE rb_mod_included_modules(VALUE); |
| 173 | 175 |
VALUE rb_mod_include_p(VALUE, VALUE); |
| 174 | 176 |
VALUE rb_mod_ancestors(VALUE); |
| b/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_HAS_NESTED_METHODS FL_USER2 |
|
| 633 |
#define RMODULE_IS_OVERLAYED FL_USER3 |
|
| 632 | 634 | |
| 633 | 635 |
struct RFloat {
|
| 634 | 636 |
struct RBasic basic; |
| b/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 |
/** |
| ... | ... | |
| 792 | 792 |
break; |
| 793 | 793 |
case DEFINED_METHOD:{
|
| 794 | 794 |
VALUE klass = CLASS_OF(v); |
| 795 |
const rb_method_entry_t *me = rb_method_entry(klass, SYM2ID(obj)); |
|
| 795 |
const rb_method_entry_t *me = rb_method_entry(klass, SYM2ID(obj), 0);
|
|
| 796 | 796 | |
| 797 | 797 |
if (me) {
|
| 798 | 798 |
if (!(me->flag & NOEX_PRIVATE)) {
|
| ... | ... | |
| 964 | 964 | |
| 965 | 965 |
/* enter scope */ |
| 966 | 966 |
vm_push_frame(th, class_iseq, |
| 967 |
VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_BLOCK_PTR(), |
|
| 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(); |
| ... | ... | |
| 996 | 997 |
(VALUE val) // inc += - (int)(op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0)); |
| 997 | 998 |
{
|
| 998 | 999 |
const rb_method_entry_t *me; |
| 999 |
VALUE recv, klass; |
|
| 1000 |
VALUE recv, klass, defined_class;
|
|
| 1000 | 1001 |
rb_block_t *blockptr = 0; |
| 1001 | 1002 |
VALUE flag = op_flag; |
| 1002 | 1003 |
int num = caller_setup_args(th, GET_CFP(), flag, (int)op_argc, |
| ... | ... | |
| 1006 | 1007 |
/* get receiver */ |
| 1007 | 1008 |
recv = (flag & VM_CALL_FCALL_BIT) ? GET_SELF() : TOPN(num); |
| 1008 | 1009 |
klass = CLASS_OF(recv); |
| 1009 |
me = vm_method_search(id, klass, ic); |
|
| 1010 |
CALL_METHOD(num, blockptr, flag, id, me, recv); |
|
| 1010 |
me = vm_method_search(id, klass, ic, &defined_class);
|
|
| 1011 |
CALL_METHOD(num, blockptr, flag, id, me, recv, defined_class);
|
|
| 1011 | 1012 |
} |
| 1012 | 1013 | |
| 1013 | 1014 |
/** |
| ... | ... | |
| 1030 | 1031 |
VALUE recv, klass; |
| 1031 | 1032 |
ID id; |
| 1032 | 1033 |
const rb_method_entry_t *me; |
| 1034 |
rb_iseq_t *ip; |
|
| 1033 | 1035 | |
| 1034 | 1036 |
flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT; |
| 1035 | 1037 | |
| 1036 | 1038 |
recv = GET_SELF(); |
| 1037 | 1039 |
vm_search_superclass(GET_CFP(), GET_ISEQ(), recv, TOPN(num), &id, &klass); |
| 1038 | 1040 | |
| 1039 |
/* temporary measure for [Bug #2402] [Bug #2502] [Bug #3136] */ |
|
| 1040 |
if (!rb_obj_is_kind_of(recv, klass)) {
|
|
| 1041 |
rb_raise(rb_eNotImpError, "super from singleton method that is defined to multiple classes is not supported; this will be fixed in 1.9.3 or later"); |
|
| 1041 |
ip = GET_ISEQ(); |
|
| 1042 |
while (ip && !ip->klass) {
|
|
| 1043 |
ip = ip->parent_iseq; |
|
| 1044 |
} |
|
| 1045 |
me = rb_method_entry(klass, id, &klass); |
|
| 1046 |
if (me && me->def->type == VM_METHOD_TYPE_ISEQ && |
|
| 1047 |
me->def->body.iseq == ip) {
|
|
| 1048 |
klass = RCLASS_SUPER(klass); |
|
| 1049 |
me = rb_method_entry_get_with_omod(Qnil, klass, id, &klass); |
|
| 1042 | 1050 |
} |
| 1043 | 1051 | |
| 1044 |
me = rb_method_entry(klass, id); |
|
| 1045 | ||
| 1046 |
CALL_METHOD(num, blockptr, flag, id, me, recv); |
|
| 1052 |
CALL_METHOD(num, blockptr, flag, id, me, recv, klass); |
|
| 1047 | 1053 |
} |
| 1048 | 1054 | |
| 1049 | 1055 |
/** |
| ... | ... | |
| 1668 | 1674 |
(VALUE val) |
| 1669 | 1675 |
{
|
| 1670 | 1676 |
extern VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2); |
| 1671 |
const rb_method_entry_t *me = vm_method_search(idNeq, CLASS_OF(recv), ic); |
|
| 1677 |
const rb_method_entry_t *me = vm_method_search(idNeq, CLASS_OF(recv), ic, 0);
|
|
| 1672 | 1678 |
val = Qundef; |
| 1673 | 1679 | |
| 1674 | 1680 |
if (check_cfunc(me, rb_obj_not_equal)) {
|
| ... | ... | |
| 2069 | 2075 |
(VALUE val) |
| 2070 | 2076 |
{
|
| 2071 | 2077 |
extern VALUE rb_obj_not(VALUE obj); |
| 2072 |
const rb_method_entry_t *me = vm_method_search(idNot, CLASS_OF(recv), ic); |
|
| 2078 |
const rb_method_entry_t *me = vm_method_search(idNot, CLASS_OF(recv), ic, 0);
|
|
| 2073 | 2079 | |
| 2074 | 2080 |
if (check_cfunc(me, rb_obj_not)) {
|
| 2075 | 2081 |
val = RTEST(recv) ? Qfalse : Qtrue; |
| b/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 |
} |
| b/lex.c.blt | ||
|---|---|---|
| 1 |
/* C code produced by gperf version 3.0.4 */
|
|
| 2 |
/* Command-line: gperf -C -p -j1 -i 1 -g -o -t -N rb_reserved_word -k'1,3,$' defs/keywords */ |
|
| 1 |
/* C code produced by gperf version 3.0.3 */
|
|
| 2 |
/* Command-line: gperf -C -p -j1 -i 1 -g -o -t -N rb_reserved_word -k'1,3,$' ../defs/keywords */
|
|
| 3 | 3 | |
| 4 | 4 |
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
|
| 5 | 5 |
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
|
| ... | ... | |
| 28 | 28 |
error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>." |
| 29 | 29 |
#endif |
| 30 | 30 | |
| 31 |
#line 1 "defs/keywords" |
|
| 31 |
#line 1 "../defs/keywords"
|
|
| 32 | 32 | |
| 33 | 33 |
struct kwtable {const char *name; int id[2]; enum lex_state_e state;};
|
| 34 | 34 |
const struct kwtable *rb_reserved_word(const char *, unsigned int); |
| 35 | 35 |
#ifndef RIPPER |
| 36 | 36 |
static const struct kwtable *reserved_word(const char *, unsigned int); |
| 37 | 37 |
#define rb_reserved_word(str, len) reserved_word(str, len) |
| 38 |
#line 9 "defs/keywords" |
|
| 38 |
#line 9 "../defs/keywords"
|
|
| 39 | 39 |
struct kwtable; |
| 40 | 40 | |
| 41 | 41 |
#define TOTAL_KEYWORDS 41 |
| ... | ... | |
| 103 | 103 | |
| 104 | 104 |
#ifdef __GNUC__ |
| 105 | 105 |
__inline |
| 106 |
#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
|
|
| 106 |
#ifdef __GNUC_STDC_INLINE__
|
|
| 107 | 107 |
__attribute__ ((__gnu_inline__)) |
| 108 | 108 |
#endif |
| 109 | 109 |
#endif |
| ... | ... | |
| 115 | 115 |
static const struct kwtable wordlist[] = |
| 116 | 116 |
{
|
| 117 | 117 |
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
| 118 |
#line 19 "defs/keywords" |
|
| 118 |
#line 19 "../defs/keywords"
|
|
| 119 | 119 |
{"break", {keyword_break, keyword_break}, EXPR_MID},
|
| 120 |
#line 25 "defs/keywords" |
|
| 120 |
#line 25 "../defs/keywords"
|
|
| 121 | 121 |
{"else", {keyword_else, keyword_else}, EXPR_BEG},
|
| 122 |
#line 35 "defs/keywords" |
|
| 122 |
#line 35 "../defs/keywords"
|
|
| 123 | 123 |
{"nil", {keyword_nil, keyword_nil}, EXPR_END},
|
| 124 |
#line 28 "defs/keywords" |
|
| 124 |
#line 28 "../defs/keywords"
|
|
| 125 | 125 |
{"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG},
|
| 126 |
#line 27 "defs/keywords" |
|
| 126 |
#line 27 "../defs/keywords"
|
|
| 127 | 127 |
{"end", {keyword_end, keyword_end}, EXPR_END},
|
| 128 |
#line 44 "defs/keywords" |
|
| 128 |
#line 44 "../defs/keywords"
|
|
| 129 | 129 |
{"then", {keyword_then, keyword_then}, EXPR_BEG},
|
| 130 |
#line 36 "defs/keywords" |
|
| 130 |
#line 36 "../defs/keywords"
|
|
| 131 | 131 |
{"not", {keyword_not, keyword_not}, EXPR_ARG},
|
| 132 |
#line 29 "defs/keywords" |
|
| 132 |
#line 29 "../defs/keywords"
|
|
| 133 | 133 |
{"false", {keyword_false, keyword_false}, EXPR_END},
|
| 134 |
#line 42 "defs/keywords" |
|
| 134 |
#line 42 "../defs/keywords"
|
|
| 135 | 135 |
{"self", {keyword_self, keyword_self}, EXPR_END},
|
| 136 |
#line 26 "defs/keywords" |
|
| 136 |
#line 26 "../defs/keywords"
|
|
| 137 | 137 |
{"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE},
|
| 138 |
#line 39 "defs/keywords" |
|
| 138 |
#line 39 "../defs/keywords"
|
|
| 139 | 139 |
{"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID},
|
| 140 |
#line 45 "defs/keywords" |
|
| 140 |
#line 45 "../defs/keywords"
|
|
| 141 | 141 |
{"true", {keyword_true, keyword_true}, EXPR_END},
|
| 142 |
#line 48 "defs/keywords" |
|
| 142 |
#line 48 "../defs/keywords"
|
|
| 143 | 143 |
{"until", {keyword_until, modifier_until}, EXPR_VALUE},
|
| 144 |
#line 47 "defs/keywords" |
|
| 144 |
#line 47 "../defs/keywords"
|
|
| 145 | 145 |
{"unless", {keyword_unless, modifier_unless}, EXPR_VALUE},
|
| 146 |
#line 41 "defs/keywords" |
|
| 146 |
#line 41 "../defs/keywords"
|
|
| 147 | 147 |
{"return", {keyword_return, keyword_return}, EXPR_MID},
|
| 148 |
#line 22 "defs/keywords" |
|
| 148 |
#line 22 "../defs/keywords"
|
|
| 149 | 149 |
{"def", {keyword_def, keyword_def}, EXPR_FNAME},
|
| 150 |
#line 17 "defs/keywords" |
|
| 150 |
#line 17 "../defs/keywords"
|
|
| 151 | 151 |
{"and", {keyword_and, keyword_and}, EXPR_VALUE},
|
| 152 |
#line 24 "defs/keywords" |
|
| 152 |
#line 24 "../defs/keywords"
|
|
| 153 | 153 |
{"do", {keyword_do, keyword_do}, EXPR_BEG},
|
| 154 |
#line 51 "defs/keywords" |
|
| 154 |
#line 51 "../defs/keywords"
|
|
| 155 | 155 |
{"yield", {keyword_yield, keyword_yield}, EXPR_ARG},
|
| 156 |
#line 30 "defs/keywords" |
|
| 156 |
#line 30 "../defs/keywords"
|
|
| 157 | 157 |
{"for", {keyword_for, keyword_for}, EXPR_VALUE},
|
| 158 |
#line 46 "defs/keywords" |
|
| 158 |
#line 46 "../defs/keywords"
|
|
| 159 | 159 |
{"undef", {keyword_undef, keyword_undef}, EXPR_FNAME},
|
| 160 |
#line 37 "defs/keywords" |
|
| 160 |
#line 37 "../defs/keywords"
|
|
| 161 | 161 |
{"or", {keyword_or, keyword_or}, EXPR_VALUE},
|
| 162 |
#line 32 "defs/keywords" |
|
| 162 |
#line 32 "../defs/keywords"
|
|
| 163 | 163 |
{"in", {keyword_in, keyword_in}, EXPR_VALUE},
|
| 164 |
#line 49 "defs/keywords" |
|
| 164 |
#line 49 "../defs/keywords"
|
|
| 165 | 165 |
{"when", {keyword_when, keyword_when}, EXPR_VALUE},
|
| 166 |
#line 40 "defs/keywords" |
|
| 166 |
#line 40 "../defs/keywords"
|
|
| 167 | 167 |
{"retry", {keyword_retry, keyword_retry}, EXPR_END},
|
| 168 |
#line 31 "defs/keywords" |
|
| 168 |
#line 31 "../defs/keywords"
|
|
| 169 | 169 |
{"if", {keyword_if, modifier_if}, EXPR_VALUE},
|
| 170 |
#line 20 "defs/keywords" |
|
| 170 |
#line 20 "../defs/keywords"
|
|
| 171 | 171 |
{"case", {keyword_case, keyword_case}, EXPR_VALUE},
|
| 172 |
#line 38 "defs/keywords" |
|
| 172 |
#line 38 "../defs/keywords"
|
|
| 173 | 173 |
{"redo", {keyword_redo, keyword_redo}, EXPR_END},
|
| 174 |
#line 34 "defs/keywords" |
|
| 174 |
#line 34 "../defs/keywords"
|
|
| 175 | 175 |
{"next", {keyword_next, keyword_next}, EXPR_MID},
|
| 176 |
#line 43 "defs/keywords" |
|
| 176 |
#line 43 "../defs/keywords"
|
|
| 177 | 177 |
{"super", {keyword_super, keyword_super}, EXPR_ARG},
|
| 178 |
#line 33 "defs/keywords" |
|
| 178 |
#line 33 "../defs/keywords"
|
|
| 179 | 179 |
{"module", {keyword_module, keyword_module}, EXPR_VALUE},
|
| 180 |
#line 18 "defs/keywords" |
|
| 180 |
#line 18 "../defs/keywords"
|
|
| 181 | 181 |
{"begin", {keyword_begin, keyword_begin}, EXPR_BEG},
|
| 182 |
#line 12 "defs/keywords" |
|
| 182 |
#line 12 "../defs/keywords"
|
|
| 183 | 183 |
{"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END},
|
| 184 |
#line 13 "defs/keywords" |
|
| 184 |
#line 13 "../defs/keywords"
|
|
| 185 | 185 |
{"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END},
|
| 186 |
#line 11 "defs/keywords" |
|
| 186 |
#line 11 "../defs/keywords"
|
|
| 187 | 187 |
{"__ENCODING__", {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END},
|
| 188 |
#line 15 "defs/keywords" |
|
| 188 |
#line 15 "../defs/keywords"
|
|
| 189 | 189 |
{"END", {keyword_END, keyword_END}, EXPR_END},
|
| 190 |
#line 16 "defs/keywords" |
|
| 190 |
#line 16 "../defs/keywords"
|
|
| 191 | 191 |
{"alias", {keyword_alias, keyword_alias}, EXPR_FNAME},
|
| 192 |
#line 14 "defs/keywords" |
|
| 192 |
#line 14 "../defs/keywords"
|
|
| 193 | 193 |
{"BEGIN", {keyword_BEGIN, keyword_BEGIN}, EXPR_END},
|
| 194 |
#line 23 "defs/keywords" |
|
| 194 |
#line 23 "../defs/keywords"
|
|
| 195 | 195 |
{"defined?", {keyword_defined, keyword_defined}, EXPR_ARG},
|
| 196 |
#line 21 "defs/keywords" |
|
| 196 |
#line 21 "../defs/keywords"
|
|
| 197 | 197 |
{"class", {keyword_class, keyword_class}, EXPR_CLASS},
|
| 198 | 198 |
{""}, {""},
|
| 199 |
#line 50 "defs/keywords" |
|
| 199 |
#line 50 "../defs/keywords"
|
|
| 200 | 200 |
{"while", {keyword_while, modifier_while}, EXPR_VALUE}
|
| 201 | 201 |
}; |
| 202 | 202 | |
| ... | ... | |
| 214 | 214 |
} |
| 215 | 215 |
return 0; |
| 216 | 216 |
} |
| 217 |
#line 52 "defs/keywords" |
|
| 217 |
#line 52 "../defs/keywords"
|
|
| 218 | 218 | |
| 219 | 219 |
#endif |
| b/method.h | ||
|---|---|---|
| 89 | 89 | |
| 90 | 90 |
void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex); |
| 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 |
rb_method_entry_t *rb_method_entry(VALUE klass, ID id); |
|
| 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); |
|
| 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); |
| b/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_NESTED_DEF, 7:NODE_FL_NEWLINE */
|
|
| 264 | 269 |
#define NODE_FL_NEWLINE (((VALUE)1)<<7) |
| 270 |
#define NODE_FL_NESTED_DEF (((VALUE)1)<<6) |
|
| 265 | 271 |
#define NODE_FL_CREF_PUSHED_BY_EVAL NODE_FL_NEWLINE |
| 272 |
#define NODE_FL_CREF_OMOD_SHARED NODE_FL_NESTED_DEF |
|
| 266 | 273 | |
| 267 | 274 |
#define NODE_TYPESHIFT 8 |
| 268 | 275 |
#define NODE_TYPEMASK (((VALUE)0x7f)<<NODE_TYPESHIFT) |
| ... | ... | |
| 277 | 284 |
#define nd_set_line(n,l) \ |
| 278 | 285 |
RNODE(n)->flags=((RNODE(n)->flags&~(-1<<NODE_LSHIFT))|(((l)&NODE_LMASK)<<NODE_LSHIFT)) |
| 279 | 286 | |
| 287 |
#define nd_file u0.file |
|
| 288 |
#define nd_omod u0.value |
|
| 289 | ||
| 280 | 290 |
#define nd_head u1.node |
| 281 | 291 |
#define nd_alen u2.argc |
| 282 | 292 |
#define nd_next u3.node |
| ... | ... | |
| 433 | 443 |
#define NEW_MODULE(n,b) NEW_NODE(NODE_MODULE,n,NEW_SCOPE(0,b),0) |
| 434 | 444 |
#define NEW_COLON2(c,i) NEW_NODE(NODE_COLON2,c,i,0) |
| 435 | 445 |
#define NEW_COLON3(i) NEW_NODE(NODE_COLON3,0,i,0) |
| 446 |
#define NEW_CREF(a) NEW_NODE(NODE_CREF,a,0,0) |
|
| 436 | 447 |
#define NEW_DOT2(b,e) NEW_NODE(NODE_DOT2,b,e,0) |
| 437 | 448 |
#define NEW_DOT3(b,e) NEW_NODE(NODE_DOT3,b,e,0) |
| 438 | 449 |
#define NEW_SELF() NEW_NODE(NODE_SELF,0,0,0) |
| b/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); |
| b/parse.y | ||
|---|---|---|
| 2967 | 2967 |
reduce_nodes(&body); |
| 2968 | 2968 |
$$ = NEW_DEFN($2, $4, body, NOEX_PRIVATE); |
| 2969 | 2969 |
nd_set_line($$, $<num>1); |
| 2970 |
if (in_def > 1 || in_single > 0) |
|
| 2971 |
$$->flags |= NODE_FL_NESTED_DEF; |
|
| 2970 | 2972 |
/*% |
| 2971 | 2973 |
$$ = dispatch3(def, $2, $4, $5); |
| 2972 | 2974 |
%*/ |
| b/proc.c | ||
|---|---|---|
| 15 | 15 |
struct METHOD {
|
| 16 | 16 |
VALUE recv; |
| 17 | 17 |
VALUE rclass; |
| 18 |
VALUE defined_class; |
|
| 18 | 19 |
ID id; |
| 19 | 20 |
rb_method_entry_t me; |
| 20 | 21 |
}; |
| ... | ... | |
| 861 | 862 |
bm_mark(void *ptr) |
| 862 | 863 |
{
|
| 863 | 864 |
struct METHOD *data = ptr; |
| 865 |
rb_gc_mark(data->defined_class); |
|
| 864 | 866 |
rb_gc_mark(data->rclass); |
| 865 | 867 |
rb_gc_mark(data->recv); |
| 866 | 868 |
rb_mark_method_entry(&data->me); |
| ... | ... | |
| 903 | 905 |
mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope) |
| 904 | 906 |
{
|
| 905 | 907 |
VALUE method; |
| 906 |
VALUE rclass = klass; |
|
| 908 |
VALUE rclass = klass, defined_class;
|
|
| 907 | 909 |
ID rid = id; |
| 908 | 910 |
struct METHOD *data; |
| 909 | 911 |
rb_method_entry_t *me, meb; |
| ... | ... | |
| 911 | 913 |
rb_method_flag_t flag = NOEX_UNDEF; |
| 912 | 914 | |
| 913 | 915 |
again: |
| 914 |
me = rb_method_entry(klass, id); |
|
| 916 |
me = rb_method_entry(klass, id, &defined_class);
|
|
| 915 | 917 |
if (UNDEFINED_METHOD_ENTRY_P(me)) {
|
| 916 | 918 |
ID rmiss = rb_intern("respond_to_missing?");
|
| 917 | 919 |
VALUE sym = ID2SYM(id); |
| ... | ... | |
| 953 | 955 |
} |
| 954 | 956 |
} |
| 955 | 957 |
if (def && def->type == VM_METHOD_TYPE_ZSUPER) {
|
| 956 |
klass = RCLASS_SUPER(me->klass);
|
|
| 958 |
klass = RCLASS_SUPER(defined_class);
|
|
| 957 | 959 |
id = def->original_id; |
| 958 | 960 |
goto again; |
| 959 | 961 |
} |
| 960 | 962 | |
| 961 |
klass = me->klass;
|
|
| 963 |
klass = defined_class;
|
|
| 962 | 964 | |
| 963 | 965 |
while (rclass != klass && |
| 964 | 966 |
(FL_TEST(rclass, FL_SINGLETON) || TYPE(rclass) == T_ICLASS)) {
|
| ... | ... | |
| 974 | 976 | |
| 975 | 977 |
data->recv = obj; |
| 976 | 978 |
data->rclass = rclass; |
| 979 |
data->defined_class = defined_class; |
|
| 977 | 980 |
data->id = rid; |
| 978 | 981 |
data->me = *me; |
| 979 | 982 |
if (def) def->alias_count++; |
| ... | ... | |
| 1085 | 1088 |
data->me = orig->me; |
| 1086 | 1089 |
if (orig->me.def) orig->me.def->alias_count++; |
| 1087 | 1090 |
data->rclass = orig->rclass; |
| 1091 |
data->defined_class = orig->defined_class; |
|
| 1088 | 1092 |
OBJ_INFECT(method, obj); |
| 1089 | 1093 | |
| 1090 | 1094 |
return method; |
| ... | ... | |
| 1421 | 1425 |
if ((state = EXEC_TAG()) == 0) {
|
| 1422 | 1426 |
rb_thread_t *th = GET_THREAD(); |
| 1423 | 1427 |
VALUE rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, const VALUE *argv, |
| 1424 |
const rb_method_entry_t *me); |
|
| 1428 |
const rb_method_entry_t *me, VALUE defined_class);
|
|
| 1425 | 1429 | |
| 1426 | 1430 |
PASS_PASSED_BLOCK_TH(th); |
| 1427 |
result = rb_vm_call(th, data->recv, data->id, argc, argv, &data->me); |
|
| 1431 |
result = rb_vm_call(th, data->recv, data->id, argc, argv, &data->me, data->defined_class);
|
|
| 1428 | 1432 |
} |
| 1429 | 1433 |
POP_TAG(); |
| 1430 | 1434 |
if (safe >= 0) |
| ... | ... | |
| 1648 | 1652 |
int |
| 1649 | 1653 |
rb_mod_method_arity(VALUE mod, ID id) |
| 1650 | 1654 |
{
|
| 1651 |
rb_method_entry_t *me = rb_method_entry(mod, id); |
|
| 1655 |
rb_method_entry_t *me = rb_method_entry(mod, id, 0);
|
|
| 1652 | 1656 |
return rb_method_entry_arity(me); |
| 1653 | 1657 |
} |
| 1654 | 1658 | |
| b/test/rdoc/test_rdoc_text.rb | ||
|---|---|---|
| 62 | 62 |
assert_equal expected, flush_left(text) |
| 63 | 63 |
end |
| 64 | 64 | |
| 65 |
def formatter() RDoc::Markup::ToHtml.new end |
|
| 65 | 66 |
def test_markup |
| 66 |
def formatter() RDoc::Markup::ToHtml.new end |
|
| 67 | 67 | |
| 68 | 68 |
assert_equal "<p>\nhi\n</p>\n", markup('hi')
|
| 69 | 69 |
end |
| b/test/ruby/test_nested_method.rb | ||
|---|---|---|
| 1 |
require 'test/unit' |
|
| 2 | ||
| 3 |
class TestNestedMethod < Test::Unit::TestCase |
|
| 4 |
def call_nested_method |
|
| 5 |
def foo |
|
| 6 |
return "foo" |
|
| 7 |
end |
|
| 8 | ||
| 9 |
return foo |
|
| 10 |
end |
|
| 11 | ||
| 12 |
def test_nested_method |
|
| 13 |
assert_equal("foo", call_nested_method)
|
|
| 14 |
assert_raise(NoMethodError) { foo() }
|
|
| 15 |
end |
|
| 16 | ||
| 17 |
def test_doubly_nested_method |
|
| 18 |
def call_doubly_nested_method |
|
| 19 |
def foo |
|
| 20 |
return "foo" |
|
| 21 |
end |
|
| 22 | ||
| 23 |
return foo |
|
| 24 |
end |
|
| 25 | ||
| 26 |
assert_equal("foo", call_doubly_nested_method)
|
|
| 27 |
assert_raise(NoMethodError) { foo() }
|
|
| 28 |
end |
|
| 29 |
end |
|
| b/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 |
end |
|
| b/vm.c | ||
|---|---|---|
| 70 | 70 |
rb_vm_set_finish_env(rb_thread_t * th) |
| 71 | 71 |
{
|
| 72 | 72 |
vm_push_frame(th, 0, VM_FRAME_MAGIC_FINISH, |
| 73 |
Qnil, th->cfp->lfp[0], 0, |
|
| 73 |
Qnil, Qnil, th->cfp->lfp[0], 0,
|
|
| 74 | 74 |
th->cfp->sp, 0, 1); |
| 75 | 75 |
th->cfp->pc = (VALUE *)&finish_insn_seq[0]; |
| 76 | 76 |
return Qtrue; |
| ... | ... | |
| 90 | 90 |
rb_vm_set_finish_env(th); |
| 91 | 91 | |
| 92 | 92 |
vm_push_frame(th, iseq, VM_FRAME_MAGIC_TOP, |
| 93 |
th->top_self, 0, iseq->iseq_encoded, |
|
| 93 |
th->top_self, rb_cObject, 0, iseq->iseq_encoded,
|
|
| 94 | 94 |
th->cfp->sp, 0, iseq->local_size); |
| 95 | 95 | |
| 96 | 96 |
CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max); |
| ... | ... | |
| 105 | 105 | |
| 106 | 106 |
/* for return */ |
| 107 | 107 |
rb_vm_set_finish_env(th); |
| 108 |
vm_push_frame(th, iseq, VM_FRAME_MAGIC_EVAL, block->self, |
|
| 108 |
vm_push_frame(th, iseq, VM_FRAME_MAGIC_EVAL, block->self, block->klass,
|
|
| 109 | 109 |
GC_GUARDED_PTR(block->dfp), iseq->iseq_encoded, |
| 110 | 110 |
th->cfp->sp, block->lfp, iseq->local_size); |
| 111 | 111 | |
| ... | ... | |
| 490 | 490 |
GetProcPtr(procval, proc); |
| 491 | 491 |
proc->blockprocval = blockprocval; |
| 492 | 492 |
proc->block.self = block->self; |
| 493 |
proc->block.klass = block->klass; |
|
| 493 | 494 |
proc->block.lfp = block->lfp; |
| 494 | 495 |
proc->block.dfp = block->dfp; |
| 495 | 496 |
proc->block.iseq = block->iseq; |
| ... | ... | |
| 539 | 540 |
type == VM_FRAME_MAGIC_LAMBDA); |
| 540 | 541 | |
| 541 | 542 |
ncfp = vm_push_frame(th, iseq, type, |
| 542 |
self, GC_GUARDED_PTR(block->dfp), |
|
| 543 |
self, th->passed_defined_class, |
|
| 544 |
GC_GUARDED_PTR(block->dfp), |
|
| 543 | 545 |
iseq->iseq_encoded + opt_pc, cfp->sp + arg_size, block->lfp, |
| 544 | 546 |
iseq->local_size - arg_size); |
| 547 |
th->passed_defined_class = 0; |
|
| 545 | 548 |
ncfp->me = th->passed_me; |
| 546 | 549 |
th->passed_me = 0; |
| 547 | 550 |
th->passed_block = blockptr; |
| ... | ... | |
| 816 | 819 |
{
|
| 817 | 820 |
rb_thread_t *th = GET_THREAD(); |
| 818 | 821 |
rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); |
| 819 |
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); |
|
| 820 | 824 |
} |
| 821 | 825 | |
| 822 | 826 |
#if 0 |
| ... | ... | |
| 1317 | 1321 |
/* push block frame */ |
| 1318 | 1322 |
cfp->sp[0] = err; |
| 1319 | 1323 |
vm_push_frame(th, catch_iseq, VM_FRAME_MAGIC_BLOCK, |
| 1320 |
cfp->self, (VALUE)cfp->dfp, catch_iseq->iseq_encoded, |
|
| 1324 |
cfp->self, cfp->klass, |
|
| 1325 |
(VALUE)cfp->dfp, catch_iseq->iseq_encoded, |
|
| 1321 | 1326 |
cfp->sp + 1 /* push value */, cfp->lfp, catch_iseq->local_size - 1); |
| 1322 | 1327 | |
| 1323 | 1328 |
state = 0; |
| ... | ... | |
| 1455 | 1460 |
VALUE val; |
| 1456 | 1461 | |
| 1457 | 1462 |
vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP, |
| 1458 |
recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1); |
|
| 1463 |
recv, CLASS_OF(recv), (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
|
|
| 1459 | 1464 | |
| 1460 | 1465 |
val = (*func)(arg); |
| 1461 | 1466 | |
| ... | ... | |
| 1667 | 1672 |
RUBY_MARK_UNLESS_NULL(th->root_fiber); |
| 1668 | 1673 |
RUBY_MARK_UNLESS_NULL(th->stat_insn_usage); |
| 1669 | 1674 |
RUBY_MARK_UNLESS_NULL(th->last_status); |
| 1675 |
RUBY_MARK_UNLESS_NULL(th->passed_defined_class); |
|
| 1670 | 1676 | |
| 1671 | 1677 |
RUBY_MARK_UNLESS_NULL(th->locking_mutex); |
| 1672 | 1678 | |
| ... | ... | |
| 1778 | 1784 | |
| 1779 | 1785 |
th->cfp = (void *)(th->stack + th->stack_size); |
| 1780 | 1786 | |
| 1781 |
vm_push_frame(th, 0, VM_FRAME_MAGIC_TOP, Qnil, 0, 0, |
|
| 1787 |
vm_push_frame(th, 0, VM_FRAME_MAGIC_TOP, Qnil, Qnil, 0, 0,
|
|
| 1782 | 1788 |
th->stack, 0, 1); |
| 1783 | 1789 | |
| 1784 | 1790 |
th->status = THREAD_RUNNABLE; |
| ... | ... | |
| 1815 | 1821 |
return self; |
| 1816 | 1822 |
} |
| 1817 | 1823 | |
| 1824 |
static VALUE |
|
| 1825 |
find_module_for_nested_methods(NODE *cref, VALUE klass) |
|
| 1826 |
{
|
|
| 1827 |
VALUE iclass; |
|
| 1828 | ||
| 1829 |
if (NIL_P(cref->nd_omod)) |
|
| 1830 |
return Qnil; |
|
| 1831 |
iclass = rb_hash_lookup(cref->nd_omod, klass); |
|
| 1832 |
if (NIL_P(iclass)) |
|
| 1833 |
return Qnil; |
|
| 1834 |
while (iclass) {
|
|
| 1835 |
VALUE module = RBASIC(iclass)->klass; |
|
| 1836 |
if (FL_TEST(module, RMODULE_HAS_NESTED_METHODS)) {
|
|
| 1837 |
return module; |
|
| 1838 |
} |
|
| 1839 |
iclass = RCLASS_SUPER(iclass); |
|
| 1840 |
} |
|
| 1841 |
return Qnil; |
|
| 1842 |
} |
|
| 1843 | ||
| 1818 | 1844 |
VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase); |
| 1819 | 1845 | |
| 1820 | 1846 |
static void |
| 1821 |
vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval, |
|
| 1847 |
vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval, VALUE nested,
|
|
| 1822 | 1848 |
rb_num_t is_singleton, NODE *cref) |
| 1823 | 1849 |
{
|
| 1824 | 1850 |
VALUE klass = cref->nd_clss; |
| 1851 |
VALUE target, defined_class; |
|
| 1852 |
rb_method_entry_t *me; |
|
| 1825 | 1853 |
int noex = (int)cref->nd_visi; |
| 1854 |
int is_nested = RTEST(nested); |
|
| 1826 | 1855 |
rb_iseq_t *miseq; |
| 1827 | 1856 |
GetISeqPtr(iseqval, miseq); |
| 1828 | 1857 | |
| ... | ... | |
| 1847 | 1876 |
noex = NOEX_PUBLIC; |
| 1848 | 1877 |
} |
| 1849 | 1878 | |
| 1879 |
if (is_nested && th->cfp->lfp == th->cfp->dfp) {
|
|
| 1880 |
VALUE c; |
|
| 1881 |
if (TYPE(klass) == T_MODULE) {
|
|
| 1882 |
c = rb_obj_class(th->cfp->self); |
|
| 1883 |
} |
|
| 1884 |
else {
|
|
| 1885 |
c = klass; |
|
| 1886 |
} |
|
| 1887 |
if (cref->flags & NODE_FL_CREF_OMOD_SHARED) {
|
|
| 1888 |
target = Qnil; |
|
| 1889 |
} |
|
| 1890 |
else {
|
|
| 1891 |
target = find_module_for_nested_methods(cref, c); |
|
| 1892 |
} |
|
| 1893 |
if (NIL_P(target)) {
|
|
| 1894 |
target = rb_module_new(); |
|
| 1895 |
FL_SET(target, RMODULE_HAS_NESTED_METHODS); |
|
| 1896 |
rb_overlay_module(cref, c, target); |
|
| 1897 |
} |
|
| 1898 |
else {
|
|
| 1899 |
me = search_method(target, id, Qnil, &defined_class); |
|
| 1900 |
if (me && me->def->type == VM_METHOD_TYPE_ISEQ && |
|
| 1901 |
me->def->body.iseq == miseq) {
|
|
| 1902 |
return; |
|
| 1903 |
} |
|
| 1904 |
} |
|
| 1905 |
noex = NOEX_PRIVATE; |
|
| 1906 |
} |
|
| 1907 |
else {
|
|
| 1908 |
target = klass; |
|
| 1909 |
} |
|
| 1850 | 1910 |
/* dup */ |
| 1851 | 1911 |
COPY_CREF(miseq->cref_stack, cref); |
| 1852 | 1912 |
miseq->cref_stack->nd_visi = NOEX_PUBLIC; |
| 1853 |
miseq->klass = klass;
|
|
| 1913 |
miseq->klass = target;
|
|
| 1854 | 1914 |
miseq->defined_method_id = id; |
| 1855 |
rb_add_method(klass, id, VM_METHOD_TYPE_ISEQ, miseq, noex);
|
|
| 1915 |
rb_add_method(target, id, VM_METHOD_TYPE_ISEQ, miseq, noex);
|
|
| 1856 | 1916 | |
| 1857 | 1917 |
if (!is_singleton && noex == NOEX_MODFUNC) {
|
| 1858 | 1918 |
rb_add_method(rb_singleton_class(klass), id, VM_METHOD_TYPE_ISEQ, miseq, NOEX_PUBLIC); |
| ... | ... | |
| 1866 | 1926 |
} while (0) |
| 1867 | 1927 | |
| 1868 | 1928 |
static VALUE |
| 1869 |
m_core_define_method(VALUE self, VALUE cbase, VALUE sym, VALUE iseqval) |
|
| 1929 |
m_core_define_method(VALUE self, VALUE cbase, VALUE sym, VALUE iseqval, VALUE nested)
|
|
| 1870 | 1930 |
{
|
| 1871 | 1931 |
REWIND_CFP({
|
| 1872 |
vm_define_method(GET_THREAD(), cbase, SYM2ID(sym), iseqval, 0, rb_vm_cref()); |
|
| 1932 |
vm_define_method(GET_THREAD(), cbase, SYM2ID(sym), iseqval, nested, 0, rb_vm_cref());
|
|
| 1873 | 1933 |
}); |
| 1874 | 1934 |
return Qnil; |
| 1875 | 1935 |
} |
| ... | ... | |
| 1878 | 1938 |
m_core_define_singleton_method(VALUE self, VALUE cbase, VALUE sym, VALUE iseqval) |
| 1879 | 1939 |
{
|
| 1880 | 1940 |
REWIND_CFP({
|
| 1881 |
vm_define_method(GET_THREAD(), cbase, SYM2ID(sym), iseqval, 1, rb_vm_cref()); |
|
| 1941 |
vm_define_method(GET_THREAD(), cbase, SYM2ID(sym), iseqval, Qfalse, 1, rb_vm_cref());
|
|
| 1882 | 1942 |
}); |
| 1883 | 1943 |
return Qnil; |
| 1884 | 1944 |
} |
| ... | ... | |
| 1994 | 2054 |
rb_define_method_id(klass, id_core_set_method_alias, m_core_set_method_alias, 3); |
| 1995 | 2055 |
rb_define_method_id(klass, id_core_set_variable_alias, m_core_set_variable_alias, 2); |
| 1996 | 2056 |
rb_define_method_id(klass, id_core_undef_method, m_core_undef_method, 2); |
| 1997 |
rb_define_method_id(klass, id_core_define_method, m_core_define_method, 3);
|
|
| 2057 |
rb_define_method_id(klass, id_core_define_method, m_core_define_method, 4);
|
|
| 1998 | 2058 |
rb_define_method_id(klass, id_core_define_singleton_method, m_core_define_singleton_method, 3); |
| 1999 | 2059 |
rb_define_method_id(klass, id_core_set_postexe, m_core_set_postexe, 1); |
| 2000 | 2060 |
rb_obj_freeze(fcore); |
| b/vm_core.h | ||
|---|---|---|
| 132 | 132 |
rb_method_entry_t *method; |
| 133 | 133 |
long index; |
| 134 | 134 |
} ic_value; |
| 135 |
union {
|
|
| 136 |
VALUE defined_class; |
|
| 137 |
} ic_value2; |
|
| 135 | 138 |
}; |
| 136 | 139 | |
| 137 | 140 |
#if 1 |
| ... | ... | |
| 325 | 328 |
VALUE *bp; /* cfp[2] */ |
| 326 | 329 |
rb_iseq_t *iseq; /* cfp[3] */ |
| 327 | 330 |
VALUE flag; /* cfp[4] */ |
| 328 |
VALUE self; /* cfp[5] / block[0] */ |
|
| 329 |
VALUE *lfp; /* cfp[6] / block[1] */ |
|
| 330 |
VALUE *dfp; /* cfp[7] / block[2] */ |
|
| 331 |
rb_iseq_t *block_iseq; /* cfp[8] / block[3] */ |
|
| 332 |
VALUE proc; /* cfp[9] / block[4] */ |
|
| 333 |
const rb_method_entry_t *me;/* cfp[10] */ |
|
| 331 |
VALUE self; /* cfp[5] / block[0] */ |
|
| 332 |
VALUE klass; /* cfp[6] / block[1] */ |
|
| 333 |
VALUE *lfp; /* cfp[7] / block[2] */ |
|
| 334 |
VALUE *dfp; /* cfp[8] / block[3] */ |
|
| 335 |
rb_iseq_t *block_iseq; /* cfp[9] / block[4] */ |
|
| 336 |
VALUE proc; /* cfp[10] / block[5] */ |
|
| 337 |
const rb_method_entry_t *me;/* cfp[11] */ |
|
| 334 | 338 |
} rb_control_frame_t; |
| 335 | 339 | |
| 336 | 340 |
typedef struct rb_block_struct {
|
| 337 | 341 |
VALUE self; /* share with method frame if it's only block */ |
| 342 |
VALUE klass; /* share with method frame if it's only block */ |
|
| 338 | 343 |
VALUE *lfp; /* share with method frame if it's only block */ |
| 339 | 344 |
VALUE *dfp; /* share with method frame if it's only block */ |
| 340 | 345 |
rb_iseq_t *iseq; |
| ... | ... | |
| 392 | 397 | |
| 393 | 398 |
/* for bmethod */ |
| 394 | 399 |
const rb_method_entry_t *passed_me; |
| 400 |
VALUE passed_defined_class; |
|
| 395 | 401 | |
| 396 | 402 |
/* for load(true) */ |
| 397 | 403 |
VALUE top_self; |
| ... | ... | |
| 711 | 717 |
} \ |
| 712 | 718 |
} while (0) |
| 713 | 719 | |
| 720 |
void rb_overlay_module(NODE*, VALUE, VALUE); |
|
| 721 | ||
| 714 | 722 |
#if defined __GNUC__ && __GNUC__ >= 4 |
| 715 | 723 |
#pragma GCC visibility push(default) |
| 716 | 724 |
#endif |
| b/vm_eval.c | ||
|---|---|---|
| 33 | 33 | |
| 34 | 34 |
static inline VALUE |
| 35 | 35 |
vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv, |
| 36 |
const rb_method_entry_t *me) |
|
| 36 |
const rb_method_entry_t *me, VALUE defined_class)
|
|
| 37 | 37 |
{
|
| 38 | 38 |
const rb_method_definition_t *def = me->def; |
| 39 | 39 |
VALUE val; |
| 40 |
VALUE klass = me->klass;
|
|
| 40 |
VALUE klass = defined_class;
|
|
| 41 | 41 |
const rb_block_t *blockptr = 0; |
| 42 | 42 | |
| 43 | 43 |
if (!def) return Qnil; |
| ... | ... | |
| 62 | 62 |
*reg_cfp->sp++ = argv[i]; |
| 63 | 63 |
} |
| 64 | 64 | |
| 65 |
vm_setup_method(th, reg_cfp, recv, argc, blockptr, 0 /* flag */, me); |
|
| 65 |
vm_setup_method(th, reg_cfp, recv, argc, blockptr, 0 /* flag */, me, klass);
|
|
| 66 | 66 |
val = vm_exec(th); |
| 67 | 67 |
break; |
| 68 | 68 |
} |
| ... | ... | |
| 73 | 73 |
rb_control_frame_t *reg_cfp = th->cfp; |
| 74 | 74 |
rb_control_frame_t *cfp = |
| 75 | 75 |
vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, |
| 76 |
recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1); |
|
| 76 |
recv, klass, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
|
|
| 77 | 77 | |
| 78 | 78 |
cfp->me = me; |
| 79 | 79 |
val = call_cfunc(def->body.cfunc.func, recv, def->body.cfunc.argc, argc, argv); |
| ... | ... | |
| 101 | 101 |
break; |
| 102 | 102 |
} |
| 103 | 103 |
case VM_METHOD_TYPE_BMETHOD: {
|
| 104 |
val = vm_call_bmethod(th, recv, argc, argv, blockptr, me); |
|
| 104 |
val = vm_call_bmethod(th, recv, argc, argv, blockptr, me, klass);
|
|
| 105 | 105 |
break; |
| 106 | 106 |
} |
| 107 | 107 |
case VM_METHOD_TYPE_ZSUPER: {
|
| 108 | 108 |
klass = RCLASS_SUPER(klass); |
| 109 |
if (!klass || !(me = rb_method_entry(klass, id))) {
|
|
| 109 |
if (!klass || !(me = rb_method_entry(klass, id, &klass))) {
|
|
| 110 | 110 |
return method_missing(recv, id, argc, argv, NOEX_SUPER); |
| 111 | 111 |
} |
| 112 | 112 |
RUBY_VM_CHECK_INTS(); |
| ... | ... | |
| 149 | 149 | |
| 150 | 150 |
VALUE |
| 151 | 151 |
rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, const VALUE *argv, |
| 152 |
const rb_method_entry_t *me) |
|
| 152 |
const rb_method_entry_t *me, VALUE defined_class)
|
|
| 153 | 153 |
{
|
| 154 |
return vm_call0(th, recv, id, argc, argv, me); |
|
| 154 |
return vm_call0(th, recv, id, argc, argv, me, defined_class);
|
|
| 155 | 155 |
} |
| 156 | 156 | |
| 157 | 157 |
static inline VALUE |
| ... | ... | |
| 163 | 163 |
rb_method_entry_t *me; |
| 164 | 164 |
rb_control_frame_t *cfp = th->cfp; |
| 165 | 165 | |
| 166 |
if (!cfp->iseq) {
|
|
| 167 |
klass = cfp->me->klass; |
|
| 168 |
klass = RCLASS_SUPER(klass); |
|
| 166 |
if (!cfp->iseq && !NIL_P(cfp->klass)) {
|
|
| 167 |
klass = RCLASS_SUPER(cfp->klass); |
|
| 169 | 168 | |
| 170 | 169 |
if (klass == 0) {
|
| 171 | 170 |
klass = vm_search_normal_superclass(cfp->me->klass, recv); |
| ... | ... | |
| 176 | 175 |
rb_bug("vm_call_super: should not be reached");
|
| 177 | 176 |
} |
| 178 | 177 | |
| 179 |
me = rb_method_entry(klass, id); |
|
| 178 |
me = rb_method_entry(klass, id, &klass);
|
|
| 180 | 179 |
if (!me) {
|
| 181 | 180 |
return method_missing(recv, id, argc, argv, NOEX_SUPER); |
| 182 | 181 |
} |
| 183 | 182 | |
| 184 |
return vm_call0(th, recv, id, argc, argv, me); |
|
| 183 |
return vm_call0(th, recv, id, argc, argv, me, klass);
|
|
| 185 | 184 |
} |
| 186 | 185 | |
| 187 | 186 |
VALUE |
| ... | ... | |
| 202 | 201 |
} |
| 203 | 202 |
} |
| 204 | 203 | |
| 205 |
static inline rb_method_entry_t *rb_search_method_entry(VALUE recv, ID mid); |
|
| 204 |
static inline rb_method_entry_t *rb_search_method_entry(VALUE recv, ID mid, VALUE *defined_class_ptr);
|
|
| 206 | 205 |
static inline int rb_method_call_status(rb_thread_t *th, rb_method_entry_t *me, call_type scope, VALUE self); |
| 207 | 206 |
#define NOEX_OK NOEX_NOSUPER |
| 208 | 207 | |
| ... | ... | |
| 224 | 223 |
rb_call0(VALUE recv, ID mid, int argc, const VALUE *argv, |
| 225 | 224 |
call_type scope, VALUE self) |
| 226 | 225 |
{
|
| 227 |
rb_method_entry_t *me = rb_search_method_entry(recv, mid); |
|
| 226 |
VALUE defined_class; |
|
| 227 |
rb_method_entry_t *me = rb_search_method_entry(recv, mid, &defined_class); |
|
| 228 | 228 |
rb_thread_t *th = GET_THREAD(); |
| 229 | 229 |
int call_status = rb_method_call_status(th, me, scope, self); |
| 230 | 230 | |
| ... | ... | |
| 232 | 232 |
return method_missing(recv, mid, argc, argv, call_status); |
| 233 | 233 |
} |
| 234 | 234 |
stack_check(); |
| 235 |
return vm_call0(th, recv, mid, argc, argv, me); |
|
| 235 |
return vm_call0(th, recv, mid, argc, argv, me, defined_class);
|
|
| 236 | 236 |
} |
| 237 | 237 | |
| 238 | 238 |
struct rescue_funcall_args {
|
| ... | ... | |
| 265 | 265 |
static VALUE |