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:
parent
144caca6bb
commit
5ddce4f7bc
6 changed files with 287 additions and 156 deletions
27
ChangeLog
27
ChangeLog
|
@ -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>
|
||||
|
||||
* eval.c, util.c: removed duplicated includes/defines.
|
||||
|
|
6
class.c
6
class.c
|
@ -198,9 +198,6 @@ rb_define_class(name, super)
|
|||
ID id;
|
||||
|
||||
id = rb_intern(name);
|
||||
if (rb_autoload_defined(id)) {
|
||||
rb_autoload_load(id);
|
||||
}
|
||||
if (rb_const_defined(rb_cObject, id)) {
|
||||
klass = rb_const_get(rb_cObject, id);
|
||||
if (TYPE(klass) != T_CLASS) {
|
||||
|
@ -287,9 +284,6 @@ rb_define_module(name)
|
|||
ID id;
|
||||
|
||||
id = rb_intern(name);
|
||||
if (rb_autoload_defined(id)) {
|
||||
rb_autoload_load(id);
|
||||
}
|
||||
if (rb_const_defined(rb_cObject, id)) {
|
||||
module = rb_const_get(rb_cObject, id);
|
||||
if (TYPE(module) == T_MODULE)
|
||||
|
|
61
eval.c
61
eval.c
|
@ -1648,12 +1648,16 @@ ev_const_defined(cref, id, self)
|
|||
VALUE self;
|
||||
{
|
||||
NODE *cbase = cref;
|
||||
VALUE result;
|
||||
|
||||
while (cbase && cbase->nd_next) {
|
||||
struct RClass *klass = RCLASS(cbase->nd_clss);
|
||||
|
||||
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;
|
||||
}
|
||||
cbase = cbase->nd_next;
|
||||
|
@ -1674,7 +1678,11 @@ ev_const_get(cref, id, self)
|
|||
VALUE klass = cbase->nd_clss;
|
||||
|
||||
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;
|
||||
}
|
||||
cbase = cbase->nd_next;
|
||||
|
@ -3502,9 +3510,6 @@ rb_eval(self, n)
|
|||
|
||||
cbase = class_prefix(self, node->nd_cpath);
|
||||
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)) {
|
||||
klass = rb_const_get(cbase, cname);
|
||||
if (TYPE(klass) != T_CLASS) {
|
||||
|
@ -3548,9 +3553,6 @@ rb_eval(self, n)
|
|||
}
|
||||
cbase = class_prefix(self, node->nd_cpath);
|
||||
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)) {
|
||||
module = rb_const_get(cbase, cname);
|
||||
if (TYPE(module) != T_MODULE) {
|
||||
|
@ -6512,7 +6514,43 @@ Init_eval()
|
|||
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
|
||||
Init_load()
|
||||
|
@ -6527,7 +6565,10 @@ Init_load()
|
|||
|
||||
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_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);
|
||||
|
||||
ruby_dln_librefs = rb_ary_new();
|
||||
|
|
7
intern.h
7
intern.h
|
@ -424,8 +424,9 @@ VALUE rb_class_path _((VALUE));
|
|||
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_autoload _((VALUE, ID, const char*));
|
||||
void rb_autoload_load _((VALUE, ID));
|
||||
VALUE rb_autoload_p _((VALUE, ID));
|
||||
void rb_gc_mark_global_tbl _((void));
|
||||
VALUE rb_f_trace_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_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));
|
||||
VALUE rb_cvar_defined _((VALUE, ID));
|
||||
#define RB_CVAR_SET_4ARGS 1
|
||||
void rb_cvar_set _((VALUE, ID, VALUE, int));
|
||||
|
|
|
@ -223,7 +223,7 @@ Individual switch class.
|
|||
def parse(arg, *val)
|
||||
if block
|
||||
val = conv.call(*val) if conv
|
||||
return arg, block, val
|
||||
return arg, block, *val
|
||||
else
|
||||
return arg, nil
|
||||
end
|
||||
|
@ -343,11 +343,17 @@ Switch that can omit argument.
|
|||
|
||||
class PlacedArgument < self
|
||||
def parse(arg, argv, &error)
|
||||
unless arg
|
||||
return nil, block, nil if argv.empty? or /\A-/ =~ argv[0]
|
||||
arg = argv.shift
|
||||
if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
|
||||
return nil, block, nil
|
||||
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
|
||||
|
@ -1116,8 +1122,8 @@ Default options, which never appear in option summary.
|
|||
raise $!.set_option(arg, true)
|
||||
end
|
||||
begin
|
||||
opt, sw, val = sw.parse(rest, argv) {|*exc| raise(*exc)}
|
||||
sw.call(val) if sw
|
||||
opt, sw, *val = sw.parse(rest, argv) {|*exc| raise(*exc)}
|
||||
sw.call(*val) if sw
|
||||
rescue ParseError
|
||||
raise $!.set_option(arg, rest)
|
||||
end
|
||||
|
@ -1143,10 +1149,10 @@ Default options, which never appear in option summary.
|
|||
raise $!.set_option(arg, true)
|
||||
end
|
||||
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}"
|
||||
argv.unshift(opt) if opt and (opt = opt.sub(/\A-*/, '-')) != '-'
|
||||
sw.call(val) if sw
|
||||
sw.call(*val) if sw
|
||||
rescue ParseError
|
||||
raise $!.set_option(arg, has_arg)
|
||||
end
|
||||
|
|
318
variable.c
318
variable.c
|
@ -20,12 +20,14 @@
|
|||
|
||||
static st_table *rb_global_tbl;
|
||||
st_table *rb_class_tbl;
|
||||
static ID autoload;
|
||||
|
||||
void
|
||||
Init_var_tables()
|
||||
{
|
||||
rb_global_tbl = st_init_numtable();
|
||||
rb_class_tbl = st_init_numtable();
|
||||
autoload = rb_intern("__autoload__");
|
||||
}
|
||||
|
||||
struct fc_result {
|
||||
|
@ -104,7 +106,6 @@ fc_i(key, value, res)
|
|||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
@ -129,7 +130,7 @@ find_class_path(klass)
|
|||
if (arg.path) {
|
||||
if (!ROBJECT(klass)->iv_tbl) {
|
||||
ROBJECT(klass)->iv_tbl = st_init_numtable();
|
||||
}
|
||||
}
|
||||
st_insert(ROBJECT(klass)->iv_tbl,rb_intern("__classpath__"),arg.path);
|
||||
return arg.path;
|
||||
}
|
||||
|
@ -278,39 +279,6 @@ rb_name_class(klass, 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 *
|
||||
rb_class2name(klass)
|
||||
VALUE klass;
|
||||
|
@ -669,7 +637,7 @@ struct trace_data {
|
|||
struct trace_var *trace;
|
||||
VALUE val;
|
||||
};
|
||||
|
||||
|
||||
static VALUE
|
||||
trace_ev(data)
|
||||
struct trace_data *data;
|
||||
|
@ -1133,6 +1101,158 @@ rb_obj_remove_instance_variable(obj, name)
|
|||
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
|
||||
top_const_get(id, klassp)
|
||||
ID id;
|
||||
|
@ -1140,13 +1260,6 @@ top_const_get(id, klassp)
|
|||
{
|
||||
/* 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 = rb_const_get(rb_cObject, id);
|
||||
return Qtrue;
|
||||
}
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
|
@ -1157,36 +1270,20 @@ rb_const_get_at(klass, id)
|
|||
{
|
||||
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;
|
||||
}
|
||||
if (klass == rb_cObject && top_const_get(id, &value)) {
|
||||
return value;
|
||||
}
|
||||
rb_name_error(id, "uninitialized constant %s::%s",
|
||||
RSTRING(rb_class_path(klass))->ptr,
|
||||
rb_id2name(id));
|
||||
uninitialized_constant(klass, id);
|
||||
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
|
||||
rb_const_get(klass, id)
|
||||
VALUE klass;
|
||||
|
@ -1198,7 +1295,11 @@ rb_const_get(klass, id)
|
|||
tmp = klass;
|
||||
retry:
|
||||
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;
|
||||
}
|
||||
if (tmp == rb_cObject && top_const_get(id, &value)) return value;
|
||||
|
@ -1210,15 +1311,7 @@ rb_const_get(klass, id)
|
|||
goto retry;
|
||||
}
|
||||
|
||||
/* Uninitialized constant */
|
||||
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));
|
||||
}
|
||||
uninitialized_constant(klass, id);
|
||||
return Qnil; /* not reached */
|
||||
}
|
||||
|
||||
|
@ -1237,13 +1330,14 @@ rb_mod_remove_const(mod, name)
|
|||
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
|
||||
|
||||
if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, &id, &val)) {
|
||||
if (val == Qundef) autoload_delete(mod, id);
|
||||
return val;
|
||||
}
|
||||
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_name_error(id, "constant %s::%s not defined",
|
||||
rb_name_error(id, "constant %s::%s not defined",
|
||||
rb_class2name(mod), rb_id2name(id));
|
||||
return Qnil; /* not reached */
|
||||
}
|
||||
|
@ -1262,18 +1356,6 @@ sv_i(key, value, tbl)
|
|||
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*
|
||||
rb_mod_const_at(mod, data)
|
||||
VALUE mod;
|
||||
|
@ -1288,9 +1370,6 @@ rb_mod_const_at(mod, data)
|
|||
}
|
||||
if ((VALUE)mod == rb_cObject) {
|
||||
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;
|
||||
}
|
||||
|
@ -1344,7 +1423,11 @@ rb_const_defined_at(klass, id)
|
|||
VALUE klass;
|
||||
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;
|
||||
}
|
||||
if (klass == rb_cObject) {
|
||||
|
@ -1353,24 +1436,17 @@ rb_const_defined_at(klass, id)
|
|||
return Qfalse;
|
||||
}
|
||||
|
||||
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 = klass;
|
||||
VALUE tmp = klass, value;
|
||||
|
||||
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;
|
||||
}
|
||||
tmp = RCLASS(tmp)->super;
|
||||
|
@ -1380,7 +1456,7 @@ rb_const_defined(klass, id)
|
|||
}
|
||||
if (st_lookup(rb_class_tbl, id, 0))
|
||||
return Qtrue;
|
||||
return rb_autoload_defined(id);
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1399,9 +1475,14 @@ mod_av_set(klass, id, val, isconst)
|
|||
RCLASS(klass)->iv_tbl = st_init_numtable();
|
||||
}
|
||||
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))) {
|
||||
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 tmp = klass;
|
||||
|
||||
|
||||
while (tmp) {
|
||||
if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
|
||||
st_insert(RCLASS(tmp)->iv_tbl, id, val);
|
||||
|
@ -1439,24 +1520,7 @@ rb_const_assign(klass, id, val)
|
|||
return;
|
||||
}
|
||||
|
||||
/* autoload */
|
||||
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));
|
||||
}
|
||||
uninitialized_constant(klass, id);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1672,7 +1736,7 @@ rb_mod_remove_cvar(mod, name)
|
|||
return val;
|
||||
}
|
||||
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_name_error(id, "class variable %s not defined for %s",
|
||||
|
|
Loading…
Reference in a new issue