static void add_module(VALUE self, VALUE module) { VALUE super = RCLASS_SUPER(rb_singleton_class(self)); #ifdef RUBY_19 VALUE klass = class_alloc(T_ICLASS, rb_cClass); #else NEWOBJ(klass, struct RClass); OBJSETUP(klass, rb_cClass, T_ICLASS); #endif if (BUILTIN_TYPE(module) == T_ICLASS) { module = KLASS_OF(module); } if (!RCLASS_IV_TBL(module)) { RCLASS_IV_TBL(module) = (void*)st_init_numtable(); } RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module); RCLASS_M_TBL(klass) = RCLASS_M_TBL(module); RCLASS_SUPER(klass) = super; if (TYPE(module) == T_ICLASS) { KLASS_OF(klass) = KLASS_OF(module); } else { KLASS_OF(klass) = module; } OBJ_INFECT(klass, module); OBJ_INFECT(klass, super); RCLASS_SUPER(rb_singleton_class(self)) = (VALUE)klass; }
VALUE rb_singleton_class_clone(VALUE obj) { VALUE klass = RBASIC(obj)->klass; if (!FL_TEST(klass, FL_SINGLETON)) return klass; else { struct clone_method_data data; /* copy singleton(unnamed) class */ VALUE clone = class_alloc(RBASIC(klass)->flags, 0); if (BUILTIN_TYPE(obj) == T_CLASS) { RBASIC(clone)->klass = (VALUE)clone; } else { RBASIC(clone)->klass = rb_singleton_class_clone(klass); } RCLASS_SUPER(clone) = RCLASS_SUPER(klass); if (RCLASS_IV_TBL(klass)) { RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass)); } RCLASS_M_TBL(clone) = st_init_numtable(); data.tbl = RCLASS_M_TBL(clone); data.klass = (VALUE)clone; st_foreach(RCLASS_M_TBL(klass), clone_method, (st_data_t)&data); rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); FL_SET(clone, FL_SINGLETON); return (VALUE)clone; } }
VALUE rb_to_module(VALUE self) { VALUE rclass, chain_start, jcur, klass; switch(BUILTIN_TYPE(self)) { case T_MODULE: return self; case T_CLASS: klass = self; break; case T_OBJECT: default: klass = rb_singleton_class(self); } chain_start = j_class_new(klass, rb_cObject); KLASS_OF(chain_start) = rb_cModule; RBASIC(chain_start)->flags = T_MODULE; jcur = chain_start; for(rclass = RCLASS_SUPER(klass); rclass != rb_cObject; rclass = RCLASS_SUPER(rclass)) { RCLASS_SUPER(jcur) = j_class_new(rclass, rb_cObject); jcur = RCLASS_SUPER(jcur); } RCLASS_SUPER(jcur) = (VALUE)NULL; return chain_start; }
VALUE rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) { VALUE recur, ary, klass; st_table *list; if (argc == 0) { recur = Qtrue; } else { rb_scan_args(argc, argv, "01", &recur); } klass = CLASS_OF(obj); list = st_init_numtable(); if (klass && FL_TEST(klass, FL_SINGLETON)) { st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list); klass = RCLASS_SUPER(klass); } if (RTEST(recur)) { while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) { st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list); klass = RCLASS_SUPER(klass); } } ary = rb_ary_new(); st_foreach(list, ins_methods_i, ary); st_free_table(list); return ary; }
void rb_extend_object(VALUE obj, VALUE module) { VALUE klass; if (TYPE(obj) == T_CLASS && RCLASS_RUBY(obj)) { VALUE sklass = rb_make_singleton_class(RCLASS_SUPER(obj)); RCLASS_SET_SUPER(obj, sklass); klass = *(VALUE *)sklass; } else { klass = rb_singleton_class(obj); } rb_include_module(klass, module); VALUE m = module; do { VALUE ary = rb_attr_get(m, idIncludedModules); if (ary != Qnil) { for (int i = 0, count = RARRAY_LEN(ary); i < count; i++) { VALUE mod = RARRAY_AT(ary, i); rb_extend_object(obj, mod); } } m = RCLASS_SUPER(m); } while (m == 0 || RCLASS_SINGLETON(m)); }
/*! * Creates a meta^(n+1)-class for a meta^(n)-class. * \param metaclass a class of a class * \return the created meta^(n+1)-class. * \pre \a metaclass is a metaclass * \post the class of \a metaclass is the returned class. */ static VALUE make_metametaclass(VALUE metaclass) { VALUE metametaclass, super_of_metaclass; if (RBASIC(metaclass)->klass == metaclass) { /* for meta^(n)-class of Class */ metametaclass = rb_class_boot(Qnil); RBASIC(metametaclass)->klass = metametaclass; } else { metametaclass = rb_class_boot(Qnil); RBASIC(metametaclass)->klass = (RBASIC(RBASIC(metaclass)->klass)->klass == RBASIC(metaclass)->klass) ? make_metametaclass(RBASIC(metaclass)->klass) : RBASIC(RBASIC(metaclass)->klass)->klass; } FL_SET(metametaclass, FL_SINGLETON); rb_singleton_class_attached(metametaclass, metaclass); RBASIC(metaclass)->klass = metametaclass; super_of_metaclass = RCLASS_SUPER(metaclass); while (FL_TEST(super_of_metaclass, T_ICLASS)) { super_of_metaclass = RCLASS_SUPER(super_of_metaclass); } RCLASS_SUPER(metametaclass) = rb_iv_get(RBASIC(super_of_metaclass)->klass, "__attached__") == super_of_metaclass ? RBASIC(super_of_metaclass)->klass : make_metametaclass(super_of_metaclass); OBJ_INFECT(metametaclass, RCLASS_SUPER(metametaclass)); return metametaclass; }
static int include_modules_at(const VALUE klass, VALUE c, VALUE module) { VALUE p, iclass; int method_changed = 0, constant_changed = 0; const st_table *const klass_m_tbl = RCLASS_M_TBL(RCLASS_ORIGIN(klass)); while (module) { int superclass_seen = FALSE; if (RCLASS_ORIGIN(module) != module) goto skip; if (klass_m_tbl && klass_m_tbl == RCLASS_M_TBL(module)) return -1; /* ignore if the module included already in superclasses */ for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) { switch (BUILTIN_TYPE(p)) { case T_ICLASS: if (RCLASS_M_TBL_WRAPPER(p) == RCLASS_M_TBL_WRAPPER(module)) { if (!superclass_seen) { c = p; /* move insertion point */ } goto skip; } break; case T_CLASS: superclass_seen = TRUE; break; } } iclass = rb_include_class_new(module, RCLASS_SUPER(c)); c = RCLASS_SET_SUPER(c, iclass); if (BUILTIN_TYPE(module) == T_ICLASS) { rb_module_add_to_subclasses_list(RBASIC(module)->klass, iclass); } else { rb_module_add_to_subclasses_list(module, iclass); } if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) { VALUE refined_class = rb_refinement_module_get_refined_class(klass); st_foreach(RMODULE_M_TBL(module), add_refined_method_entry_i, (st_data_t) refined_class); FL_SET(c, RMODULE_INCLUDED_INTO_REFINEMENT); } if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries) method_changed = 1; if (RMODULE_CONST_TBL(module) && RMODULE_CONST_TBL(module)->num_entries) constant_changed = 1; skip: module = RCLASS_SUPER(module); } if (method_changed) rb_clear_method_cache_by_class(klass); if (constant_changed) rb_clear_constant_cache(); return method_changed; }
/*! * Creates a metaclass of \a klass * \param klass a class * \return created metaclass for the class * \pre \a klass is a Class object * \pre \a klass has no singleton class. * \post the class of \a klass is the returned class. * \post the returned class is meta^(n+1)-class when \a klass is a meta^(n)-klass for n >= 0 */ static inline VALUE make_metaclass(VALUE klass) { VALUE super; VALUE metaclass = rb_class_boot(Qundef); FL_SET(metaclass, FL_SINGLETON); rb_singleton_class_attached(metaclass, klass); if (META_CLASS_OF_CLASS_CLASS_P(klass)) { METACLASS_OF(klass) = METACLASS_OF(metaclass) = metaclass; } else { VALUE tmp = METACLASS_OF(klass); /* for a meta^(n)-class klass, tmp is meta^(n)-class of Class class */ METACLASS_OF(klass) = metaclass; METACLASS_OF(metaclass) = ENSURE_EIGENCLASS(tmp); } super = RCLASS_SUPER(klass); while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super); RCLASS_SUPER(metaclass) = super ? ENSURE_EIGENCLASS(super) : rb_cClass; OBJ_INFECT(metaclass, RCLASS_SUPER(metaclass)); return metaclass; }
VALUE rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) { VALUE recur, ary, klass, origin; st_table *list, *mtbl; if (argc == 0) { recur = Qtrue; } else { rb_scan_args(argc, argv, "01", &recur); } klass = CLASS_OF(obj); origin = RCLASS_ORIGIN(klass); list = st_init_numtable(); if (klass && FL_TEST(klass, FL_SINGLETON)) { if ((mtbl = RCLASS_M_TBL(origin)) != 0) st_foreach(mtbl, method_entry_i, (st_data_t)list); klass = RCLASS_SUPER(klass); } if (RTEST(recur)) { while (klass && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) { if (klass != origin && (mtbl = RCLASS_M_TBL(klass)) != 0) st_foreach(mtbl, method_entry_i, (st_data_t)list); klass = RCLASS_SUPER(klass); } } ary = rb_ary_new(); st_foreach(list, ins_methods_i, ary); st_free_table(list); return ary; }
static VALUE superclass_name(VALUE module) { if(TYPE(module) == T_MODULE) { return Qnil; } else { VALUE super = RCLASS_SUPER(module); while(TYPE(super) == T_ICLASS) { super = RCLASS_SUPER(super); } if(!super) { return Qnil; } if(FL_TEST(super, FL_SINGLETON)) { VALUE v = rb_iv_get(super, "__attached__"); VALUE name = rb_mod_name(v); rb_str_cat2(name, "::<Singleton>"); return name; } else { return rb_mod_name(super); } } }
/* :nodoc: */ VALUE rb_mod_init_copy(VALUE clone, VALUE orig) { rb_obj_init_copy(clone, orig); if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) { RBASIC(clone)->klass = rb_singleton_class_clone(orig); } RCLASS_SUPER(clone) = RCLASS_SUPER(orig); if (RCLASS_IV_TBL(orig)) { ID id; RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(orig)); CONST_ID(id, "__classpath__"); st_delete(RCLASS_IV_TBL(clone), (st_data_t*)&id, 0); CONST_ID(id, "__classid__"); st_delete(RCLASS_IV_TBL(clone), (st_data_t*)&id, 0); } if (RCLASS_M_TBL(orig)) { struct clone_method_data data; data.tbl = RCLASS_M_TBL(clone) = st_init_numtable(); data.klass = clone; st_foreach(RCLASS_M_TBL(orig), clone_method, (st_data_t)&data); } return clone; }
VALUE rb_singleton_class_clone(VALUE obj) { VALUE klass = RBASIC(obj)->klass; if (!RCLASS_SINGLETON(klass)) { return klass; } // Create new singleton class. VALUE clone = rb_objc_create_class(NULL, RCLASS_SUPER(klass)); // Copy ivars. CFMutableDictionaryRef ivar_dict = rb_class_ivar_dict(klass); if (ivar_dict != NULL) { CFMutableDictionaryRef cloned_ivar_dict = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)ivar_dict); rb_class_ivar_set_dict(clone, cloned_ivar_dict); CFMakeCollectable(cloned_ivar_dict); } // Copy methods. rb_vm_copy_methods((Class)klass, (Class)clone); rb_singleton_class_attached(clone, obj); if (RCLASS_SUPER(clone) == rb_cRubyObject) { long v = RCLASS_VERSION(clone) ^ RCLASS_IS_OBJECT_SUBCLASS; RCLASS_SET_VERSION(clone, v); } RCLASS_SET_VERSION_FLAG(clone, RCLASS_IS_SINGLETON); return clone; }
static VALUE rb_mod_append_features(VALUE module, SEL sel, VALUE include) { VALUE orig = include; switch (TYPE(include)) { case T_CLASS: case T_MODULE: break; default: Check_Type(include, T_CLASS); break; } if (RCLASS_RUBY(include)) { VALUE sinclude = rb_make_singleton_class(RCLASS_SUPER(include)); RCLASS_SET_SUPER(include, sinclude); include = sinclude; } rb_include_module2(include, orig, module, true, true); VALUE m = module; do { VALUE ary = rb_attr_get(m, idIncludedModules); if (ary != Qnil) { for (int i = 0, count = RARRAY_LEN(ary); i < count; i++) { VALUE mod = RARRAY_AT(ary, i); rb_mod_append_features(mod, sel, include); } } m = RCLASS_SUPER(m); } while (m == 0 || RCLASS_SINGLETON(m)); return module; }
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)); } }
/* Walk the super chain from klass until either before or an iclass for mod is encountered. If * before is encountered first, return NULL. If an iclass for mod is encountered first, return * the iclass. */ static VALUE evilr__iclass_matching_before(VALUE klass, VALUE mod, VALUE before) { VALUE c; for (c = RCLASS_SUPER(klass); c && c != before; c = RCLASS_SUPER(c)) { if (BUILTIN_TYPE(c) == T_ICLASS && RBASIC_KLASS(c) == mod) { return c; } } return NULL; }
static VALUE rb_obj_superclass(VALUE klass, SEL sel) { VALUE cl = RCLASS_SUPER(klass); while (rb_class_hidden(cl)) { cl = RCLASS_SUPER(cl); } return rb_class_real(cl, true); }
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 rb_gsl_spline_info(VALUE obj) { rb_gsl_spline *p = NULL; char buf[256]; Data_Get_Struct(obj, rb_gsl_spline, p); sprintf(buf, "Class: %s\n", rb_class2name(CLASS_OF(obj))); sprintf(buf, "%sSuperClass: %s\n", buf, rb_class2name(RCLASS_SUPER(RCLASS_SUPER(obj)))); sprintf(buf, "%sType: %s\n", buf, gsl_interp_name(p->s->interp)); sprintf(buf, "%sxmin: %f\n", buf, p->s->interp->xmin); sprintf(buf, "%sxmax: %f\n", buf, p->s->interp->xmax); sprintf(buf, "%sSize: %d\n", buf, (int) p->s->size); return rb_str_new2(buf); }
VALUE rb_mod_included_modules(VALUE mod) { VALUE ary = rb_ary_new(); VALUE p; for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) { if (BUILTIN_TYPE(p) == T_ICLASS) { rb_ary_push(ary, RBASIC(p)->klass); } } return ary; }
VALUE rb_mod_include_p(VALUE mod, VALUE mod2) { VALUE p; Check_Type(mod2, T_MODULE); for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) { if (BUILTIN_TYPE(p) == T_ICLASS) { if (RBASIC(p)->klass == mod2) return Qtrue; } } return Qfalse; }
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; }
VALUE rb_obj_singleton_methods(VALUE obj, SEL sel, int argc, VALUE *argv) { VALUE recur, objc_methods, klass, ary; if (argc == 0) { recur = Qtrue; objc_methods = Qfalse; } else { rb_scan_args(argc, argv, "02", &recur, &objc_methods); } klass = CLASS_OF(obj); ary = rb_ary_new(); do { if (RCLASS_SINGLETON(klass)) { rb_vm_push_methods(ary, klass, RTEST(objc_methods), ins_methods_i); } klass = RCLASS_SUPER(klass); } while (recur == Qtrue && klass != 0); return ary; }
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super) { VALUE klass; ID id; id = rb_intern(name); if (rb_const_defined_at(outer, id)) { klass = rb_const_get_at(outer, id); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", name); } if (RCLASS_RUBY(klass)) { // Only for pure Ruby classes, as Objective-C classes // might be returned from the dynamic resolver. if (rb_class_real(RCLASS_SUPER(klass), true) != super) { rb_name_error(id, "%s is already defined", name); } return klass; } } if (!super) { rb_warn("no super class for `%s::%s', Object assumed", rb_class2name(outer), name); } klass = rb_define_class_id(id, super); rb_set_class_path(klass, outer, name); rb_const_set(outer, id, klass); rb_class_inherited(super, klass); return klass; }
static VALUE class_instance_method_list(int argc, VALUE *argv, VALUE mod, int (*func) (ID, long, VALUE)) { VALUE ary; int recur; st_table *list; if (argc == 0) { recur = TRUE; } else { VALUE r; rb_scan_args(argc, argv, "01", &r); recur = RTEST(r); } list = st_init_numtable(); for (; mod; mod = RCLASS_SUPER(mod)) { st_foreach(RCLASS_M_TBL(mod), method_entry, (st_data_t)list); if (BUILTIN_TYPE(mod) == T_ICLASS) continue; if (FL_TEST(mod, FL_SINGLETON)) continue; if (!recur) break; } ary = rb_ary_new(); st_foreach(list, func, ary); st_free_table(list); return ary; }
static void robj_sclass_finalize_imp(void *rcv, SEL sel) { bool changed = false; while (true) { VALUE k = *(VALUE *)rcv; if (!RCLASS_SINGLETON(k) || !rb_singleton_class_attached_object(k) == (VALUE)rcv) { break; } VALUE sk = RCLASS_SUPER(k); if (sk == 0) { // This can't happen, but we are never sure... break; } *(VALUE *)rcv = sk; rb_vm_dispose_class((Class)k); changed = true; } #if 0 if (changed) { objc_msgSend(rcv, selFinalize); } #endif }
static VALUE class_instance_method_list(int argc, VALUE *argv, VALUE mod, int (*func) (VALUE, ID, VALUE)) { VALUE ary; VALUE recur, objc_methods; ary = rb_ary_new(); if (argc == 0) { recur = Qtrue; objc_methods = Qfalse; } else { rb_scan_args(argc, argv, "02", &recur, &objc_methods); if (NIL_P(recur)) { recur = Qtrue; } if (NIL_P(objc_methods)) { objc_methods = Qfalse; } } while (mod != 0) { rb_vm_push_methods(ary, mod, RTEST(objc_methods), func); if (recur == Qfalse) { break; } mod = RCLASS_SUPER(mod); } return ary; }
static inline VALUE vm_call_super(rb_thread_t * const th, const int argc, const VALUE * const argv) { VALUE recv = th->cfp->self; VALUE klass; ID id; NODE *body; rb_control_frame_t *cfp = th->cfp; if (!cfp->iseq) { klass = cfp->method_class; klass = RCLASS_SUPER(klass); if (klass == 0) { klass = vm_search_normal_superclass(cfp->method_class, recv); } id = cfp->method_id; } else { rb_bug("vm_call_super: should not be reached"); } body = rb_method_node(klass, id); /* this returns NODE_METHOD */ if (!body) { return method_missing(recv, id, argc, argv, 0); } return vm_call0(th, klass, recv, id, (ID)body->nd_file, argc, argv, body->nd_body, CALL_SUPER); }
static VALUE include_class_new(VALUE module, VALUE super) { VALUE klass = class_alloc(T_ICLASS, rb_cClass); if (BUILTIN_TYPE(module) == T_ICLASS) { module = RBASIC(module)->klass; } if (!RCLASS_IV_TBL(module)) { RCLASS_IV_TBL(module) = st_init_numtable(); } RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module); RCLASS_M_TBL(klass) = RCLASS_M_TBL(module); RCLASS_SUPER(klass) = super; if (TYPE(module) == T_ICLASS) { RBASIC(klass)->klass = RBASIC(module)->klass; } else { RBASIC(klass)->klass = module; } OBJ_INFECT(klass, module); OBJ_INFECT(klass, super); return (VALUE)klass; }
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super) { VALUE klass; ID id; id = rb_intern(name); if (rb_const_defined_at(outer, id)) { klass = rb_const_get_at(outer, id); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", name); } if (rb_class_real(RCLASS_SUPER(klass)) != super) { rb_name_error(id, "%s is already defined", name); } return klass; } if (!super) { rb_warn("no super class for `%s::%s', Object assumed", rb_class2name(outer), name); } klass = rb_define_class_id(id, super); rb_set_class_path(klass, outer, name); rb_const_set(outer, id, klass); rb_class_inherited(super, klass); return klass; }
VALUE rb_define_class(const char *name, VALUE super) { VALUE klass; ID id; id = rb_intern(name); if (rb_const_defined(rb_cObject, id)) { klass = rb_const_get(rb_cObject, id); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", name); } if (rb_class_real(RCLASS_SUPER(klass)) != super) { rb_name_error(id, "%s is already defined", name); } return klass; } if (!super) { rb_warn("no super class for `%s', Object assumed", name); } klass = rb_define_class_id(id, super); st_add_direct(rb_class_tbl, id, klass); rb_name_class(klass, id); rb_const_set(rb_cObject, id, klass); rb_class_inherited(super, klass); return klass; }