static VALUE rb_unmix(VALUE self, VALUE module) { VALUE klass; /* check that module is valid */ if (TYPE(module) != T_MODULE) rb_raise(rb_eArgError, "error: parameter must be a module"); for (klass = KLASS_OF(self); klass != rb_class_real(klass); klass = RCLASS_SUPER(klass)) { VALUE super = RCLASS_SUPER(klass); if (BUILTIN_TYPE(super) == T_ICLASS) { if (KLASS_OF(super) == module) { if (RCLASS_SUPER(module) && BUILTIN_TYPE(RCLASS_SUPER(module)) == T_ICLASS) remove_nested_module(super, module); RCLASS_SUPER(klass) = RCLASS_SUPER(RCLASS_SUPER(klass)); rb_clear_cache(); /* If the module is taken out, call the unmixed(obj) hook on * the module */ rb_funcall(module, rb_intern("unmixed"), 1, self); } } } return self; }
static void remove_nested_module(VALUE klass, VALUE module) { if (CLASS_OF(RCLASS_SUPER(klass)) == CLASS_OF(RCLASS_SUPER(module))) { if (RCLASS_SUPER(RCLASS_SUPER(module)) && BUILTIN_TYPE(RCLASS_SUPER(module)) == T_ICLASS) { remove_nested_module(RCLASS_SUPER(klass), RCLASS_SUPER(module)); } RCLASS_SUPER(klass) = RCLASS_SUPER(RCLASS_SUPER(klass)); } }
static void remove_nested_module(VALUE klass, VALUE include_class) { if (KLASS_OF(RCLASS_SUPER(klass)) != KLASS_OF(RCLASS_SUPER(include_class))) { return; } if (RCLASS_SUPER(RCLASS_SUPER(include_class)) && BUILTIN_TYPE(RCLASS_SUPER(include_class)) == T_ICLASS) { remove_nested_module(RCLASS_SUPER(klass), RCLASS_SUPER(include_class)); } RCLASS_SUPER(klass) = RCLASS_SUPER(RCLASS_SUPER(klass)); }
static VALUE do_unmix(VALUE self, VALUE receiver, VALUE module) { VALUE klass = CLASS_OF(receiver); while (klass != rb_class_real(klass)) { VALUE super = RCLASS_SUPER(klass); if (BUILTIN_TYPE(super) == T_ICLASS && CLASS_OF(super) == module) { if (RCLASS_SUPER(module) && BUILTIN_TYPE(RCLASS_SUPER(module)) == T_ICLASS) { remove_nested_module(super, module); } RCLASS_SUPER(klass) = RCLASS_SUPER(super); rb_clear_cache(); } klass = super; } return receiver; }