1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* eval.c (ev_const_defined, ev_const_get), variable.c

(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
  as autoload marker.  [ruby-dev:18103], [ruby-dev:18184]

* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
  Module#autoload, Module#autoload?.

* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
  manage autoload constants per classes/modules.

* variable.c (rb_const_defined_at, rb_const_defined): return false
  for autoloading constants.

* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
  variable.c (rb_mod_const_at, rb_const_assign): removed autoload
  stuff.

* intern.h: prototypes; rb_autoload, rb_autoload_load,
  rb_autoload_p.

* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
  do not treat unmatched argument as an option.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2003-05-29 00:11:11 +00:00
parent 144caca6bb
commit 5ddce4f7bc
6 changed files with 287 additions and 156 deletions

View file

@ -1,3 +1,30 @@
Thu May 29 09:11:01 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net>
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
Thu May 29 09:11:01 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net>
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
Tue May 27 20:33:18 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net> Tue May 27 20:33:18 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net>
* eval.c, util.c: removed duplicated includes/defines. * eval.c, util.c: removed duplicated includes/defines.

View file

@ -198,9 +198,6 @@ rb_define_class(name, super)
ID id; ID id;
id = rb_intern(name); id = rb_intern(name);
if (rb_autoload_defined(id)) {
rb_autoload_load(id);
}
if (rb_const_defined(rb_cObject, id)) { if (rb_const_defined(rb_cObject, id)) {
klass = rb_const_get(rb_cObject, id); klass = rb_const_get(rb_cObject, id);
if (TYPE(klass) != T_CLASS) { if (TYPE(klass) != T_CLASS) {
@ -287,9 +284,6 @@ rb_define_module(name)
ID id; ID id;
id = rb_intern(name); id = rb_intern(name);
if (rb_autoload_defined(id)) {
rb_autoload_load(id);
}
if (rb_const_defined(rb_cObject, id)) { if (rb_const_defined(rb_cObject, id)) {
module = rb_const_get(rb_cObject, id); module = rb_const_get(rb_cObject, id);
if (TYPE(module) == T_MODULE) if (TYPE(module) == T_MODULE)

61
eval.c
View file

@ -1648,12 +1648,16 @@ ev_const_defined(cref, id, self)
VALUE self; VALUE self;
{ {
NODE *cbase = cref; NODE *cbase = cref;
VALUE result;
while (cbase && cbase->nd_next) { while (cbase && cbase->nd_next) {
struct RClass *klass = RCLASS(cbase->nd_clss); struct RClass *klass = RCLASS(cbase->nd_clss);
if (NIL_P(klass)) return rb_const_defined(CLASS_OF(self), id); if (NIL_P(klass)) return rb_const_defined(CLASS_OF(self), id);
if (klass->iv_tbl && st_lookup(klass->iv_tbl, id, 0)) { if (klass->iv_tbl && st_lookup(klass->iv_tbl, id, &result)) {
if (result == Qundef && NIL_P(rb_autoload_p((VALUE)klass, id))) {
return Qfalse;
}
return Qtrue; return Qtrue;
} }
cbase = cbase->nd_next; cbase = cbase->nd_next;
@ -1674,7 +1678,11 @@ ev_const_get(cref, id, self)
VALUE klass = cbase->nd_clss; VALUE klass = cbase->nd_clss;
if (NIL_P(klass)) return rb_const_get(CLASS_OF(self), id); if (NIL_P(klass)) return rb_const_get(CLASS_OF(self), id);
if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, &result)) { while (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, &result)) {
if (result == Qundef) {
rb_autoload_load(klass, id);
continue;
}
return result; return result;
} }
cbase = cbase->nd_next; cbase = cbase->nd_next;
@ -3502,9 +3510,6 @@ rb_eval(self, n)
cbase = class_prefix(self, node->nd_cpath); cbase = class_prefix(self, node->nd_cpath);
cname = node->nd_cpath->nd_mid; cname = node->nd_cpath->nd_mid;
if ((cbase == rb_cObject) && rb_autoload_defined(cname)) {
rb_autoload_load(cname);
}
if (rb_const_defined_at(cbase, cname)) { if (rb_const_defined_at(cbase, cname)) {
klass = rb_const_get(cbase, cname); klass = rb_const_get(cbase, cname);
if (TYPE(klass) != T_CLASS) { if (TYPE(klass) != T_CLASS) {
@ -3548,9 +3553,6 @@ rb_eval(self, n)
} }
cbase = class_prefix(self, node->nd_cpath); cbase = class_prefix(self, node->nd_cpath);
cname = node->nd_cpath->nd_mid; cname = node->nd_cpath->nd_mid;
if ((cbase == rb_cObject) && rb_autoload_defined(cname)) {
rb_autoload_load(cname);
}
if (rb_const_defined_at(cbase, cname)) { if (rb_const_defined_at(cbase, cname)) {
module = rb_const_get(cbase, cname); module = rb_const_get(cbase, cname);
if (TYPE(module) != T_MODULE) { if (TYPE(module) != T_MODULE) {
@ -6512,7 +6514,43 @@ Init_eval()
rb_define_virtual_variable("$SAFE", safe_getter, safe_setter); rb_define_virtual_variable("$SAFE", safe_getter, safe_setter);
} }
VALUE rb_f_autoload(); static VALUE
rb_mod_autoload(mod, sym, file)
VALUE mod;
VALUE sym;
VALUE file;
{
ID id = rb_to_id(sym);
Check_SafeStr(file);
rb_autoload(mod, id, RSTRING(file)->ptr);
return Qnil;
}
static VALUE
rb_mod_autoload_p(mod, sym)
VALUE mod, sym;
{
return rb_autoload_p(mod, rb_to_id(sym));
}
static VALUE
rb_f_autoload(obj, sym, file)
VALUE obj;
VALUE sym;
VALUE file;
{
return rb_mod_autoload(ruby_class, sym, file);
}
static VALUE
rb_f_autoload_p(obj, sym)
VALUE obj;
VALUE sym;
{
/* use ruby_class as same as rb_f_autoload. */
return rb_mod_autoload_p(ruby_class, sym);
}
void void
Init_load() Init_load()
@ -6527,7 +6565,10 @@ Init_load()
rb_define_global_function("load", rb_f_load, -1); rb_define_global_function("load", rb_f_load, -1);
rb_define_global_function("require", rb_f_require, 1); rb_define_global_function("require", rb_f_require, 1);
rb_define_global_function("autoload", rb_f_autoload, 2); rb_define_method(rb_cModule, "autoload", rb_mod_autoload, 2);
rb_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, 1);
rb_define_global_function("autoload", rb_f_autoload, 2);
rb_define_global_function("autoload?", rb_f_autoload_p, 1);
rb_global_variable(&ruby_wrapper); rb_global_variable(&ruby_wrapper);
ruby_dln_librefs = rb_ary_new(); ruby_dln_librefs = rb_ary_new();

View file

@ -424,8 +424,9 @@ VALUE rb_class_path _((VALUE));
void rb_set_class_path _((VALUE, VALUE, const char*)); void rb_set_class_path _((VALUE, VALUE, const char*));
VALUE rb_path2class _((const char*)); VALUE rb_path2class _((const char*));
void rb_name_class _((VALUE, ID)); void rb_name_class _((VALUE, ID));
void rb_autoload _((const char*, const char*)); void rb_autoload _((VALUE, ID, const char*));
VALUE rb_f_autoload _((VALUE, VALUE, VALUE)); void rb_autoload_load _((VALUE, ID));
VALUE rb_autoload_p _((VALUE, ID));
void rb_gc_mark_global_tbl _((void)); void rb_gc_mark_global_tbl _((void));
VALUE rb_f_trace_var _((int, VALUE*)); VALUE rb_f_trace_var _((int, VALUE*));
VALUE rb_f_untrace_var _((int, VALUE*)); VALUE rb_f_untrace_var _((int, VALUE*));
@ -450,14 +451,12 @@ VALUE rb_const_list _((void*));
VALUE rb_mod_constants _((VALUE)); VALUE rb_mod_constants _((VALUE));
VALUE rb_mod_remove_const _((VALUE, VALUE)); VALUE rb_mod_remove_const _((VALUE, VALUE));
int rb_const_defined_at _((VALUE, ID)); int rb_const_defined_at _((VALUE, ID));
int rb_autoload_defined _((ID));
int rb_const_defined _((VALUE, ID)); int rb_const_defined _((VALUE, ID));
VALUE rb_const_get _((VALUE, ID)); VALUE rb_const_get _((VALUE, ID));
VALUE rb_const_get_at _((VALUE, ID)); VALUE rb_const_get_at _((VALUE, ID));
void rb_const_set _((VALUE, ID, VALUE)); void rb_const_set _((VALUE, ID, VALUE));
void rb_const_assign _((VALUE, ID, VALUE)); void rb_const_assign _((VALUE, ID, VALUE));
VALUE rb_mod_constants _((VALUE)); VALUE rb_mod_constants _((VALUE));
void rb_autoload_load _((ID));
VALUE rb_cvar_defined _((VALUE, ID)); VALUE rb_cvar_defined _((VALUE, ID));
#define RB_CVAR_SET_4ARGS 1 #define RB_CVAR_SET_4ARGS 1
void rb_cvar_set _((VALUE, ID, VALUE, int)); void rb_cvar_set _((VALUE, ID, VALUE, int));

View file

@ -223,7 +223,7 @@ Individual switch class.
def parse(arg, *val) def parse(arg, *val)
if block if block
val = conv.call(*val) if conv val = conv.call(*val) if conv
return arg, block, val return arg, block, *val
else else
return arg, nil return arg, nil
end end
@ -343,11 +343,17 @@ Switch that can omit argument.
class PlacedArgument < self class PlacedArgument < self
def parse(arg, argv, &error) def parse(arg, argv, &error)
unless arg if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
return nil, block, nil if argv.empty? or /\A-/ =~ argv[0] return nil, block, nil
arg = argv.shift
end end
super(*parse_arg(arg, &error)) if (val = parse_arg(val, &error))[1]
arg = nil
else
val[0] = arg
end
*val = super(*val)
argv.shift unless arg
val
end end
end end
end end
@ -1116,8 +1122,8 @@ Default options, which never appear in option summary.
raise $!.set_option(arg, true) raise $!.set_option(arg, true)
end end
begin begin
opt, sw, val = sw.parse(rest, argv) {|*exc| raise(*exc)} opt, sw, *val = sw.parse(rest, argv) {|*exc| raise(*exc)}
sw.call(val) if sw sw.call(*val) if sw
rescue ParseError rescue ParseError
raise $!.set_option(arg, rest) raise $!.set_option(arg, rest)
end end
@ -1143,10 +1149,10 @@ Default options, which never appear in option summary.
raise $!.set_option(arg, true) raise $!.set_option(arg, true)
end end
begin begin
opt, sw, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq} opt, sw, *val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}" raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}"
argv.unshift(opt) if opt and (opt = opt.sub(/\A-*/, '-')) != '-' argv.unshift(opt) if opt and (opt = opt.sub(/\A-*/, '-')) != '-'
sw.call(val) if sw sw.call(*val) if sw
rescue ParseError rescue ParseError
raise $!.set_option(arg, has_arg) raise $!.set_option(arg, has_arg)
end end

View file

@ -20,12 +20,14 @@
static st_table *rb_global_tbl; static st_table *rb_global_tbl;
st_table *rb_class_tbl; st_table *rb_class_tbl;
static ID autoload;
void void
Init_var_tables() Init_var_tables()
{ {
rb_global_tbl = st_init_numtable(); rb_global_tbl = st_init_numtable();
rb_class_tbl = st_init_numtable(); rb_class_tbl = st_init_numtable();
autoload = rb_intern("__autoload__");
} }
struct fc_result { struct fc_result {
@ -104,7 +106,6 @@ fc_i(key, value, res)
default: default:
break; break;
} }
return ST_CONTINUE; return ST_CONTINUE;
} }
@ -129,7 +130,7 @@ find_class_path(klass)
if (arg.path) { if (arg.path) {
if (!ROBJECT(klass)->iv_tbl) { if (!ROBJECT(klass)->iv_tbl) {
ROBJECT(klass)->iv_tbl = st_init_numtable(); ROBJECT(klass)->iv_tbl = st_init_numtable();
} }
st_insert(ROBJECT(klass)->iv_tbl,rb_intern("__classpath__"),arg.path); st_insert(ROBJECT(klass)->iv_tbl,rb_intern("__classpath__"),arg.path);
return arg.path; return arg.path;
} }
@ -278,39 +279,6 @@ rb_name_class(klass, id)
rb_iv_set(klass, "__classid__", ID2SYM(id)); rb_iv_set(klass, "__classid__", ID2SYM(id));
} }
static st_table *autoload_tbl = 0;
static void
rb_autoload_id(id, filename)
ID id;
const char *filename;
{
rb_secure(4);
if (!rb_is_const_id(id)) {
rb_name_error(id, "autoload must be constant name");
}
if (!autoload_tbl) {
autoload_tbl = st_init_numtable();
}
st_insert(autoload_tbl, id, (st_data_t)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), StringValuePtr(file));
return Qnil;
}
char * char *
rb_class2name(klass) rb_class2name(klass)
VALUE klass; VALUE klass;
@ -669,7 +637,7 @@ struct trace_data {
struct trace_var *trace; struct trace_var *trace;
VALUE val; VALUE val;
}; };
static VALUE static VALUE
trace_ev(data) trace_ev(data)
struct trace_data *data; struct trace_data *data;
@ -1133,6 +1101,158 @@ rb_obj_remove_instance_variable(obj, name)
return Qnil; /* not reached */ return Qnil; /* not reached */
} }
NORETURN(static void uninitialized_constant _((VALUE, ID)));
static void
uninitialized_constant(klass, id)
VALUE klass;
ID id;
{
if (klass && klass != rb_cObject)
rb_name_error(id, "uninitialized constant %s::%s",
RSTRING(rb_class_path(klass))->ptr,
rb_id2name(id));
else {
rb_name_error(id, "uninitialized constant %s",rb_id2name(id));
}
}
static struct st_table *
check_autoload_table(av)
VALUE av;
{
struct st_table *tbl;
Check_Type(av, T_DATA);
if (RDATA(av)->dmark != (RUBY_DATA_FUNC)rb_mark_tbl ||
RDATA(av)->dfree != (RUBY_DATA_FUNC)st_free_table) {
rb_raise(rb_eTypeError, "wrong autoload table: %s", RSTRING(rb_inspect(av))->ptr);
}
return (struct st_table *)DATA_PTR(av);
}
void
rb_autoload(mod, id, file)
VALUE mod;
ID id;
const char *file;
{
VALUE av;
struct st_table *tbl;
if (!rb_is_const_id(id)) {
rb_raise(rb_eNameError, "autoload must be constant name",
rb_id2name(id));
}
if (!file || !*file) {
rb_raise(rb_eArgError, "empty file name");
}
if ((tbl = RCLASS(mod)->iv_tbl) && st_lookup(tbl, id, &av) && av != Qundef)
return;
rb_const_set(mod, id, Qundef);
tbl = RCLASS(mod)->iv_tbl;
if (st_lookup(tbl, autoload, &av)) {
tbl = check_autoload_table(av);
}
else {
av = Data_Wrap_Struct(rb_cData, rb_mark_tbl, st_free_table, 0);
st_add_direct(tbl, autoload, av);
DATA_PTR(av) = tbl = st_init_numtable();
}
st_insert(tbl, id, rb_str_new2(file));
}
static VALUE
autoload_delete(mod, id)
VALUE mod;
ID id;
{
VALUE val, file = Qnil;
if (st_lookup(RCLASS(mod)->iv_tbl, autoload, &val)) {
struct st_table *tbl = check_autoload_table(val);
if (!st_delete(tbl, &id, &file)) file = Qnil;
if (!tbl->num_entries) {
DATA_PTR(val) = 0;
st_free_table(tbl);
id = autoload;
if (st_delete(RCLASS(mod)->iv_tbl, &id, &val)) {
rb_gc_force_recycle(val);
}
}
}
return file;
}
void
rb_autoload_load(klass, id)
VALUE klass;
ID id;
{
VALUE file, value;
file = autoload_delete(klass, id);
if (NIL_P(file)) {
uninitialized_constant(klass, id);
}
if (rb_provided(RSTRING(file)->ptr)) {
uninitialized_constant(klass, id);
}
FL_UNSET(file, FL_TAINT);
rb_f_require(Qnil, file);
}
static VALUE
autoload_file(mod, id)
VALUE mod;
ID id;
{
VALUE val, file;
struct st_table *tbl;
if (!st_lookup(RCLASS(mod)->iv_tbl, autoload, &val) ||
!(tbl = check_autoload_table(val)) || !st_lookup(tbl, id, &file)) {
return Qnil;
}
Check_Type(file, T_STRING);
if (!RSTRING(file)->ptr) {
rb_raise(rb_eArgError, "empty file name");
}
if (!rb_provided(RSTRING(file)->ptr)) {
return file;
}
/* already loaded but not defined */
st_delete(tbl, &id, 0);
if (!tbl->num_entries) {
DATA_PTR(val) = 0;
st_free_table(tbl);
id = autoload;
if (st_delete(RCLASS(mod)->iv_tbl, &id, &val)) {
rb_gc_force_recycle(val);
}
}
return Qnil;
}
VALUE
rb_autoload_p(mod, id)
VALUE mod;
ID id;
{
struct st_table *tbl = RCLASS(mod)->iv_tbl;
VALUE val;
if (!tbl || !st_lookup(tbl, id, &val) || val != Qundef) {
return Qnil;
}
return autoload_file(mod, id);
}
static int static int
top_const_get(id, klassp) top_const_get(id, klassp)
ID id; ID id;
@ -1140,13 +1260,6 @@ top_const_get(id, klassp)
{ {
/* pre-defined class */ /* pre-defined class */
if (st_lookup(rb_class_tbl, id, klassp)) return Qtrue; 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 = rb_const_get(rb_cObject, id);
return Qtrue;
}
return Qfalse; return Qfalse;
} }
@ -1157,36 +1270,20 @@ rb_const_get_at(klass, id)
{ {
VALUE value; VALUE value;
if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, &value)) { while (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, &value)) {
if (value == Qundef) {
rb_autoload_load(klass, id);
continue;
}
return value; return value;
} }
if (klass == rb_cObject && top_const_get(id, &value)) { if (klass == rb_cObject && top_const_get(id, &value)) {
return value; return value;
} }
rb_name_error(id, "uninitialized constant %s::%s", uninitialized_constant(klass, id);
RSTRING(rb_class_path(klass))->ptr,
rb_id2name(id));
return Qnil; /* not reached */ return Qnil; /* not reached */
} }
void
rb_autoload_load(id)
ID id;
{
char *modname;
VALUE module;
st_delete(autoload_tbl, &id, (st_data_t *)&modname);
if (rb_provided(modname)) {
free(modname);
return;
}
module = rb_str_new2(modname);
free(modname);
FL_UNSET(module, FL_TAINT);
rb_f_require(Qnil, module);
}
VALUE VALUE
rb_const_get(klass, id) rb_const_get(klass, id)
VALUE klass; VALUE klass;
@ -1198,7 +1295,11 @@ rb_const_get(klass, id)
tmp = klass; tmp = klass;
retry: retry:
while (tmp) { while (tmp) {
if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) { while (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) {
if (value == Qundef) {
rb_autoload_load(tmp, id);
continue;
}
return value; return value;
} }
if (tmp == rb_cObject && top_const_get(id, &value)) return value; if (tmp == rb_cObject && top_const_get(id, &value)) return value;
@ -1210,15 +1311,7 @@ rb_const_get(klass, id)
goto retry; goto retry;
} }
/* Uninitialized constant */ uninitialized_constant(klass, id);
if (klass && klass != rb_cObject) {
rb_name_error(id, "uninitialized constant %s at %s",
rb_id2name(id),
RSTRING(rb_class_path(klass))->ptr);
}
else { /* global_uninitialized */
rb_name_error(id, "uninitialized constant %s",rb_id2name(id));
}
return Qnil; /* not reached */ return Qnil; /* not reached */
} }
@ -1237,13 +1330,14 @@ rb_mod_remove_const(mod, name)
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module"); if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, &id, &val)) { if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, &id, &val)) {
if (val == Qundef) autoload_delete(mod, id);
return val; return val;
} }
if (rb_const_defined_at(mod, id)) { if (rb_const_defined_at(mod, id)) {
rb_name_error(id, "cannot remove %s::%s", rb_name_error(id, "cannot remove %s::%s",
rb_class2name(mod), rb_id2name(id)); rb_class2name(mod), rb_id2name(id));
} }
rb_name_error(id, "constant %s::%s not defined", rb_name_error(id, "constant %s::%s not defined",
rb_class2name(mod), rb_id2name(id)); rb_class2name(mod), rb_id2name(id));
return Qnil; /* not reached */ return Qnil; /* not reached */
} }
@ -1262,18 +1356,6 @@ sv_i(key, value, tbl)
return ST_CONTINUE; return ST_CONTINUE;
} }
static int
autoload_i(key, name, tbl)
ID key;
const char *name;
st_table *tbl;
{
if (!st_lookup(tbl, key, 0)) {
st_insert(tbl, key, key);
}
return ST_CONTINUE;
}
void* void*
rb_mod_const_at(mod, data) rb_mod_const_at(mod, data)
VALUE mod; VALUE mod;
@ -1288,9 +1370,6 @@ rb_mod_const_at(mod, data)
} }
if ((VALUE)mod == rb_cObject) { if ((VALUE)mod == rb_cObject) {
st_foreach(rb_class_tbl, sv_i, (st_data_t)tbl); st_foreach(rb_class_tbl, sv_i, (st_data_t)tbl);
if (autoload_tbl) {
st_foreach(autoload_tbl, autoload_i, (st_data_t)tbl);
}
} }
return tbl; return tbl;
} }
@ -1344,7 +1423,11 @@ rb_const_defined_at(klass, id)
VALUE klass; VALUE klass;
ID id; ID id;
{ {
if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, 0)) { VALUE value;
if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, &value)) {
if (value == Qundef && NIL_P(autoload_file(klass, id)))
return Qfalse;
return Qtrue; return Qtrue;
} }
if (klass == rb_cObject) { if (klass == rb_cObject) {
@ -1353,24 +1436,17 @@ rb_const_defined_at(klass, id)
return Qfalse; return Qfalse;
} }
int
rb_autoload_defined(id)
ID id;
{
if (autoload_tbl && st_lookup(autoload_tbl, id, 0))
return Qtrue;
return Qfalse;
}
int int
rb_const_defined(klass, id) rb_const_defined(klass, id)
VALUE klass; VALUE klass;
ID id; ID id;
{ {
VALUE tmp = klass; VALUE tmp = klass, value;
while (tmp) { while (tmp) {
if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) { if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl, id, &value)) {
if (value == Qundef && NIL_P(autoload_file(klass, id)))
return Qfalse;
return Qtrue; return Qtrue;
} }
tmp = RCLASS(tmp)->super; tmp = RCLASS(tmp)->super;
@ -1380,7 +1456,7 @@ rb_const_defined(klass, id)
} }
if (st_lookup(rb_class_tbl, id, 0)) if (st_lookup(rb_class_tbl, id, 0))
return Qtrue; return Qtrue;
return rb_autoload_defined(id); return Qfalse;
} }
static void static void
@ -1399,9 +1475,14 @@ mod_av_set(klass, id, val, isconst)
RCLASS(klass)->iv_tbl = st_init_numtable(); RCLASS(klass)->iv_tbl = st_init_numtable();
} }
else if (isconst) { else if (isconst) {
if (st_lookup(RCLASS(klass)->iv_tbl, id, 0) || VALUE value = Qfalse;
if (st_lookup(RCLASS(klass)->iv_tbl, id, &value) ||
(klass == rb_cObject && st_lookup(rb_class_tbl, id, 0))) { (klass == rb_cObject && st_lookup(rb_class_tbl, id, 0))) {
rb_warn("already initialized %s %s", dest, rb_id2name(id)); if (value == Qundef)
autoload_delete(klass, id);
else
rb_warn("already initialized %s %s", dest, rb_id2name(id));
} }
} }
@ -1424,7 +1505,7 @@ rb_const_assign(klass, id, val)
VALUE val; VALUE val;
{ {
VALUE tmp = klass; VALUE tmp = klass;
while (tmp) { while (tmp) {
if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) { if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
st_insert(RCLASS(tmp)->iv_tbl, id, val); st_insert(RCLASS(tmp)->iv_tbl, id, val);
@ -1439,24 +1520,7 @@ rb_const_assign(klass, id, val)
return; return;
} }
/* autoload */ uninitialized_constant(klass, id);
if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) {
char *modname;
st_delete(autoload_tbl, (st_data_t *)&id, (st_data_t *)&modname);
free(modname);
st_insert(RCLASS(rb_cObject)->iv_tbl, id, val);
return;
}
/* Uninitialized constant */
if (klass && klass != rb_cObject)
rb_name_error(id, "uninitialized constant %s::%s",
RSTRING(rb_class_path(klass))->ptr,
rb_id2name(id));
else {
rb_name_error(id, "uninitialized constant %s",rb_id2name(id));
}
} }
void void
@ -1672,7 +1736,7 @@ rb_mod_remove_cvar(mod, name)
return val; return val;
} }
if (rb_cvar_defined(mod, id)) { if (rb_cvar_defined(mod, id)) {
rb_name_error(id, "cannot remove %s for %s", rb_name_error(id, "cannot remove %s for %s",
rb_id2name(id), rb_class2name(mod)); rb_id2name(id), rb_class2name(mod));
} }
rb_name_error(id, "class variable %s not defined for %s", rb_name_error(id, "class variable %s not defined for %s",