? test
? secret.patch
Index: class.c
===================================================================
RCS file: /src/ruby/class.c,v
retrieving revision 1.36
diff -u -r1.36 class.c
--- class.c	2002/03/08 07:03:03	1.36
+++ class.c	2002/03/10 17:43:38
@@ -434,7 +434,7 @@
     NODE *body;
     VALUE ary;
 {
-    if ((body->nd_noex&(NOEX_PRIVATE|NOEX_PROTECTED)) == 0) {
+    if ((body->nd_noex&(NOEX_SECRET|NOEX_PRIVATE|NOEX_PROTECTED)) == 0) {
 	VALUE name = rb_str_new2(rb_id2name(key));
 
 	if (!rb_ary_includes(ary, name)) {
@@ -499,6 +499,30 @@
     return ST_CONTINUE;
 }
 
+static int
+ins_methods_secr_i(key, body, ary)
+    ID key;
+    NODE *body;
+    VALUE ary;
+{
+    if (!body->nd_body) {
+	rb_ary_push(ary, Qnil);
+	rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
+    }
+    else if (body->nd_noex & NOEX_SECRET) {
+	VALUE name = rb_str_new2(rb_id2name(key));
+
+	if (!rb_ary_includes(ary, name)) {
+	    rb_ary_push(ary, name);
+	}
+    }
+    else if (nd_type(body->nd_body) == NODE_ZSUPER) {
+	rb_ary_push(ary, Qnil);
+	rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
+    }
+    return ST_CONTINUE;
+}
+
 static VALUE
 method_list(mod, option, func)
     VALUE mod;
@@ -563,6 +587,18 @@
 }
 
 VALUE
+rb_class_secret_instance_methods(argc, argv, mod)
+    int argc;
+    VALUE *argv;
+    VALUE mod;
+{
+    VALUE option;
+
+    rb_scan_args(argc, argv, "01", &option);
+    return method_list(mod, RTEST(option), ins_methods_secr_i);
+}
+
+VALUE
 rb_obj_singleton_methods(argc, argv, obj)
     int argc;
     VALUE *argv;
@@ -643,6 +679,17 @@
 {
     rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc),
 		  NOEX_PRIVATE|NOEX_CFUNC);
+}
+
+void
+rb_define_secret_method(klass, name, func, argc)
+    VALUE klass;
+    const char *name;
+    VALUE (*func)();
+    int argc;
+{
+    rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc),
+		  NOEX_SECRET|NOEX_CFUNC);
 }
 
 void
Index: eval.c
===================================================================
RCS file: /src/ruby/eval.c,v
retrieving revision 1.270
diff -u -r1.270 eval.c
--- eval.c	2002/03/08 07:03:03	1.270
+++ eval.c	2002/03/10 17:44:07
@@ -111,8 +111,9 @@
 #define SCOPE_PUBLIC    0
 #define SCOPE_PRIVATE   1
 #define SCOPE_PROTECTED 2
-#define SCOPE_MODFUNC   5
-#define SCOPE_MASK      7
+#define SCOPE_SECRET    4
+#define SCOPE_MODFUNC   8
+#define SCOPE_MASK      15
 #define SCOPE_SET(f)  do {scope_vmode=(f);} while(0)
 #define SCOPE_TEST(f) (scope_vmode&(f))
 
@@ -423,13 +424,13 @@
     /* is it in the method cache? */
     ent = cache + EXPR1(klass, id);
     if (ent->mid == id && ent->klass == klass) {
-	if (ex && (ent->noex & NOEX_PRIVATE))
+	if (ex && (ent->noex & (NOEX_PRIVATE | NOEX_SECRET)))
 	    return Qfalse;
 	if (!ent->method) return Qfalse;
 	return Qtrue;
     }
     if (rb_get_method_body(&klass, &id, &noex)) {
-	if (ex && (noex & NOEX_PRIVATE))
+	if (ex && (noex & (NOEX_PRIVATE | NOEX_SECRET)))
 	    return Qfalse;
 	return Qtrue;
     }
@@ -459,6 +460,12 @@
 		       "attribute accessor as module_function" :
 		       "private attribute?");
 	}
