prepare metaclass of metaclass when retrieving by singleton_class(); close #540

parent 8856c892
......@@ -64,26 +64,38 @@ mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name)
mrb_intern(mrb, "__classid__"), mrb_symbol_value(name));
}
#define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c))
static void
make_metaclass(mrb_state *mrb, struct RClass *c)
prepare_singleton_class(mrb_state *mrb, struct RBasic *o)
{
struct RClass *sc;
struct RClass *sc, *c;
if (c->c->tt == MRB_TT_SCLASS) {
return;
}
if (o->c->tt == MRB_TT_SCLASS) return;
sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class);
sc->mt = 0;
sc->iv = 0;
if (!c->super) {
sc->super = mrb->class_class;
if (o->tt == MRB_TT_CLASS) {
c = (struct RClass*)o;
if (!c->super) {
sc->super = mrb->class_class;
}
else {
sc->super = c->super->c;
}
}
else {
else if (o->tt == MRB_TT_SCLASS) {
c = (struct RClass*)o;
make_metaclass(mrb, c->super);
sc->super = c->super->c;
}
c->c = sc;
mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)sc);
mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)sc->super);
else {
sc->super = o->c;
}
o->c = sc;
mrb_field_write_barrier(mrb, (struct RBasic*)o, (struct RBasic*)sc);
mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)o);
mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern(mrb, "__attached__"), mrb_obj_value(o));
}
struct RClass*
......@@ -179,7 +191,6 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id
mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %s", mrb_sym2name(mrb, id));
}
}
return c;
}
......@@ -759,20 +770,6 @@ mrb_mod_included_modules(mrb_state *mrb, mrb_value self)
return result;
}
static struct RClass *
mrb_singleton_class_ptr(mrb_state *mrb, struct RClass *c)
{
struct RClass *sc;
if (o->c->tt == MRB_TT_SCLASS) return;
sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class);
sc->mt = 0;
sc->super = c;
mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)c);
return sc;
}
mrb_value
mrb_singleton_class(mrb_state *mrb, mrb_value v)
{
......@@ -796,14 +793,14 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v)
break;
}
obj = mrb_object(v);
obj->c = mrb_singleton_class_ptr(mrb, obj->c);
prepare_singleton_class(mrb, obj);
return mrb_obj_value(obj->c);
}
void
mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, int aspec)
{
o->c = mrb_singleton_class_ptr(mrb, o->c);
prepare_singleton_class(mrb, (struct RBasic*)o);
mrb_define_method_id(mrb, o->c, mrb_intern(mrb, name), func, aspec);
}
......@@ -944,15 +941,14 @@ mrb_value
mrb_class_superclass(mrb_state *mrb, mrb_value klass)
{
struct RClass *c;
mrb_value superclass;
c = mrb_class_ptr(klass);
if (c->super)
superclass = mrb_obj_value(mrb_class_real(c->super));
else
superclass = mrb_nil_value();
return superclass;
c = c->super;
while (c && c->tt == MRB_TT_ICLASS) {
c = c->super;
}
if (!c) return mrb_nil_value();
return mrb_obj_value(c);
}
static mrb_value
......
......@@ -287,7 +287,8 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
clone->super = klass->super;
if (klass->iv) {
clone->iv = klass->iv;
mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass));
mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern(mrb, "__attached__"), obj);
}
if (klass->mt) {
clone->mt = kh_copy(mt, mrb, klass->mt);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment