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 | |
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
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | variable.c | 42 | ||||
-rw-r--r-- | vm.c | 17 |
3 files changed, 52 insertions, 23 deletions
@@ -12,6 +12,22 @@ Fri Feb 2 18:27:54 2007 Yukihiro Matsumoto <matz@ruby-lang.org> * eval.c: remove duplicated global variables rb_cProc and rb_cBinding. [ruby-dev:30242] +Thu Feb 1 20:53:32 2007 Yukihiro Matsumoto <matz@ruby-lang.org> + + * 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. + Thu Feb 1 20:31:41 2007 Yukihiro Matsumoto <matz@ruby-lang.org> * variable.c (rb_cvar_set): remove warn argument. 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; } @@ -1141,22 +1141,11 @@ eval_get_cvar_base(yarv_thread_t *th, yarv_iseq_t *iseq) NODE *cref = get_cref(iseq, th->cfp->lfp); VALUE klass = Qnil; - while (cref) { + if (cref) { klass = cref->nd_clss; - cref = cref->nd_next; - - if (cref == 0) { - continue; + if (!cref->nd_next) { + rb_warn("class variable access from toplevel"); } - - if (NIL_P(klass) || FL_TEST(klass, FL_SINGLETON)) { - if (cref->nd_next == 0) { - rb_warn - ("class variable access from toplevel singleton method"); - } - continue; - } - break; } if (NIL_P(klass)) { rb_raise(rb_eTypeError, "no class variables available"); |