+        else if (SCOPE_TEST(SCOPE_SECRET)) {
+	    noex = NOEX_SECRET;
+	    rb_warning((scope_vmode == SCOPE_MODFUNC) ?
+		       "attribute accessor as module_function" :
+		       "secret attribute?");
+	}
 	else if (SCOPE_TEST(SCOPE_PROTECTED)) {
 	    noex = NOEX_PROTECTED;
 	}
@@ -3104,8 +3111,15 @@
 	    rb_frozen_class_p(ruby_class);
 	    body = search_method(ruby_class, node->nd_mid, &origin);
 	    if (body){
-		if (RTEST(ruby_verbose) && ruby_class == origin && body->nd_cnt == 0) {
-		    rb_warning("discarding old %s", rb_id2name(node->nd_mid));
+		if (RTEST(ruby_verbose)) {
+                    if (ruby_class == origin && body->nd_cnt == 0) {
+		        rb_warning("discarding old %s",
+                                   rb_id2name(node->nd_mid));
+		    }
+		    else if (body->nd_noex & NOEX_SECRET) {
+			rb_warning("hiding secret method %s in base class",
+				   rb_id2name(node->nd_mid));
+		    }
 		}
 		if (node->nd_noex) { /* toplevel */
 		    /* should upgrade to rb_warn() if no super was called inside? */
@@ -3117,6 +3131,9 @@
 	    if (SCOPE_TEST(SCOPE_PRIVATE) || node->nd_mid == init) {
 		noex = NOEX_PRIVATE;
 	    }
+            else if (SCOPE_TEST(SCOPE_SECRET)) {
+		noex = NOEX_SECRET;
+	    }
 	    else if (SCOPE_TEST(SCOPE_PROTECTED)) {
 		noex = NOEX_PROTECTED;
 	    }
@@ -4187,6 +4204,7 @@
 #define CSTAT_PRIV  1
 #define CSTAT_PROT  2
 #define CSTAT_VCALL 4
+#define CSTAT_SECR  8
 
 static VALUE
 rb_f_missing(argc, argv, obj)
@@ -4234,6 +4252,9 @@
 	desc = RSTRING(d)->ptr;
     }
 
+    if (last_call_status & CSTAT_SECR) {
+        format = "secret method `%s' called for %s%s%s";
+    }
     if (last_call_status & CSTAT_PRIV) {
 	format = "private method `%s' called for %s%s%s";
     }
@@ -4660,8 +4681,13 @@
     }
 
     if (mid != missing) {
+	/* receiver must be the same type as the current class for secret */
+	if ((noex & NOEX_SECRET) && klass != ruby_frame->last_class) {
+	    return rb_undefined(recv, mid, argc, argv, CSTAT_SECR);
+	}
+	    
 	/* receiver specified form for private method */
-	if ((noex & NOEX_PRIVATE) && scope == 0)
+	if ((noex & (NOEX_PRIVATE | NOEX_SECRET)) && scope == 0)
 	    return rb_undefined(recv, mid, argc, argv, CSTAT_PRIV);
 
 	/* self must be kind of a specified form for private method */
@@ -5672,6 +5698,22 @@
 }
 
 static VALUE
+rb_mod_secret(argc, argv, module)
+    int argc;
+    VALUE *argv;
+    VALUE module;
+{
+    secure_visibility(module);
+    if (argc == 0) {
+	SCOPE_SET(SCOPE_SECRET);
+    }
+    else {
+	set_method_visibility(module, argc, argv, NOEX_SECRET);
+    }
+    return module;
+}
+
+static VALUE
 rb_mod_public_method(argc, argv, obj)
     int argc;
     VALUE *argv;
@@ -5692,6 +5734,16 @@
 }
 
 static VALUE
+rb_mod_secret_method(argc, argv, obj)
+    int argc;
+    VALUE *argv;
+    VALUE obj;
+{
+    set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_SECRET);
+    return obj;
+}
+
+static VALUE
 top_public(argc, argv)
     int argc;
     VALUE *argv;
@@ -6074,10 +6126,12 @@
     rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
     rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
     rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
+    rb_define_private_method(rb_cModule, "secret", rb_mod_secret, -1);
     rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
     rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
     rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
     rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
+    rb_define_method(rb_cModule, "secret_class_method", rb_mod_secret_method, -1);
     rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
     rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
 
