Hi,
At Mon, 6 Dec 2004 09:39:43 +0900,
Peter wrote in [ruby-talk:122619]:
At
https://developer.berlios.de/project/showfiles.php?group_id=1216&release_id=4105
you can find a patch that implements the idea but returns an UnboundMethod
instead of a symbol (or a Method when defining a singleton method). It
extends Module#public/private/protected to take a single (Unbound)?Method
as parameter. The patch is against the source of Ruby 1.8.2.
I wonder if this might cause confution.
class Foo
public def foo
end
end
class Bar
private Foo.instance_method
foo)
end
Aren't Method#public etc. superfluous?
Index: eval.c
===================================================================
RCS file: /cvs/ruby/src/ruby/eval.c,v
retrieving revision 1.742
diff -U2 -p -d -r1.742 eval.c
--- eval.c 3 Dec 2004 04:56:24 -0000 1.742
+++ eval.c 6 Dec 2004 02:50:59 -0000
@@ -147,4 +147,7 @@ static VALUE rb_mod_define_method _((int
NORETURN(static void rb_raise_jump _((VALUE)));
static VALUE rb_make_exception _((int argc, VALUE *argv));
+static VALUE um_new _((VALUE klass, NODE *body, ID id));
+static VALUE m_new _((VALUE klass, VALUE recv, NODE *body, ID id));
+static ID check_method_id _((VALUE obj, VALUE mod));
static int scope_vmode;
@@ -315,5 +318,5 @@ static ID added, singleton_added;
static ID __id__, __send__, respond_to;
-void
+NODE *
rb_add_method(klass, mid, node, noex)
VALUE klass;
@@ -351,4 +354,5 @@ rb_add_method(klass, mid, node, noex)
}
}
+ return node;
}
@@ -3671,10 +3675,10 @@ rb_eval(self, n)
defn = copy_node_scope(node->nd_defn, ruby_cref);
- rb_add_method(ruby_class, node->nd_mid, defn, noex);
+ body = rb_add_method(ruby_class, node->nd_mid, defn, noex);
if (scope_vmode == SCOPE_MODFUNC) {
rb_add_method(rb_singleton_class(ruby_class),
node->nd_mid, defn, NOEX_PUBLIC);
}
- result = Qnil;
+ result = um_new(ruby_class, body, node->nd_mid);
}
break;
@@ -3707,7 +3711,7 @@ rb_eval(self, n)
}
defn = copy_node_scope(node->nd_defn, ruby_cref);
- rb_add_method(klass, node->nd_mid, defn,
+ body = rb_add_method(klass, node->nd_mid, defn,
NOEX_PUBLIC|(body?body->nd_noex&NOEX_UNDEF:0));
- result = Qnil;
+ result = m_new(klass, recv, body, node->nd_mid);
}
break;
@@ -6926,8 +6930,13 @@ set_method_visibility(self, argc, argv,
{
int i;
+ VALUE m;
+ ID id;
secure_visibility(self);
for (i=0; i<argc; i++) {
- rb_export_method(self, rb_to_id(argv
), ex);
+ m = argv;
+ id = check_method_id(m, self);
+ if (!id) id = rb_to_id(m);
+ rb_export_method(self, id, ex);
}
rb_clear_cache_by_class(self);
@@ -7148,20 +7157,22 @@ rb_mod_modfunc(argc, argv, module)
set_method_visibility(module, argc, argv, NOEX_PRIVATE);
for (i=0; i<argc; i++) {
- VALUE m = module;
+ if (!(id = check_method_id(argv, module))) {
+ VALUE m = module;
- id = rb_to_id(argv);
- for (; {
- body = search_method(m, id, &m);
- if (body == 0) {
- body = search_method(rb_cObject, id, &m);
- }
- if (body == 0 || body->nd_body == 0) {
- rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
- }
- if (nd_type(body->nd_body) != NODE_ZSUPER) {
- break; /* normal case: need not to follow 'super' link */
+ id = rb_to_id(argv);
+ for (; {
+ body = search_method(m, id, &m);
+ if (body == 0) {
+ body = search_method(rb_cObject, id, &m);
+ }
+ if (body == 0 || body->nd_body == 0) {
+ rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
+ }
+ if (nd_type(body->nd_body) != NODE_ZSUPER) {
+ break; /* normal case: need not to follow 'super' link */
+ }
+ m = RCLASS(m)->super;
+ if (!m) break;
}
- m = RCLASS(m)->super;
- if (!m) break;
}
rb_add_method(rb_singleton_class(module), id, body->nd_body, NOEX_PUBLIC);
@@ -8635,5 +8646,5 @@ mnew(klass, obj, id, mklass)
}
if (TYPE(klass) == T_ICLASS) klass = RBASIC(klass)->klass;
- method = Data_Make_Struct(mklass, struct METHOD, bm_mark, free, data);
+ method = Data_Make_Struct(mklass, struct METHOD, bm_mark, -1, data);
data->klass = klass;
data->recv = obj;
@@ -8647,4 +8658,79 @@ mnew(klass, obj, id, mklass)
}
+static VALUE
+um_new(klass, body, id)
+ VALUE klass;
+ ID id;
+ NODE *body;
+{
+ VALUE method;
+ struct METHOD *data;
+
+ method = Data_Make_Struct(rb_cUnboundMethod, struct METHOD, bm_mark, -1, data);
+ data->klass = klass;
+ data->recv = Qundef;
+ data->id = id;
+ data->body = body;
+ data->rklass = klass;
+ data->oid = id;
+ OBJ_INFECT(method, klass);
+
+ return method;
+}
+
+static VALUE
+m_new(klass, recv, body, id)
+ VALUE klass, recv;
+ ID id;
+ NODE *body;
+{
+ VALUE method;
+ struct METHOD *data;
+
+ method = Data_Make_Struct(rb_cMethod, struct METHOD, bm_mark, -1, data);
+ data->klass = klass;
+ data->recv = recv;
+ data->id = id;
+ data->body = body;
+ data->rklass = klass;
+ data->oid = id;
+ OBJ_INFECT(method, klass);
+
+ return method;
+}
+
+static ID
+check_method_id(obj, mod)
+ VALUE obj, mod;
+{
+ struct METHOD *data;
+ VALUE klass;
+ ID id;
+ ID noex;
+ NODE *body;
+
+ if (TYPE(obj) != T_DATA || RDATA(obj)->dmark != bm_mark)
+ return 0;
+ data = (struct METHOD *)RDATA(obj)->data;
+ if (data->rklass != mod) {
+ rb_raise(rb_eTypeError, "%s mismatch - %s for %s",
+ (TYPE(mod) == T_CLASS ? "class" : "module"),
+ rb_obj_as_string(data->rklass), rb_obj_as_string(mod));
+ }
+ for (klass = data->rklass, id = data->oid;; klass = RCLASS(klass)->super) {
+ if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
+ rb_raise(rb_eTypeError, "method %s in %s disappeared",
+ rb_id2name(data->oid), rb_class2name(data->rklass));
+ }
+
+ if (nd_type(body) != NODE_ZSUPER) break;
+ }
+
+ if (body != data->body) {
+ rb_raise(rb_eTypeError, "method %s in %s changed",
+ rb_id2name(data->oid), rb_class2name(data->rklass));
+ }
+ return data->oid;
+}
/**********************************************************************