예제 #1
0
파일: proc.c 프로젝트: MSch/MacRuby
static VALUE
rb_mod_define_method(VALUE mod, SEL sel, int argc, VALUE *argv)
{
#if MACRUBY_STATIC
    not_implemented_in_static(sel);
#else
    ID id;
    VALUE body;

    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 (rb_obj_is_method(body)) {
	rb_vm_method_t *data;
	Data_Get_Struct(body, rb_vm_method_t, data);
	if (data->node == NULL) {
	    rb_raise(rb_eArgError, "cannot use Method object of pure Objective-C method");
	}
	SEL msel = rb_vm_id_to_sel(id, data->arity);
	rb_vm_define_method2((Class)mod, msel, data->node, data->node->flags, false);
    }
    else {
	rb_vm_block_t *proc;
	GetProcPtr(body, proc);
	rb_vm_define_method3((Class)mod, id, proc);
    }

    return body;
#endif
}
예제 #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;
}