mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Implement Module#prepend.
This commit is contained in:
+65
-2
@@ -194,6 +194,7 @@ define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass *
|
||||
|
||||
if (mrb_const_defined_at(mrb, mrb_obj_value(outer), name)) {
|
||||
c = class_from_sym(mrb, outer, name);
|
||||
c = c->origin;
|
||||
if (super && mrb_class_real(c->super) != super) {
|
||||
mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %S (%S not %S)",
|
||||
mrb_sym2str(mrb, name),
|
||||
@@ -763,12 +764,13 @@ boot_defclass(mrb_state *mrb, struct RClass *super)
|
||||
else {
|
||||
c->super = mrb->object_class;
|
||||
}
|
||||
c->origin = c;
|
||||
c->mt = kh_init(mt, mrb);
|
||||
return c;
|
||||
}
|
||||
|
||||
MRB_API void
|
||||
mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
|
||||
MRB_API inline void
|
||||
include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *m, int search_super)
|
||||
{
|
||||
struct RClass *ins_pos;
|
||||
|
||||
@@ -782,6 +784,7 @@ mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
|
||||
}
|
||||
while (p) {
|
||||
if (c != p && p->tt == MRB_TT_CLASS) {
|
||||
if (!search_super) break;
|
||||
superclass_seen = 1;
|
||||
}
|
||||
else if (p->mt == m->mt) {
|
||||
@@ -810,6 +813,63 @@ mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
|
||||
}
|
||||
}
|
||||
|
||||
MRB_API void
|
||||
mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
|
||||
{
|
||||
include_module_at(mrb, c, m, FALSE);
|
||||
}
|
||||
|
||||
MRB_API void
|
||||
mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
|
||||
{
|
||||
struct RClass *origin;
|
||||
int changed = 0;
|
||||
|
||||
origin = c->origin;
|
||||
if (origin == c) {
|
||||
origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c);
|
||||
//OBJ_WB_UNPROTECT(origin); /* TODO: conservative shading. Need more survey. */
|
||||
origin->super = c->super;
|
||||
c->super = origin;
|
||||
c->origin = origin;
|
||||
origin->mt = c->mt;
|
||||
c->mt = kh_init(mt, mrb);
|
||||
}
|
||||
include_module_at(mrb, c, m, FALSE); // changed =
|
||||
if (changed) {
|
||||
//rb_vm_check_redefinition_by_prepend(klass);
|
||||
}
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_mod_prepend_features(mrb_state *mrb, mrb_value mod)
|
||||
{
|
||||
mrb_value klass;
|
||||
|
||||
mrb_check_type(mrb, mod, MRB_TT_MODULE);
|
||||
mrb_get_args(mrb, "C", &klass);
|
||||
mrb_prepend_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod));
|
||||
return mod;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_mod_prepend(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
mrb_value *argv;
|
||||
mrb_int argc, i;
|
||||
|
||||
mrb_get_args(mrb, "*", &argv, &argc);
|
||||
for (i=0; i<argc; i++) {
|
||||
mrb_check_type(mrb, argv[i], MRB_TT_MODULE);
|
||||
}
|
||||
while (argc--) {
|
||||
mrb_funcall(mrb, argv[argc], "prepend_features", 1, klass);
|
||||
mrb_funcall(mrb, argv[argc], "prepended", 1, klass);
|
||||
}
|
||||
|
||||
return klass;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_mod_append_features(mrb_state *mrb, mrb_value mod)
|
||||
{
|
||||
@@ -2090,6 +2150,9 @@ mrb_init_class(mrb_state *mrb)
|
||||
mrb_define_method(mrb, mod, "class_variable_set", mrb_mod_cvar_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.18 */
|
||||
mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, MRB_ARGS_REQ(1)); /* 15.2.2.4.25 */
|
||||
mrb_define_method(mrb, mod, "extended", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */
|
||||
mrb_define_method(mrb, mod, "prepend", mrb_mod_prepend, MRB_ARGS_ANY());
|
||||
mrb_define_method(mrb, mod, "prepended", mrb_bob_init, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, mod, "prepend_features", mrb_mod_prepend_features, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, mod, "include", mrb_mod_include, MRB_ARGS_ANY()); /* 15.2.2.4.27 */
|
||||
mrb_define_method(mrb, mod, "include?", mrb_mod_include_p, MRB_ARGS_REQ(1)); /* 15.2.2.4.28 */
|
||||
mrb_define_method(mrb, mod, "append_features", mrb_mod_append_features, MRB_ARGS_REQ(1)); /* 15.2.2.4.10 */
|
||||
|
||||
Reference in New Issue
Block a user