mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* variable.c (rb_cvar_set): check whether class variable is
defined in superclasses. root classes have higher priority. removes lower class variable entry from IV_TBL (if it's defined in classes, not modules). * variable.c (rb_cvar_get): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13604 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
ee2ac58e4d
commit
91a079cc86
3 changed files with 77 additions and 16 deletions
|
@ -1,3 +1,12 @@
|
||||||
|
Wed Oct 3 15:43:15 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
|
* variable.c (rb_cvar_set): check whether class variable is
|
||||||
|
defined in superclasses. root classes have higher priority.
|
||||||
|
removes lower class variable entry from IV_TBL (if it's defined
|
||||||
|
in classes, not modules).
|
||||||
|
|
||||||
|
* variable.c (rb_cvar_get): ditto.
|
||||||
|
|
||||||
Wed Oct 3 10:06:53 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Wed Oct 3 10:06:53 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* ruby.c (ruby_process_options): push frame with program name.
|
* ruby.c (ruby_process_options): push frame with program name.
|
||||||
|
|
|
@ -25,7 +25,7 @@ class TestVariable < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
class Titans < Gods
|
class Titans < Gods
|
||||||
@@rule = "Cronus" # do not affect @@rule in Gods
|
@@rule = "Cronus" # modifies @@rule in Gods
|
||||||
include Olympians
|
include Olympians
|
||||||
def ruler4
|
def ruler4
|
||||||
@@rule
|
@@rule
|
||||||
|
@ -44,13 +44,13 @@ class TestVariable < Test::Unit::TestCase
|
||||||
$_ = foobar
|
$_ = foobar
|
||||||
assert_equal(foobar, $_)
|
assert_equal(foobar, $_)
|
||||||
|
|
||||||
assert_equal("Uranus", Gods.new.ruler0)
|
assert_equal("Cronus", Gods.new.ruler0)
|
||||||
assert_equal("Uranus", Gods.ruler1)
|
assert_equal("Cronus", Gods.ruler1)
|
||||||
assert_equal("Uranus", Gods.ruler2)
|
assert_equal("Cronus", Gods.ruler2)
|
||||||
assert_equal("Uranus", Titans.ruler1)
|
assert_equal("Cronus", Titans.ruler1)
|
||||||
assert_equal("Uranus", Titans.ruler2)
|
assert_equal("Cronus", Titans.ruler2)
|
||||||
atlas = Titans.new
|
atlas = Titans.new
|
||||||
assert_equal("Uranus", atlas.ruler0)
|
assert_equal("Cronus", atlas.ruler0)
|
||||||
assert_equal("Zeus", atlas.ruler3)
|
assert_equal("Zeus", atlas.ruler3)
|
||||||
assert_equal("Cronus", atlas.ruler4)
|
assert_equal("Cronus", atlas.ruler4)
|
||||||
end
|
end
|
||||||
|
|
66
variable.c
66
variable.c
|
@ -1701,15 +1701,53 @@ rb_define_global_const(const char *name, VALUE val)
|
||||||
rb_define_const(rb_cObject, name, val);
|
rb_define_const(rb_cObject, name, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
original_module(c)
|
||||||
|
VALUE c;
|
||||||
|
{
|
||||||
|
if (TYPE(c) == T_ICLASS)
|
||||||
|
return RBASIC(c)->klass;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_cvar_set(VALUE klass, ID id, VALUE val)
|
rb_cvar_set(VALUE klass, ID id, VALUE val)
|
||||||
{
|
{
|
||||||
mod_av_set(klass, id, val, Qfalse);
|
VALUE tmp;
|
||||||
|
VALUE front = 0, target = 0;
|
||||||
|
|
||||||
|
tmp = klass;
|
||||||
|
while (tmp) {
|
||||||
|
if (RCLASS_IV_TBL(tmp) && st_lookup(RCLASS_IV_TBL(tmp),id,0)) {
|
||||||
|
if (!front) front = tmp;
|
||||||
|
target = tmp;
|
||||||
|
}
|
||||||
|
tmp = RCLASS_SUPER(tmp);
|
||||||
|
}
|
||||||
|
if (target) {
|
||||||
|
if (front && target != front) {
|
||||||
|
ID did = id;
|
||||||
|
|
||||||
|
if (RTEST(ruby_verbose)) {
|
||||||
|
rb_warning("class variable %s of %s is overtaken by %s",
|
||||||
|
rb_id2name(id), rb_class2name(original_module(front)),
|
||||||
|
rb_class2name(original_module(target)));
|
||||||
|
}
|
||||||
|
if (BUILTIN_TYPE(front) == T_CLASS) {
|
||||||
|
st_delete(RCLASS_IV_TBL(front),&did,0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
target = klass;
|
||||||
|
}
|
||||||
|
|
||||||
|
mod_av_set(target, id, val, Qfalse);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CVAR_LOOKUP(v,r) do {\
|
#define CVAR_LOOKUP(v,r) do {\
|
||||||
if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),id,(v))) {\
|
if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),id,(v))) {\
|
||||||
return (r);\
|
r;\
|
||||||
}\
|
}\
|
||||||
if (FL_TEST(klass, FL_SINGLETON) ) {\
|
if (FL_TEST(klass, FL_SINGLETON) ) {\
|
||||||
VALUE obj = rb_iv_get(klass, "__attached__");\
|
VALUE obj = rb_iv_get(klass, "__attached__");\
|
||||||
|
@ -1728,7 +1766,7 @@ rb_cvar_set(VALUE klass, ID id, VALUE val)
|
||||||
}\
|
}\
|
||||||
while (klass) {\
|
while (klass) {\
|
||||||
if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),id,(v))) {\
|
if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),id,(v))) {\
|
||||||
return (r);\
|
r;\
|
||||||
}\
|
}\
|
||||||
klass = RCLASS_SUPER(klass);\
|
klass = RCLASS_SUPER(klass);\
|
||||||
}\
|
}\
|
||||||
|
@ -1737,20 +1775,34 @@ rb_cvar_set(VALUE klass, ID id, VALUE val)
|
||||||
VALUE
|
VALUE
|
||||||
rb_cvar_get(VALUE klass, ID id)
|
rb_cvar_get(VALUE klass, ID id)
|
||||||
{
|
{
|
||||||
VALUE value, tmp;
|
VALUE value, tmp, front = 0, target = 0;
|
||||||
|
|
||||||
tmp = klass;
|
tmp = klass;
|
||||||
CVAR_LOOKUP(&value, value);
|
CVAR_LOOKUP(&value, {if (!front) front = klass; target = klass;});
|
||||||
|
if (!target) {
|
||||||
rb_name_error(id,"uninitialized class variable %s in %s",
|
rb_name_error(id,"uninitialized class variable %s in %s",
|
||||||
rb_id2name(id), rb_class2name(tmp));
|
rb_id2name(id), rb_class2name(tmp));
|
||||||
return Qnil; /* not reached */
|
}
|
||||||
|
if (front && target != front) {
|
||||||
|
ID did = id;
|
||||||
|
|
||||||
|
if (RTEST(ruby_verbose)) {
|
||||||
|
rb_warning("class variable %s of %s is overtaken by %s",
|
||||||
|
rb_id2name(id), rb_class2name(original_module(front)),
|
||||||
|
rb_class2name(original_module(target)));
|
||||||
|
}
|
||||||
|
if (BUILTIN_TYPE(front) == T_CLASS) {
|
||||||
|
st_delete(RCLASS_IV_TBL(front),&did,0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_cvar_defined(VALUE klass, ID id)
|
rb_cvar_defined(VALUE klass, ID id)
|
||||||
{
|
{
|
||||||
if (!klass) return Qfalse;
|
if (!klass) return Qfalse;
|
||||||
CVAR_LOOKUP(0,Qtrue);
|
CVAR_LOOKUP(0,return Qtrue);
|
||||||
return Qfalse;
|
return Qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue