From d99bcbe583eb9f95022f8bcc51674cbdecf40d3b Mon Sep 17 00:00:00 2001 From: matz Date: Fri, 2 Feb 2007 09:47:55 +0000 Subject: * 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 --- variable.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) (limited to 'variable.c') 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; } -- cgit v1.2.3