@@ -7046,6 +7100,9 @@
     }
     else if (SCOPE_TEST(SCOPE_PROTECTED)) {
 	noex = NOEX_PROTECTED;
+    }
+    else if (SCOPE_TEST(SCOPE_SECRET)) {
+	noex = NOEX_SECRET;
     }
     else {
 	noex = NOEX_PUBLIC;
Index: intern.h
===================================================================
RCS file: /src/ruby/intern.h,v
retrieving revision 1.82
diff -u -r1.82 intern.h
--- intern.h	2002/03/07 11:19:37	1.82
+++ intern.h	2002/03/10 17:44:10
@@ -103,14 +103,15 @@
 VALUE rb_class_instance_methods _((int, VALUE*, VALUE));
 VALUE rb_class_protected_instance_methods _((int, VALUE*, VALUE));
 VALUE rb_class_private_instance_methods _((int, VALUE*, VALUE));
+VALUE rb_class_secret_instance_methods _((int, VALUE*, VALUE));
 VALUE rb_obj_singleton_methods _((int, VALUE*, VALUE));
 void rb_define_method_id _((VALUE, ID, VALUE (*)(ANYARGS), int));
 void rb_frozen_class_p _((VALUE));
 void rb_undef _((VALUE, ID));
 void rb_define_protected_method _((VALUE, const char*, VALUE (*)(ANYARGS), int));
 void rb_define_private_method _((VALUE, const char*, VALUE (*)(ANYARGS), int));
+void rb_define_secret_method _((VALUE, const char*, VALUE(*)(ANYARGS), int));
 void rb_define_singleton_method _((VALUE, const char*, VALUE(*)(ANYARGS), int));
-void rb_define_private_method _((VALUE, const char*, VALUE(*)(ANYARGS), int));
 VALUE rb_singleton_class _((VALUE));
 /* enum.c */
 /* error.c */
Index: node.h
===================================================================
RCS file: /src/ruby/node.h,v
retrieving revision 1.28
diff -u -r1.28 node.h
--- node.h	2002/02/13 09:01:09	1.28
+++ node.h	2002/03/10 17:44:12
@@ -336,6 +336,7 @@
 #define NOEX_CFUNC     1
 #define NOEX_PRIVATE   2
 #define NOEX_PROTECTED 4 
+#define NOEX_SECRET    8
 
 NODE *rb_compile_cstr _((const char*, const char*, int, int));
 NODE *rb_compile_string _((const char*, VALUE, int));
Index: object.c
===================================================================
RCS file: /src/ruby/object.c,v
retrieving revision 1.75
diff -u -r1.75 object.c
--- object.c	2002/03/08 07:03:03	1.75
+++ object.c	2002/03/10 17:44:16
@@ -857,6 +857,22 @@
 }
 
 static VALUE
+rb_obj_secret_methods(obj)
+    VALUE obj;
+{
+    VALUE argv[1];
+
+    argv[0] = Qtrue;
+    return rb_class_secret_instance_methods(1, argv, CLASS_OF(obj));
+}
+
+struct arg_to {
+    VALUE val;
+    const char *s;
+    ID m;
+};
+
+static VALUE
 convert_type(val, tname, method, raise)
     VALUE val;
     const char *tname, *method;
@@ -1258,6 +1274,7 @@
     rb_define_method(rb_mKernel, "singleton_methods", rb_obj_singleton_methods, -1);
     rb_define_method(rb_mKernel, "protected_methods", rb_obj_protected_methods, 0);
     rb_define_method(rb_mKernel, "private_methods", rb_obj_private_methods, 0);
+    rb_define_method(rb_mKernel, "secret_methods", rb_obj_secret_methods, 0);
     rb_define_method(rb_mKernel, "instance_variables", rb_obj_instance_variables, 0);
     rb_define_private_method(rb_mKernel, "remove_instance_variable",
 			     rb_obj_remove_instance_variable, 1);
@@ -1330,6 +1347,7 @@
     rb_define_method(rb_cModule, "public_instance_methods", rb_class_instance_methods, -1);
     rb_define_method(rb_cModule, "protected_instance_methods", rb_class_protected_instance_methods, -1);
     rb_define_method(rb_cModule, "private_instance_methods", rb_class_private_instance_methods, -1);
+    rb_define_method(rb_cModule, "secret_instance_methods", rb_class_secret_instance_methods, -1);
 
     rb_define_method(rb_cModule, "constants", rb_mod_constants, 0);
     rb_define_method(rb_cModule, "const_get", rb_mod_const_get, 1);
