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) ...@@ -64,26 +64,38 @@ mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name)
mrb_intern(mrb, "__classid__"), mrb_symbol_value(name)); mrb_intern(mrb, "__classid__"), mrb_symbol_value(name));
} }
#define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c))
static void 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) { if (o->c->tt == MRB_TT_SCLASS) return;
return;
}
sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class); sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class);
sc->mt = 0; sc->mt = 0;
sc->iv = 0; sc->iv = 0;
if (!c->super) { if (o->tt == MRB_TT_CLASS) {
sc->super = mrb->class_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; sc->super = c->super->c;
} }
c->c = sc; else {
mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)sc); sc->super = o->c;
mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)sc->super); }
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* struct RClass*
...@@ -179,7 +191,6 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id ...@@ -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)); mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %s", mrb_sym2name(mrb, id));
} }
} }
return c; return c;
} }
...@@ -759,20 +770,6 @@ mrb_mod_included_modules(mrb_state *mrb, mrb_value self) ...@@ -759,20 +770,6 @@ mrb_mod_included_modules(mrb_state *mrb, mrb_value self)
return result; 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_value
mrb_singleton_class(mrb_state *mrb, mrb_value v) mrb_singleton_class(mrb_state *mrb, mrb_value v)
{ {
...@@ -796,14 +793,14 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v) ...@@ -796,14 +793,14 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v)
break; break;
} }
obj = mrb_object(v); obj = mrb_object(v);
obj->c = mrb_singleton_class_ptr(mrb, obj->c); prepare_singleton_class(mrb, obj);
return mrb_obj_value(obj->c); return mrb_obj_value(obj->c);
} }
void void
mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, int aspec) 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); mrb_define_method_id(mrb, o->c, mrb_intern(mrb, name), func, aspec);
} }
...@@ -944,15 +941,14 @@ mrb_value ...@@ -944,15 +941,14 @@ mrb_value
mrb_class_superclass(mrb_state *mrb, mrb_value klass) mrb_class_superclass(mrb_state *mrb, mrb_value klass)
{ {
struct RClass *c; struct RClass *c;
mrb_value superclass;
c = mrb_class_ptr(klass); c = mrb_class_ptr(klass);
if (c->super) c = c->super;
superclass = mrb_obj_value(mrb_class_real(c->super)); while (c && c->tt == MRB_TT_ICLASS) {
else c = c->super;
superclass = mrb_nil_value(); }
if (!c) return mrb_nil_value();
return superclass; return mrb_obj_value(c);
} }
static mrb_value static mrb_value
......
...@@ -287,7 +287,8 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) ...@@ -287,7 +287,8 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
clone->super = klass->super; clone->super = klass->super;
if (klass->iv) { 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) { if (klass->mt) {
clone->mt = kh_copy(mt, mrb, 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