Feature #4085 » nested_methods-r29944-20101127.diff
bootstraptest/test_method.rb | ||
---|---|---|
assert_equal '1', %q( class C
|
||
def m
|
||
def mm() 1 end
|
||
mm
|
||
end
|
||
end
|
||
C.new.m
|
||
C.new.mm )
|
||
C.new.m )
|
||
assert_equal '1', %q( class C
|
||
def m
|
||
def mm() 1 end
|
||
mm
|
||
end
|
||
end
|
||
instance_eval "C.new.m; C.new.mm" )
|
||
instance_eval "C.new.m" )
|
||
# method_missing
|
||
assert_equal ':m', %q( class C
|
compile.c | ||
---|---|---|
ADD_INSN1(ret, nd_line(node), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
|
||
ADD_INSN1(ret, nd_line(node), putobject, ID2SYM(node->nd_mid));
|
||
ADD_INSN1(ret, nd_line(node), putiseq, iseqval);
|
||
ADD_SEND (ret, nd_line(node), ID2SYM(id_core_define_method), INT2FIX(3));
|
||
ADD_INSN1(ret, nd_line(node), putobject,
|
||
node->flags & NODE_FL_NESTED_DEF ? Qtrue : Qfalse);
|
||
ADD_SEND (ret, nd_line(node), ID2SYM(id_core_define_method), INT2FIX(4));
|
||
if (poped) {
|
||
ADD_INSN(ret, nd_line(node), pop);
|
include/ruby/ruby.h | ||
---|---|---|
#define RMODULE_M_TBL(m) RCLASS_M_TBL(m)
|
||
#define RMODULE_SUPER(m) RCLASS_SUPER(m)
|
||
#define RMODULE_IS_OVERLAYED FL_USER2
|
||
#define RMODULE_HAS_NESTED_METHODS FL_USER3
|
||
struct RFloat {
|
||
struct RBasic basic;
|
node.h | ||
---|---|---|
#define NODE_FL_NEWLINE (((VALUE)1)<<7)
|
||
#define NODE_FL_CREF_PUSHED_BY_EVAL NODE_FL_NEWLINE
|
||
#define NODE_FL_CREF_OMOD_SHARED (((VALUE)1)<<6)
|
||
#define NODE_FL_NESTED_DEF NODE_FL_CREF_OMOD_SHARED
|
||
#define NODE_TYPESHIFT 8
|
||
#define NODE_TYPEMASK (((VALUE)0x7f)<<NODE_TYPESHIFT)
|
parse.y | ||
---|---|---|
reduce_nodes(&body);
|
||
$$ = NEW_DEFN($2, $4, body, NOEX_PRIVATE);
|
||
nd_set_line($$, $<num>1);
|
||
if (in_def > 1 || in_single > 0)
|
||
$$->flags |= NODE_FL_NESTED_DEF;
|
||
/*%
|
||
$$ = dispatch3(def, $2, $4, $5);
|
||
%*/
|
test/rdoc/test_rdoc_text.rb | ||
---|---|---|
assert_equal expected, flush_left(text)
|
||
end
|
||
def formatter() RDoc::Markup::ToHtml.new end
|
||
def test_markup
|
||
def formatter() RDoc::Markup::ToHtml.new end
|
||
assert_equal "<p>\nhi\n</p>\n", markup('hi')
|
||
end
|
test/ruby/test_nested_method.rb | ||
---|---|---|
require 'test/unit'
|
||
class TestNestedMethod < Test::Unit::TestCase
|
||
def call_nested_method
|
||
def foo
|
||
return "foo"
|
||
end
|
||
return foo
|
||
end
|
||
def test_nested_method
|
||
assert_equal("foo", call_nested_method)
|
||
assert_raise(NoMethodError) { foo() }
|
||
end
|
||
def test_doubly_nested_method
|
||
def call_doubly_nested_method
|
||
def foo
|
||
return "foo"
|
||
end
|
||
return foo
|
||
end
|
||
assert_equal("foo", call_doubly_nested_method)
|
||
assert_raise(NoMethodError) { foo() }
|
||
end
|
||
end
|
vm.c | ||
---|---|---|
return self;
|
||
}
|
||
static VALUE
|
||
find_module_for_nested_methods(NODE *cref, VALUE klass)
|
||
{
|
||
VALUE iclass;
|
||
if (NIL_P(cref->nd_omod))
|
||
return Qnil;
|
||
iclass = rb_hash_lookup(cref->nd_omod, klass);
|
||
if (NIL_P(iclass))
|
||
return Qnil;
|
||
while (iclass) {
|
||
VALUE module = RBASIC(iclass)->klass;
|
||
if (FL_TEST(module, RMODULE_HAS_NESTED_METHODS)) {
|
||
return module;
|
||
}
|
||
iclass = RCLASS_SUPER(iclass);
|
||
}
|
||
return Qnil;
|
||
}
|
||
VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase);
|
||
static void
|
||
vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval,
|
||
vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval, VALUE nested,
|
||
rb_num_t is_singleton, NODE *cref)
|
||
{
|
||
VALUE klass = cref->nd_clss;
|
||
VALUE target, defined_class;
|
||
rb_method_entry_t *me;
|
||
int noex = (int)cref->nd_visi;
|
||
int is_nested = RTEST(nested);
|
||
rb_iseq_t *miseq;
|
||
GetISeqPtr(iseqval, miseq);
|
||
... | ... | |
noex = NOEX_PUBLIC;
|
||
}
|
||
if (is_nested && th->cfp->lfp == th->cfp->dfp) {
|
||
VALUE c;
|
||
if (TYPE(klass) == T_MODULE) {
|
||
c = rb_obj_class(th->cfp->self);
|
||
}
|
||
else {
|
||
c = klass;
|
||
}
|
||
if (cref->flags & NODE_FL_CREF_OMOD_SHARED) {
|
||
target = Qnil;
|
||
}
|
||
else {
|
||
target = find_module_for_nested_methods(cref, c);
|
||
}
|
||
if (NIL_P(target)) {
|
||
target = rb_module_new();
|
||
FL_SET(target, RMODULE_HAS_NESTED_METHODS);
|
||
rb_overlay_module(cref, c, target);
|
||
}
|
||
else {
|
||
me = search_method(target, id, Qnil, &defined_class);
|
||
if (me && me->def->type == VM_METHOD_TYPE_ISEQ &&
|
||
me->def->body.iseq == miseq) {
|
||
return;
|
||
}
|
||
}
|
||
noex = NOEX_PRIVATE;
|
||
}
|
||
else {
|
||
target = klass;
|
||
}
|
||
/* dup */
|
||
COPY_CREF(miseq->cref_stack, cref);
|
||
miseq->cref_stack->nd_visi = NOEX_PUBLIC;
|
||
miseq->klass = klass;
|
||
miseq->klass = target;
|
||
miseq->defined_method_id = id;
|
||
rb_add_method(klass, id, VM_METHOD_TYPE_ISEQ, miseq, noex);
|
||
rb_add_method(target, id, VM_METHOD_TYPE_ISEQ, miseq, noex);
|
||
if (!is_singleton && noex == NOEX_MODFUNC) {
|
||
rb_add_method(rb_singleton_class(klass), id, VM_METHOD_TYPE_ISEQ, miseq, NOEX_PUBLIC);
|
||
... | ... | |
} while (0)
|
||
static VALUE
|
||
m_core_define_method(VALUE self, VALUE cbase, VALUE sym, VALUE iseqval)
|
||
m_core_define_method(VALUE self, VALUE cbase, VALUE sym, VALUE iseqval, VALUE nested)
|
||
{
|
||
REWIND_CFP({
|
||
vm_define_method(GET_THREAD(), cbase, SYM2ID(sym), iseqval, 0, rb_vm_cref());
|
||
vm_define_method(GET_THREAD(), cbase, SYM2ID(sym), iseqval, nested, 0, rb_vm_cref());
|
||
});
|
||
return Qnil;
|
||
}
|
||
... | ... | |
m_core_define_singleton_method(VALUE self, VALUE cbase, VALUE sym, VALUE iseqval)
|
||
{
|
||
REWIND_CFP({
|
||
vm_define_method(GET_THREAD(), cbase, SYM2ID(sym), iseqval, 1, rb_vm_cref());
|
||
vm_define_method(GET_THREAD(), cbase, SYM2ID(sym), iseqval, Qfalse, 1, rb_vm_cref());
|
||
});
|
||
return Qnil;
|
||
}
|
||
... | ... | |
rb_define_method_id(klass, id_core_set_method_alias, m_core_set_method_alias, 3);
|
||
rb_define_method_id(klass, id_core_set_variable_alias, m_core_set_variable_alias, 2);
|
||
rb_define_method_id(klass, id_core_undef_method, m_core_undef_method, 2);
|
||
rb_define_method_id(klass, id_core_define_method, m_core_define_method, 3);
|
||
rb_define_method_id(klass, id_core_define_method, m_core_define_method, 4);
|
||
rb_define_method_id(klass, id_core_define_singleton_method, m_core_define_singleton_method, 3);
|
||
rb_define_method_id(klass, id_core_set_postexe, m_core_set_postexe, 1);
|
||
rb_obj_freeze(fcore);
|
vm_core.h | ||
---|---|---|
} \
|
||
} while (0)
|
||
void rb_overlay_module(NODE*, VALUE, VALUE);
|
||
#if defined __GNUC__ && __GNUC__ >= 4
|
||
#pragma GCC visibility push(default)
|
||
#endif
|
vm_method.c | ||
---|---|---|
}
|
||
if (!RTEST(rb_class_inherited_p(klass, me->klass))) {
|
||
VALUE mod = rb_module_new();
|
||
rb_overlay_module(cref, klass, mod);
|
||
klass = mod;
|
||
if (FL_TEST(me->klass, RMODULE_HAS_NESTED_METHODS)) {
|
||
klass = me->klass;
|
||
}
|
||
else {
|
||
VALUE mod = rb_module_new();
|
||
rb_overlay_module(cref, klass, mod);
|
||
klass = mod;
|
||
}
|
||
}
|
||
rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, NOEX_PUBLIC);
|
||
- « Previous
- 1
- 2
- 3
- 4
- Next »