咳といいます。

> matz> |[ruby-dev:21590]のextendの件はmarshal.cで気を使ってくれると
> matz> |良いように思うけど、どうなのかしら。
> matz> 
> matz> 具体的にはどういうアクションが期待されているんでしょう。きち
> matz> んと定義しようとするととたんに難しいように思います。

> えっと、s_dumpの時みたいにこんな感じなのを思ってました。

> --- marshal.c~  Fri Oct 10 02:45:52 2003
> +++ marshal.c   Tue Oct 14 08:55:28 2003
> @@ -483,8 +483,7 @@
>             VALUE v;
>  
>             v = rb_funcall(obj, s_mdump, 0, 0);
> -           w_byte(TYPE_USRMARSHAL, arg);
> -           w_unique(rb_class2name(CLASS_OF(obj)), arg);
> +           w_class(TYPE_USRMARSHAL, obj, arg);
>             w_object(v, arg, limit);
>             if (ivtbl) w_ivar(0, &c_arg);
>             return;


> でも、復元する時は、r_object0()してからrb_extend_object()するので
> (つまり、オブジェクトが復元されてからextendされるので)
> marshal_loadを持つモジュールをextendしても呼んでもらえないんですね。
> 
>       case TYPE_EXTENDED:
> 	{
> 	    VALUE m = path2module(r_unique(arg));
> 
> 	    v = r_object0(arg, 0, 0);
> 	    rb_extend_object(v, m);
> 	}
> 	break;


あんまりかっこよくないんですけど、こういう動きです。↑のに追加で…


--- marshal.c~	Tue Oct 14 08:55:28 2003
+++ marshal.c	Wed Oct 15 08:02:54 2003
@@ -952,10 +952,11 @@
 }
 
 static VALUE
-r_object0(arg, proc, ivp)
+r_object0(arg, proc, ivp, extended)
     struct load_arg *arg;
     VALUE proc;
     int *ivp;
+    VALUE extended;
 {
     VALUE v = Qnil;
     int type = r_byte(arg);
@@ -974,7 +975,7 @@
         {
 	    int ivar = Qtrue;
 
-	    v = r_object0(arg, 0, &ivar);
+	    v = r_object0(arg, 0, &ivar, extended);
 	    if (ivar) r_ivar(v, arg);
 	}
 	break;
@@ -983,8 +984,14 @@
 	{
 	    VALUE m = path2module(r_unique(arg));
 
-	    v = r_object0(arg, 0, 0);
-	    rb_extend_object(v, m);
+            if (NIL_P(extended)) extended = rb_ary_new2(0);
+            rb_ary_push(extended, m);
+
+	    v = r_object0(arg, 0, 0, extended);
+            while (RARRAY(extended)->len > 0) {
+                m = rb_ary_pop(extended);
+                rb_extend_object(v, m);
+            }
 	}
 	break;
 
@@ -995,7 +1002,7 @@
 	    if (FL_TEST(c, FL_SINGLETON)) {
 		rb_raise(rb_eTypeError, "singleton can't be loaded");
 	    }
-	    v = r_object0(arg, 0, 0);
+	    v = r_object0(arg, 0, 0, extended);
 	    if (rb_special_const_p(v) || TYPE(v) == T_OBJECT || TYPE(v) == T_CLASS) {
 	      format_error:
 		rb_raise(rb_eArgError, "dump format error (user class)");
@@ -1199,6 +1206,12 @@
 	    VALUE data;
 
 	    v = rb_obj_alloc(klass);
+            if (! NIL_P(extended)) {
+                while (RARRAY(extended)->len > 0) {
+                    VALUE m = rb_ary_pop(extended);
+                    rb_extend_object(v, m);
+                }
+            }
 	    if (!rb_respond_to(v, s_mload)) {
 		rb_raise(rb_eTypeError, "instance of %s needs to have method `marshal_load'",
 			 rb_class2name(klass));
@@ -1245,7 +1258,7 @@
                         "class %s needs to have instance method `_load_data'",
                         rb_class2name(klass));
            }
-           rb_funcall(v, s_load_data, 1, r_object0(arg, 0, 0));
+           rb_funcall(v, s_load_data, 1, r_object0(arg, 0, 0, extended));
        }
        break;
 
@@ -1297,7 +1310,7 @@
 r_object(arg)
     struct load_arg *arg;
 {
-    return r_object0(arg, arg->proc, 0);
+    return r_object0(arg, arg->proc, 0, Qnil);
 }
 
 static VALUE