diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2007-02-02 09:47:55 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2007-02-02 09:47:55 +0000 |
commit | d99bcbe583eb9f95022f8bcc51674cbdecf40d3b (patch) | |
tree | 2d424c6f8326ed1c3197d67627e4b60752ae3d2e /variable.c | |
parent | e137ee9ac4019ca0002005ec6d3806c09797250d (diff) | |
download | ruby-d99bcbe583eb9f95022f8bcc51674cbdecf40d3b.tar.gz |
* vm.c (eval_get_cvar_base): destination for class variable access
is now strictly innermost surrounding class or module. warned
if accessed from toplevel.
* variable.c (rb_cvar_get): new class variable look-up scheme:
1) look up in the class. 2) if the class is singleton attached
to a class (i.e. metaclass) then start look up in the attached
class and its ancestors. 3) otherwise, look-up in ancestors of
the class.
* eval.c (cvar_cbase): destination for class variable access is
the class/module that holds the method, or cbase outside of
methods.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11613 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'variable.c')
-rw-r--r-- | variable.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/variable.c b/variable.c index fea78232ed..be94d4314e 100644 --- a/variable.c +++ b/variable.c @@ -1570,26 +1570,50 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) mod_av_set(klass, id, val, Qfalse); } +#define CVAR_LOOKUP(v,r) do {\ + if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl,id,(v))) {\ + return (r);\ + }\ + if (FL_TEST(klass, FL_SINGLETON) ) {\ + VALUE obj = rb_iv_get(klass, "__attached__");\ + switch (TYPE(obj)) {\ + case T_MODULE:\ + case T_CLASS:\ + klass = obj;\ + break;\ + default:\ + klass = RCLASS(klass)->super;\ + break;\ + }\ + }\ + else {\ + klass = RCLASS(klass)->super;\ + }\ + while (klass) {\ + if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl,id,(v))) {\ + return (r);\ + }\ + klass = RCLASS(klass)->super;\ + }\ +} while(0) + VALUE rb_cvar_get(VALUE klass, ID id) { - VALUE value; - - if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl,id,&value)) { - return value; - } + VALUE value, tmp; + tmp = klass; + CVAR_LOOKUP(&value, value); rb_name_error(id,"uninitialized class variable %s in %s", - rb_id2name(id), rb_class2name(klass)); + rb_id2name(id), rb_class2name(tmp)); return Qnil; /* not reached */ } VALUE rb_cvar_defined(VALUE klass, ID id) { - if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl,id,0)) { - return Qtrue; - } + if (!klass) return Qfalse; + CVAR_LOOKUP(0,Qtrue); return Qfalse; } |