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 | 1b7c50a6b849135f4f34a199853ec797ed3b85af (patch) | |
| tree | 2d424c6f8326ed1c3197d67627e4b60752ae3d2e /variable.c | |
| parent | 441c153a6ac3c4d110f43e60dee3bc8a901558ad (diff) | |
| download | ruby-1b7c50a6b849135f4f34a199853ec797ed3b85af.tar.gz ruby-1b7c50a6b849135f4f34a199853ec797ed3b85af.tar.xz ruby-1b7c50a6b849135f4f34a199853ec797ed3b85af.zip | |
* 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: http://svn.ruby-lang.org/repos/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 fea78232e..be94d4314 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; } |
