1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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
This commit is contained in:
matz 2007-02-02 09:47:55 +00:00
parent e137ee9ac4
commit d99bcbe583
3 changed files with 52 additions and 23 deletions

View file

@ -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.

View file

@ -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;
}

17
vm.c
View file

@ -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");