--Multipart_Sat_Mar__2_06:38:05_2002-1 Content-Type: text/plain; charset=ISO-2022-JP GUI toolkit¤Î¤è¤¦¤Ê¡¢Â礤¯¤Æ¤«¤Ä°ìÉô¤·¤«»È¤ï¤Ê¤¤¤³¤È¤¬Â¿¤¤¤â¤Î¤ò ¥â¥¸¥å¡¼¥ë¤Ë¤¹¤ë¾ì¹ç¤ò¹Í¤¨¤ë¤È¡¢¤Ê¤ë¤Ù¤¯autoload¤ò»Ä¤·¤ÆÄº¤±¤ëÊý¤¬ ¤è¤¤¤È»×¤¤¤Þ¤¹¡£ > |>¤È¤¤¤¦¤³¤È¤Ç¡¢¤Û¤ó¤È¤Ïautoload¤Ï¤Ê¤¯¤·¤¿¤¤¤Ç¤¹¡£Rite¤Ç¤Ï¤Ê¤¯ > |>¤Ê¤ë¤«¤â¡£ > | > |¤²¡¢¤Ê¤Î¤«¤¢¡£¤·¤«¤·¡¢autoload ¤¬ require ¤·¤¿¥Õ¥¡¥¤¥ë¤Ë¤Ï > |¿ʬµá¤á¤ëÄê¿ô¤ÎÄêµÁ¤¬ «¤ì¤Æ¤¤¤ë¤Î¤Ç¡¢¤ Äê¿ô¤Ë´Ø¤·¤Æ¤Ï£²ÅÙ > |¤È fallback ¤Ï¸Æ¤Ð¤ì¤Ê¤¤¤Î¤Ç¡¢¤Ê¤Ë®ÅÙ¤ÏÊѤï¤é¤Ê¤¤µ¤¤¬¤¹¤ë > |¤ó¤À¤±¤É¡¢¤Ç¤â¤Ê¤¤¤Î¤«¤Ê¡£ > > Äê¿ô¸Æ¤Ó ·¤Î¤¿¤Ó¤Ë¿Æ¥¯¥é¥¹¤Ëʹ¤¤Ë¹Ô¤¯Á°¤¨Âæáììâáãë¤Î¸ºß¤ò > ¥Á¥§¥Ã¥¯¤·¤Ë¹Ô¤«¤Ê¤¤¤È¤¤¤±¤Ê¤¤¤è¤¦¤Êµ¤¤¬¤·¤Þ¤¹¡£¤¬Çϼ¯¤Ë > ¤Ç¤¤Ê¤¤¥³¥¹¥È¤Î¤è¤¦¤Ê¡£ fallback¤ò¥Á¥§¥Ã¥¯¤·¤Ë¤¤¤¯Âå¤ï¤ê¤Ë¡¢ ËÜʪ¤Î¥ª¥Ö¥¸¥§¥¯¥È¤ÎÂå¤ï¤ê¤Ë autoload ¤¹¤ë¤³¤È¤ò¼¨¤¹¥ª¥Ö¥¸¥§¥¯¥È¤ò ÂåÆþ¤·¤Æ¤ª¤¡¢const_get ¤Ç¤¬ Ƥ¤¿¤¨Â áõôïìïáä ¤¹¤ë¤Î¤Ç¤Ï ¤É¤¦¤Ç¤·¤ç¤¦¤«¡£ ¤È¤Ã¤¯¤Ë¹Í¤¨¤é¤ì¤Æ¤¤¡¢¤È¤â»×¤Ã¤¿¤Î¤Ç¤¹¤¬¡¢ ¤È¤ê¤¢¤¨¤º ¤¤Æ¤ß¤Þ¤·¤¿¡£¤´¾ÐÍ÷²¼¤µ¤¤¡¨Â áõôïìïáä ºÔïðÍïä¬ ¢ôïðíïä®òâ¤ä module TopMod autoload :SubMod, "topmod/submod.rb" # for TopMod::SubMod end ¤¬ è¤Þ¤¹¡¨Â °Ê²¼¡¢ - ¥µ¥ó¥×¥ë¥¹¥¯¥ê¥×¥È - 1.6.6¤«¤é¤Îº¹Ê¬ ¤òꤍ¤Þ¤¹¡£ -- MOROHOSHI Akihiko --Multipart_Sat_Mar__2_06:38:05_2002-1 Content-Type: application/octet-stream Content-Disposition: attachment; filename="altest.rb" Content-Transfer-Encoding: 7bit ConstA p ConstA # 1 module ModB end p ModB # ModB module Foo autoload :Bar, "foo_bar.rb" end p Foo.const_defined? :Bar # true p Foo::Bar # ./foo_bar.rb is loaded. # Foo::Bar p Foo::Bar::A # 1 begin p Bar::A # (NameError) rescue NameError e puts "Bar::A not found: #{e} (#{e.class})" puts "OK, let's continue...." end autoload :Bar, "bar.rb" p Object.const_defined? :Bar # true p Bar::A # ./bar.rb is loaded. # 2 --Multipart_Sat_Mar__2_06:38:05_2002-1 Content-Type: application/octet-stream Content-Disposition: attachment; filename="foo_bar.rb" Content-Transfer-Encoding: 7bit module Foo class Bar A end end puts "#{__FILE__} is loaded." --Multipart_Sat_Mar__2_06:38:05_2002-1 Content-Type: application/octet-stream Content-Disposition: attachment; filename="bar.rb" Content-Transfer-Encoding: 7bit class Bar A end puts "#{__FILE__} is loaded." --Multipart_Sat_Mar__2_06:38:05_2002-1 Content-Type: application/octet-stream; type=patch Content-Disposition: attachment; filename="ruby-1.6.6-autoload.patch" Content-Transfer-Encoding: 7bit diff -ruN --exclude ext --exclude config* --exclude *.rb --exclude Makefile --exclude *~ --exclude variable.c.* ruby-1.6.6.orig/eval.c ruby-1.6.6/eval.c --- ruby-1.6.6.orig/eval.c Fri Dec 21 18:19:47 2001 +++ ruby-1.6.6/eval.c Sat Mar 2 05:18:26 2002 @@ -3072,9 +3072,6 @@ } klass ; - if ((ruby_class rb_cObject) && rb_autoload_defined(node->nd_cname)) { - rb_autoload_load(node->nd_cname); - } if (rb_const_defined_at(ruby_class, node->nd_cname)) { klass b_const_get(ruby_class, node->nd_cname); } @@ -3118,9 +3115,6 @@ rb_raise(rb_eTypeError, "no outer class/module"); } module ; - if ((ruby_class rb_cObject) && rb_autoload_defined(node->nd_cname)) { - rb_autoload_load(node->nd_cname); - } if (rb_const_defined_at(ruby_class, node->nd_cname)) { module b_const_get(ruby_class, node->nd_cname); } @@ -6025,8 +6019,6 @@ #endif } -VALUE rb_f_autoload(); - void Init_load() { @@ -6040,7 +6032,6 @@ rb_define_global_function("load", rb_f_load, -1); rb_define_global_function("require", rb_f_require, 1); - rb_define_global_function("autoload", rb_f_autoload, 2); rb_global_variable(&ruby_wrapper); ruby_dln_librefs b_ary_new(); diff -ruN --exclude ext --exclude config* --exclude *.rb --exclude Makefile --exclude *~ --exclude variable.c.* ruby-1.6.6.orig/inits.c ruby-1.6.6/inits.c --- ruby-1.6.6.orig/inits.c Wed Mar 21 17:04:11 2001 +++ ruby-1.6.6/inits.c Sat Mar 2 03:25:36 2002 @@ -13,6 +13,8 @@ #include "ruby.h" void Init_Array _((void)); +void Init_autoload_1 _((void)); +void Init_autoload_2 _((void)); void Init_Bignum _((void)); void Init_Comparable _((void)); void Init_Dir _((void)); @@ -50,6 +52,7 @@ Init_sym(); Init_var_tables(); Init_Object(); + Init_autoload_1(); Init_Comparable(); Init_Enumerable(); Init_Precision(); @@ -72,6 +75,7 @@ Init_signal(); Init_process(); Init_load(); + Init_autoload_2(); Init_Proc(); Init_Math(); Init_GC(); diff -ruN --exclude ext --exclude config* --exclude *.rb --exclude Makefile --exclude *~ --exclude variable.c.* ruby-1.6.6.orig/intern.h ruby-1.6.6/intern.h --- ruby-1.6.6.orig/intern.h Fri Dec 21 18:19:47 2001 +++ ruby-1.6.6/intern.h Sat Mar 2 05:34:47 2002 @@ -352,8 +352,6 @@ void rb_set_class_path _((VALUE, VALUE, const char*)); VALUE rb_path2class _((const char*)); void rb_name_class _((VALUE, ID)); -void rb_autoload _((const char*, const char*)); -VALUE rb_f_autoload _((VALUE, VALUE, VALUE)); void rb_gc_mark_global_tbl _((void)); VALUE rb_f_trace_var _((int, VALUE*)); VALUE rb_f_untrace_var _((int, VALUE*)); @@ -374,14 +372,12 @@ VALUE rb_mod_const_of _((VALUE, VALUE)); VALUE rb_mod_remove_const _((VALUE, VALUE)); int rb_const_defined_at _((VALUE, ID)); -int rb_autoload_defined _((ID)); int rb_const_defined _((VALUE, ID)); VALUE rb_const_get _((VALUE, ID)); VALUE rb_const_get_at _((VALUE, ID)); void rb_const_set _((VALUE, ID, VALUE)); void rb_const_assign _((VALUE, ID, VALUE)); VALUE rb_mod_constants _((VALUE)); -void rb_autoload_load _((ID)); void rb_cvar_declare _((VALUE, ID, VALUE)); VALUE rb_cvar_defined _((VALUE, ID)); void rb_cvar_set _((VALUE, ID, VALUE)); diff -ruN --exclude ext --exclude config* --exclude *.rb --exclude Makefile --exclude *~ --exclude variable.c.* ruby-1.6.6.orig/variable.c ruby-1.6.6/variable.c --- ruby-1.6.6.orig/variable.c Fri Dec 21 18:20:54 2001 +++ ruby-1.6.6/variable.c Sat Mar 2 06:10:21 2002 @@ -242,40 +242,6 @@ rb_iv_set(klass, "__classid__", ID2SYM(id)); } -static st_table *autoload_tbl ; - -static void -rb_autoload_id(id, filename) - ID id; - const char *filename; -{ - rb_secure(4); - if (!rb_is_const_id(id)) { - rb_raise(rb_eNameError, "autoload must be constant name", - rb_id2name(id)); - } - - if (!autoload_tbl) { - autoload_tbl t_init_numtable(); - } - st_insert(autoload_tbl, id, strdup(filename)); -} - -void -rb_autoload(klass, filename) - const char *klass, *filename; -{ - rb_autoload_id(rb_intern(klass), filename); -} - -VALUE -rb_f_autoload(obj, klass, file) - VALUE obj, klass, file; -{ - rb_autoload_id(rb_to_id(klass), STR2CSTR(file)); - return Qnil; -} - char * rb_class2name(klass) VALUE klass; @@ -1029,6 +995,117 @@ return val; } +static VALUE autoload_tbl ; +static VALUE autoload_target ; +#define AUTOLOAD_TARGET autoload_target +#define IS_AUTOLOAD_TARGET(obj) ((obj) utoload_target) +#define AUTOLOAD_KEY_NEW(klass,id) rb_ary_new3(2,klass,ID2SYM(id)) + +static void +autoload_add(VALUE klass, ID id, VALUE file) { + VALUE key; + + rb_secure(4); + Check_SafeStr(file); + if (!rb_is_const_id(id)) { + rb_raise(rb_eNameError, "autoload must be constant name", + rb_id2name(id)); + } + + key UTOLOAD_KEY_NEW(klass, id); + rb_hash_aset(autoload_tbl, key, file); +} + +static VALUE +rb_mod_autoload(VALUE mod, VALUE sym, VALUE file) { + ID id b_to_id(sym); + + if (rb_const_defined_at(mod, id)) + return Qnil; + + rb_const_set(mod, id, AUTOLOAD_TARGET); + autoload_add(mod, id, file); + + return Qnil; +} + +static VALUE +rb_f_autoload(VALUE obj, VALUE sym, VALUE file) { + ID id b_to_id(sym); + + /* I use ruby_class as obj as same as NODE_CDECL, + * assuming autoload is another representation of rb_const_set. + */ + obj uby_class; + + if (rb_const_defined_at(obj, id)) + return Qnil; + + rb_const_set(obj, id, AUTOLOAD_TARGET); + autoload_add(obj, id, file); + + return Qnil; +} + +static void +autoload_delete(VALUE klass, VALUE id) { + VALUE key; + key UTOLOAD_KEY_NEW(klass, id); + rb_funcall(autoload_tbl, rb_intern("delete"), 1, key); +} + +static void +autoload_load(VALUE klass, ID id) { + VALUE key, file; + + if (RCLASS(klass)->iv_tbl) { + VALUE value; + st_delete(ROBJECT(klass)->iv_tbl, &id, &value); + if (! IS_AUTOLOAD_TARGET(value)) + rb_bug("autoload_load: removed normal constant: %s::%s", + rb_class2name(klass), rb_id2name(id)); + } else { + rb_bug("autoload_load: AUTOLOAD_TARGET not found: %s::%s", + rb_class2name(klass), rb_id2name(id)); + } + + key UTOLOAD_KEY_NEW(klass, id); + file b_funcall(autoload_tbl, rb_intern("delete"), 1, key); + + if (NIL_P(file)) { + rb_bug("autoload file not found for %s::%s", + rb_class2name(klass), rb_id2name(id)); + } + + if (rb_provided(RSTRING(file)->ptr)) + return; + + FL_UNSET(file, FL_TAINT); + rb_f_require(Qnil, file); +} + +static VALUE +rb_f_autoload_p(VALUE self, VALUE mod, VALUE sym) { + ID id b_to_id(sym); + return NIL_P(rb_hash_aref(autoload_tbl,AUTOLOAD_KEY_NEW(mod,id))) ? + Qfalse : Qtrue; +} + +void +Init_autoload_1() { + autoload_target b_obj_alloc(rb_cObject); +} + +void +Init_autoload_2() { + autoload_tbl b_hash_new(); + rb_global_variable(&autoload_tbl); + + rb_define_method(rb_cModule, "autoload", rb_mod_autoload, 2); + rb_define_global_function("autoload", rb_f_autoload, 2); + rb_define_global_function("autoload?", rb_f_autoload_p, 2); +} + static int top_const_get(id, klassp) ID id; @@ -1039,12 +1116,6 @@ /* pre-defined class */ if (st_lookup(rb_class_tbl, id, klassp)) return Qtrue; - /* autoload */ - if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) { - rb_autoload_load(id); - *klassp b_const_get(rb_cObject, id); - return Qtrue; - } return Qfalse; } @@ -1055,7 +1126,12 @@ { VALUE value; +retry: if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, &value)) { + if (IS_AUTOLOAD_TARGET(value)) { + autoload_load(klass, id); + goto retry; + } return value; } if (klass rb_cObject && top_const_get(id, &value)) { @@ -1067,22 +1143,24 @@ return Qnil; /* not reached */ } -void -rb_autoload_load(id) - ID id; -{ - char *modname; - VALUE module; - - st_delete(autoload_tbl, &id, &modname); - if (rb_provided(modname)) { - free(modname); - return; - } - module b_str_new2(modname); - free(modname); - FL_UNSET(module, FL_TAINT); - rb_f_require(Qnil, module); +/* for debugging purpose. */ +static char buf[1024]; +const char * +print_class_id(VALUE klass, VALUE id) { + const char *ptr ULL; + + buf[0] \0'; + if (RTEST(rb_funcall(klass, rb_intern("kind_of?"), 1, rb_cModule))) { + strcpy(buf, rb_class2name(klass)); + } else { + strcpy(buf, "??"); + } + ptr b_id2name(id); + if (ptr) + strcat(buf, ptr); + else + strcat(buf, "(NULL)"); + return buf; } VALUE @@ -1097,6 +1175,10 @@ retry: while (tmp) { if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) { + if (IS_AUTOLOAD_TARGET(value)) { + autoload_load(tmp,id); + goto retry; + } return value; } if (tmp rb_cObject && top_const_get(id, &value)) return value; @@ -1125,6 +1207,7 @@ VALUE value; VALUE ary; { + /* autoload consideration: include. */ if (rb_is_const_id(key)) { VALUE kval b_str_new2(rb_id2name(key)); if (!rb_ary_includes(ary, kval)) { @@ -1149,7 +1232,14 @@ if (OBJ_FROZEN(mod)) rb_error_frozen("class/module"); if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, &id, &val)) { - return val; + if (IS_AUTOLOAD_TARGET(val)) { + /* cancel autoload and go through. + * + * XXX - should we do autoload and retry? + */ + } else { + return val; + } } if (rb_const_defined_at(mod, id)) { rb_raise(rb_eNameError, "cannot remove %s::%s", @@ -1160,19 +1250,6 @@ return Qnil; /* not reached */ } -static int -autoload_i(key, name, ary) - ID key; - const char *name; - VALUE ary; -{ - VALUE kval b_str_new2(rb_id2name(key)); - if (!rb_ary_includes(ary, kval)) { - rb_ary_push(ary, kval); - } - return ST_CONTINUE; -} - VALUE rb_mod_const_at(mod, ary) VALUE mod, ary; @@ -1182,9 +1259,6 @@ } if ((VALUE)mod rb_cObject) { st_foreach(rb_class_tbl, sv_i, ary); - if (autoload_tbl) { - st_foreach(autoload_tbl, autoload_i, ary); - } } return ary; } @@ -1214,6 +1288,7 @@ VALUE klass; ID id; { + /* autoload consideration: include. */ if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, 0)) { return Qtrue; } @@ -1224,21 +1299,13 @@ } int -rb_autoload_defined(id) - ID id; -{ - if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) - return Qtrue; - return Qfalse; -} - -int rb_const_defined(klass, id) VALUE klass; ID id; { VALUE tmp lass; + /* autoload consideration: include. */ while (tmp) { if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) { return Qtrue; @@ -1250,7 +1317,7 @@ } if (st_lookup(rb_class_tbl, id, 0)) return Qtrue; - return rb_autoload_defined(id); + return Qfalse; } static void @@ -1269,8 +1336,12 @@ RCLASS(klass)->iv_tbl t_init_numtable(); } else if (isconst) { - if (st_lookup(RCLASS(klass)->iv_tbl, id, 0) || - (klass rb_cObject && st_lookup(rb_class_tbl, id, 0))) { + VALUE value; + if (st_lookup(RCLASS(klass)->iv_tbl, id, &value)) { + if (IS_AUTOLOAD_TARGET(value)) + autoload_delete(klass, id); + rb_warn("already initialized %s %s", dest, rb_id2name(id)); + } else if (klass rb_cObject && st_lookup(rb_class_tbl, id, 0)) { rb_warn("already initialized %s %s", dest, rb_id2name(id)); } } @@ -1295,8 +1366,14 @@ { VALUE tmp lass; +retry: while (tmp) { - if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) { + VALUE value; + if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) { + if (IS_AUTOLOAD_TARGET(value)) { + autoload_load(tmp,id); + goto retry; + } st_insert(RCLASS(tmp)->iv_tbl, id, val); return; } @@ -1305,16 +1382,6 @@ /* pre-defined class */ if (st_lookup(rb_class_tbl, id, 0)) { st_delete(rb_class_tbl, id, 0); - st_insert(RCLASS(rb_cObject)->iv_tbl, id, val); - return; - } - - /* autoload */ - if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) { - char *modname; - - st_delete(autoload_tbl, &id, &modname); - free(modname); st_insert(RCLASS(rb_cObject)->iv_tbl, id, val); return; } --Multipart_Sat_Mar__2_06:38:05_2002-1--