From: m_seki@... Date: 2003-10-15T08:31:59+09:00 Subject: [ruby-list:38564] Re: marshal_dump (was Re: ) 咳といいます。 > 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