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>
* eval.c, util.c: removed duplicated includes/defines.

View file

@ -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
View file

@ -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();

View file

@ -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));

View file

@ -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

View file

@ -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",