예제 #1
0
static int
clone_method(ID mid, NODE *body, VALUE nklass)
{
    NODE *fbody = body->nd_body;

    if (fbody) {
	VALUE nbody;

	switch (nd_type(fbody)) {
	  case NODE_SCOPE:
	    fbody = rb_copy_node_scope(fbody, ruby_cref);
    	    break;
	  case NODE_BMETHOD:
	    nbody = rb_block_dup(fbody->nd_cval, nklass, (VALUE)ruby_cref);
	    fbody = NEW_BMETHOD(nbody);
	    break;
	  case NODE_DMETHOD:
	    nbody = rb_method_dup(fbody->nd_cval, nklass, (VALUE)ruby_cref);
	    fbody = NEW_DMETHOD(nbody);
	    break;
	}
    }
    st_insert(RCLASS(nklass)->m_tbl, mid, (st_data_t)NEW_METHOD(fbody, body->nd_noex));
    return ST_CONTINUE;
}
예제 #2
0
static VALUE
rb_mod_define_method(int argc, VALUE *argv, VALUE mod)
{
    ID id;
    VALUE body;
    NODE *node;
    int noex = NOEX_PUBLIC;

    if (argc == 1) {
	id = rb_to_id(argv[0]);
	body = rb_block_lambda();
    }
    else if (argc == 2) {
	id = rb_to_id(argv[0]);
	body = argv[1];
	if (!rb_obj_is_method(body) && !rb_obj_is_proc(body)) {
	    rb_raise(rb_eTypeError,
		     "wrong argument type %s (expected Proc/Method)",
		     rb_obj_classname(body));
	}
    }
    else {
	rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
    }

    if (RDATA(body)->dmark == (RUBY_DATA_FUNC) bm_mark) {
	struct METHOD *method = (struct METHOD *)DATA_PTR(body);
	VALUE rklass = method->rklass;
	if (rklass != mod) {
	    if (FL_TEST(rklass, FL_SINGLETON)) {
		rb_raise(rb_eTypeError,
			 "can't bind singleton method to a different class");
	    }
	    if (!RTEST(rb_class_inherited_p(mod, rklass))) {
		rb_raise(rb_eTypeError,
			 "bind argument must be a subclass of %s",
			 rb_class2name(rklass));
	    }
	}
	node = method->body;
    }
    else if (rb_obj_is_proc(body)) {
	rb_proc_t *proc;
	body = proc_dup(body);
	GetProcPtr(body, proc);
	if (BUILTIN_TYPE(proc->block.iseq) != T_NODE) {
	    proc->block.iseq->defined_method_id = id;
	    proc->block.iseq->klass = mod;
	    proc->is_lambda = Qtrue;
	}
	node = NEW_BMETHOD(body);
    }
    else {
	/* type error */
	rb_raise(rb_eTypeError, "wrong argument type (expected Proc/Method)");
    }

    /* TODO: visibility */

    rb_add_method(mod, id, node, noex);
    return body;
}