Ejemplo n.º 1
0
void
rb_prepend_module(VALUE klass, VALUE module)
{
    void rb_vm_check_redefinition_by_prepend(VALUE klass);
    VALUE origin;
    int changed = 0;

    rb_frozen_class_p(klass);

    Check_Type(module, T_MODULE);

    OBJ_INFECT(klass, module);

    origin = RCLASS_ORIGIN(klass);
    if (origin == klass) {
	origin = class_alloc(T_ICLASS, klass);
	RCLASS_SET_SUPER(origin, RCLASS_SUPER(klass));
	RCLASS_SET_SUPER(klass, origin);
	RCLASS_ORIGIN(klass) = origin;
	RCLASS_M_TBL(origin) = RCLASS_M_TBL(klass);
	RCLASS_M_TBL(klass) = st_init_numtable();
	st_foreach(RCLASS_M_TBL(origin), move_refined_method,
		   (st_data_t) RCLASS_M_TBL(klass));
    }
    changed = include_modules_at(klass, klass, module);
    if (changed < 0)
	rb_raise(rb_eArgError, "cyclic prepend detected");
    if (changed) {
	rb_clear_cache();
	rb_vm_check_redefinition_by_prepend(klass);
    }
}
Ejemplo n.º 2
0
void
rb_prepend_module(VALUE klass, VALUE module)
{
    void rb_vm_check_redefinition_by_prepend(VALUE klass);
    VALUE origin;
    int changed = 0;

    rb_frozen_class_p(klass);

    Check_Type(module, T_MODULE);

    OBJ_INFECT(klass, module);

    origin = RCLASS_ORIGIN(klass);
    if (origin == klass) {
	origin = class_alloc(T_ICLASS, klass);
	OBJ_WB_UNPROTECT(origin); /* TODO: conservertive shading. Need more survery. */
	RCLASS_SET_SUPER(origin, RCLASS_SUPER(klass));
	RCLASS_SET_SUPER(klass, origin);
	RCLASS_ORIGIN(klass) = origin;
	RCLASS_M_TBL_WRAPPER(origin) = RCLASS_M_TBL_WRAPPER(klass);
	RCLASS_M_TBL_INIT(klass);
	st_foreach(RCLASS_M_TBL(origin), move_refined_method,
		   (st_data_t) RCLASS_M_TBL(klass));
    }
    changed = include_modules_at(klass, klass, module);
    if (changed < 0)
	rb_raise(rb_eArgError, "cyclic prepend detected");
    if (changed) {
	rb_vm_check_redefinition_by_prepend(klass);
    }
}
Ejemplo n.º 3
0
/* call-seq:
 *   set_singleton_class(klass) -> klass
 * 
 * Makes the given +klass+ the singleton class of the receiver,
 * ignoring any existing singleton class and modules extending the receiver.
 * Modules already included in +klass+ become modules that extend the receiver.
 * If the receiver is an immediate or +klass+ is not a Class,
 * raises +TypeError+. */
static VALUE evilr_set_singleton_class(VALUE self, VALUE klass) {
  evilr__check_obj_and_class(self, klass);
  RCLASS_SET_SUPER(evilr__iclass_before_next_class(klass), rb_obj_class(self));
  rb_clear_cache_by_class(klass);
  evilr__make_singleton(self, klass);
  return klass;
}
Ejemplo n.º 4
0
/*!
 * 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)) {
	SET_METACLASS_OF(klass, metaclass);
	SET_METACLASS_OF(metaclass, metaclass);
    }
    else {
	VALUE tmp = METACLASS_OF(klass); /* for a meta^(n)-class klass, tmp is meta^(n)-class of Class class */
	SET_METACLASS_OF(klass, metaclass);
	SET_METACLASS_OF(metaclass, ENSURE_EIGENCLASS(tmp));
    }

    super = RCLASS_SUPER(klass);
    while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super);
    RCLASS_SET_SUPER(metaclass, super ? ENSURE_EIGENCLASS(super) : rb_cClass);

    OBJ_INFECT(metaclass, RCLASS_SUPER(metaclass));

    return metaclass;
}
Ejemplo n.º 5
0
VALUE
rb_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();
    }
    if (!RCLASS_CONST_TBL(module)) {
	RCLASS_CONST_TBL(module) = st_init_numtable();
    }
    RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
    RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);

    RCLASS_M_TBL_WRAPPER(OBJ_WB_UNPROTECT(klass)) =
	RCLASS_M_TBL_WRAPPER(OBJ_WB_UNPROTECT(RCLASS_ORIGIN(module)));

    RCLASS_SET_SUPER(klass, super);
    if (RB_TYPE_P(module, T_ICLASS)) {
	RBASIC_SET_CLASS(klass, RBASIC(module)->klass);
    }
    else {
	RBASIC_SET_CLASS(klass, module);
    }
    OBJ_INFECT(klass, module);
    OBJ_INFECT(klass, super);

    return (VALUE)klass;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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));
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
/* call-seq:
 *   superclass=(klass) -> klass
 * 
 * Modifies the superclass of the current class to be the given
 * class.  Any modules included in the receiver remain included.
 * Raises +TypeError+ if klass is not a Class or if the receiver
 * and class are not compatible (where their instances use
 * different internal types). */
static VALUE evilr_superclass_e(VALUE klass, VALUE super) {
  VALUE iclass;
  evilr__check_compatible_classes(klass, super);
  iclass = evilr__iclass_before_next_class(klass);
  RCLASS_SET_SUPER(iclass, super);
  rb_clear_cache_by_class(klass);
  return super;
}
Ejemplo n.º 10
0
/* call-seq:
 *   to_class(klass=Object) -> Class
 * 
 * Makes a copy of the module, converts the copy to a class, and returns it. The
 * returned class can then have instances created from it. The +klass+ argument
 * sets the superclass of the returned class.  If +klass+ is not a Class,
 * raises +TypeError+. */
static VALUE evilr_to_class(int argc, VALUE *argv, VALUE self) {
  VALUE klass = evilr__optional_class(argc, argv);

  self = rb_obj_clone(self);
  RBASIC_SET_KLASS(self, rb_singleton_class(klass));
  RCLASS_SET_SUPER(self, klass);
  FL_UNSET(self, T_MASK);
  FL_SET(self, T_CLASS);
  return self;
}
Ejemplo n.º 11
0
/* If self has a singleton class, set the superclass of the
 * singleton class to the given klass, keeping all modules
 * that are included in the singleton class.  Otherwise, set the
 * object's klass to the given klass. */
void evilr__reparent_singleton_class(VALUE self, VALUE klass) {
  VALUE self_klass = RBASIC_KLASS(self);

  if (IS_SINGLETON_CLASS(self_klass)) {
    RCLASS_SET_SUPER(evilr__iclass_before_next_class(self_klass), klass);
    rb_clear_cache_by_class(self_klass);
  } else {
    RBASIC_SET_KLASS(self, klass);
  }
}
Ejemplo n.º 12
0
VALUE
rb_mod_init_copy(VALUE clone, SEL sel, VALUE orig)
{
    rb_obj_init_copy(clone, 0, orig);

    VALUE super;
    if (!RCLASS_RUBY(orig)) {
	super = orig;
	rb_warn("cloning class `%s' is not supported, creating a " \
		"subclass instead", rb_class2name(orig));
    }
    else {
	super = RCLASS_SUPER(orig);
    }
    RCLASS_SET_SUPER(clone, super);

    // Copy flags.
    unsigned long version_flag = RCLASS_IS_RUBY_CLASS;
    if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS)
	    == RCLASS_IS_OBJECT_SUBCLASS) {
	version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
    }
    if (RCLASS_MODULE(orig)) {
	version_flag |= RCLASS_IS_MODULE;
    }
    RCLASS_SET_VERSION(clone, version_flag);
    if (!class_isMetaClass((Class)clone)) {
	// Clear type info.
	RCLASS_SET_VERSION(*(Class *)clone, RCLASS_VERSION(*(Class *)clone));
    }

    // Copy methods.
    rb_vm_copy_methods((Class)orig, (Class)clone);
    if (!class_isMetaClass((Class)orig)) {
	rb_vm_copy_methods(*(Class *)orig, *(Class *)clone);
    }

    // Copy ivars.
    CFMutableDictionaryRef orig_dict = rb_class_ivar_dict(orig);
    CFMutableDictionaryRef clone_dict;
    if (orig_dict != NULL) {
	clone_dict = CFDictionaryCreateMutableCopy(NULL, 0, orig_dict);
	rb_class_ivar_set_dict(clone, clone_dict);
	CFMakeCollectable(clone_dict);
    }
    else {
	clone_dict = rb_class_ivar_dict_or_create(clone);
    }

    // Remove the classpath & classid (name) so that they are not
    // copied over the new module / class.
    CFDictionaryRemoveValue(clone_dict, (const void *)id_classpath);
    CFDictionaryRemoveValue(clone_dict, (const void *)id_classid);
    return clone;
}
Ejemplo n.º 13
0
/*!
 * A utility function that wraps class_alloc.
 *
 * allocates a class and initializes safely.
 * \param super     a class from which the new class derives.
 * \return          a class object.
 * \pre  \a super must be a class.
 * \post the metaclass of the new class is Class.
 */
VALUE
rb_class_boot(VALUE super)
{
    VALUE klass = class_alloc(T_CLASS, rb_cClass);

    RCLASS_SET_SUPER(klass, super);
    RCLASS_M_TBL(klass) = st_init_numtable();

    OBJ_INFECT(klass, super);
    return (VALUE)klass;
}
Ejemplo n.º 14
0
/*!
 * A utility function that wraps class_alloc.
 *
 * allocates a class and initializes safely.
 * \param super     a class from which the new class derives.
 * \return          a class object.
 * \pre  \a super must be a class.
 * \post the metaclass of the new class is Class.
 */
VALUE
rb_class_boot(VALUE super)
{
    VALUE klass = class_alloc(T_CLASS, rb_cClass);

    RCLASS_SET_SUPER(klass, super);
    RCLASS_M_TBL_INIT(klass);

    OBJ_INFECT(klass, super);
    return (VALUE)klass;
}
Ejemplo n.º 15
0
Archivo: class.c Proyecto: MSch/MacRuby
/* :nodoc: */
VALUE
rb_mod_init_copy(VALUE clone, SEL sel, VALUE orig)
{
    static ID classpath = 0;
    static ID classid = 0;

    rb_obj_init_copy(clone, 0, orig);
    {
	VALUE super;
	unsigned long version_flag;

	if (!RCLASS_RUBY(orig)) {
	    super = orig;
	    rb_warn("cloning class `%s' is not supported, creating a " \
		    "subclass instead", rb_class2name(orig));
	}
	else {
	    super = RCLASS_SUPER(orig);
	}
	RCLASS_SET_SUPER(clone, super);

	version_flag = RCLASS_IS_RUBY_CLASS;
	if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS) == RCLASS_IS_OBJECT_SUBCLASS) {
	    version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
	}

	RCLASS_SET_VERSION(clone, version_flag);

	rb_vm_copy_methods((Class)orig, (Class)clone);
	CFMutableDictionaryRef ivar_dict = rb_class_ivar_dict(orig);
	if (ivar_dict != NULL) {
	    CFMutableDictionaryRef cloned_ivar_dict;

	    if (classpath == 0) {
		classpath = rb_intern("__classpath__");
	    }
	    if (classid == 0) {
		classid = rb_intern("__classid__");
	    }
	    cloned_ivar_dict = CFDictionaryCreateMutableCopy(NULL, 0,
		(CFDictionaryRef)ivar_dict);
	    // Remove the classpath & classid (name) so that they are not
	    // copied over the new module / class
	    CFDictionaryRemoveValue(cloned_ivar_dict, (const void *)classpath);
	    CFDictionaryRemoveValue(cloned_ivar_dict, (const void *)classid);
	    CFMakeCollectable(cloned_ivar_dict);
	    rb_class_ivar_set_dict(clone, cloned_ivar_dict);
	}
    }

    return clone;
}
Ejemplo n.º 16
0
/* Empty is an almost completely empty class, even more basic than
 * BasicObject.  It has no parent class, and only implements
 * +allocate+, +new+, +initialize+, and +superclass+.  All other
 * behavior must be added by the user.  Note that if you want to
 * call a method defined in Object, Kernel, or BasicObject that
 * isn't defined in Empty, you can use <tt>UndefinedMethod#force_bind</tt>,
 * to do so:
 *
 *   Object.instance_method(:puts).force_bind(Empty.new).call()
 */
void Init_evilr(void) {
  empty = rb_define_class("Empty", rb_cObject);
  rb_define_alloc_func(empty, evilr_empty_alloc);
  rb_define_singleton_method(empty, "new", evilr_empty_new, -1);
  rb_define_singleton_method(empty, "superclass", evilr_empty_superclass, 0);
  rb_define_method(empty, "initialize", evilr_empty_initialize, 0);
  RCLASS_SET_SUPER(empty, NULL);
  rb_global_variable(&empty);

  evilr__attached = rb_intern("__attached__");
  evilr__bind = rb_intern("bind");
  evilr__clone = rb_intern("clone");

  rb_define_method(rb_cObject, "class=", evilr_class_e, 1);
  rb_define_method(rb_cObject, "evilr_debug_print", evilr_debug_print, 0);
  rb_define_method(rb_cObject, "extend_between", evilr_extend_between, 1);
  rb_define_method(rb_cObject, "flags", evilr_flags, 0);
  rb_define_method(rb_cObject, "detach_singleton_class", evilr_detach_singleton_class, 0);
  rb_define_method(rb_cObject, "dup_singleton_class", evilr_dup_singleton_class, -1);
  rb_define_method(rb_cObject, "pop_singleton_class", evilr_pop_singleton_class, 0);
  rb_define_method(rb_cObject, "push_singleton_class", evilr_push_singleton_class, 1);
  rb_define_method(rb_cObject, "remove_singleton_class", evilr_remove_singleton_class, 0);
  rb_define_method(rb_cObject, "remove_singleton_classes", evilr_remove_singleton_classes, 0);
  rb_define_method(rb_cObject, "set_singleton_class", evilr_set_singleton_class, 1);
  rb_define_method(rb_cObject, "swap", evilr_swap, 1);
  rb_define_method(rb_cObject, "swap_instance_variables", evilr_swap_instance_variables, 1);
  rb_define_method(rb_cObject, "swap_singleton_class", evilr_swap_singleton_class, 1);
  rb_define_method(rb_cObject, "unextend", evilr_unextend, 1);
  rb_define_method(rb_cObject, "unfreeze", evilr_unfreeze, 0);

  rb_define_method(rb_mKernel, "segfault", evilr_segfault, 0);
  rb_define_method(rb_mKernel, "seppuku", evilr_seppuku, 0);
  rb_define_method(rb_mKernel, "set_safe_level", evilr_set_safe_level, 1);

  rb_define_method(rb_cModule, "include_between", evilr_include_between, 1);
  rb_define_method(rb_cModule, "swap_method_tables", evilr_swap_method_tables, 1);
  rb_define_method(rb_cModule, "to_class", evilr_to_class, -1);
  rb_define_method(rb_cModule, "uninclude", evilr_uninclude, 1);

  rb_define_method(rb_cClass, "detach_singleton", evilr_detach_singleton, 0);
  rb_define_method(rb_cClass, "inherit", evilr_inherit, -1);
  rb_define_method(rb_cClass, "singleton_class_instance", evilr_singleton_class_instance, 0);
  rb_define_method(rb_cClass, "superclass=", evilr_superclass_e, 1);
  rb_define_method(rb_cClass, "to_module", evilr_to_module, 0);

  rb_define_method(rb_cUnboundMethod, "force_bind", evilr_force_bind, 1);

  rb_define_method(rb_cProc, "self", evilr_self, 0);
  rb_define_method(rb_cProc, "self=", evilr_self_e, 1);
}
Ejemplo n.º 17
0
/* call-seq:
 *   include_between(mod){|p, c| } -> mod || nil
 *
 * Walks the receiver's super chain, yielding the previous and current entries in
 * the super chain at every step.  The first time the block returns +true+, +mod+ is
 * inserted into the super chain between the two values, and the method returns
 * immediately.  Raises +TypeError+ if +mod+ is not a Module.
 * If the block ever returns +true+, the return value is +mod+.  If
 * the block never returns +true+, the return value is +nil+.  On the first block call,
 * the first block argument is the receiver, and on the last block call, the last block
 * argument is +nil+. */
static VALUE evilr_include_between(VALUE klass, VALUE mod) {
  VALUE iclass, prev, cur;

  evilr__check_immediate(mod);
  evilr__check_type(T_MODULE, mod);

  /* Create ICLASS for module by inserting it and removing it.
   * If module already in super chain, will change it's position. */
  rb_include_module(klass, mod);
  iclass = evilr__iclass_matching(klass, mod);
  evilr_uninclude(klass, mod);

  for (prev = klass, cur = RCLASS_SUPER(klass); prev ; prev = cur, cur = cur ? RCLASS_SUPER(cur) : cur) {
    if (BUILTIN_TYPE(prev) == T_CLASS) {
      rb_clear_cache_by_class(prev);
    }
    if (rb_yield_values(2, INCLUDE_BETWEEN_VAL(prev), INCLUDE_BETWEEN_VAL(cur)) == Qtrue) {
      RCLASS_SET_SUPER(prev, iclass);
      RCLASS_SET_SUPER(iclass, cur);
      return mod;
    }
  }
  return Qnil;
}
Ejemplo n.º 18
0
/* call-seq:
 *   extend_between(mod){|p, c| } -> mod || nil
 *
 * Walks the receiver's singleton class's super chain until it reaches the receiver's
 * class, yielding the previous and current entries in the super chain at every step.
 * The first time the block returns +true+, +mod+ is inserted into the super chain
 * between the two values and the method returns immediately.  Raises +TypeError+ if
 * +mod+ is not a Module or if the receiver is an immediate.
 * If the block ever returns +true+, the return value is
 * +mod+.  If the block never returns +true+, the return value is +nil+.  On the first block call,
 * the first block argument is the receiver's singleton class, and on the last block call,
 * the last block argument is the receiver's class. */
static VALUE evilr_extend_between(VALUE self, VALUE mod) {
  VALUE sc, iclass, klass, prev, cur;

  evilr__check_immediates(self, mod);
  evilr__check_type(T_MODULE, mod);

  sc = rb_singleton_class(self);
  klass = rb_obj_class(self);
  rb_extend_object(self, mod);
  iclass = evilr__iclass_matching_before(sc, mod, klass);
  if (iclass == NULL) {
    rb_raise(rb_eArgError, "module already included in object's class");
  }
  evilr_unextend(self, mod);

  for (prev = sc, cur = RCLASS_SUPER(sc); prev && prev != klass; prev = cur, cur = cur ? RCLASS_SUPER(cur) : cur) {
    if (rb_yield_values(2, INCLUDE_BETWEEN_VAL(prev), INCLUDE_BETWEEN_VAL(cur)) == Qtrue) {
      RCLASS_SET_SUPER(prev, iclass);
      RCLASS_SET_SUPER(iclass, cur);
      return mod;
    }
  }
  return Qnil;
}
Ejemplo n.º 19
0
/**
 * Allocates a struct RClass for a new class.
 *
 * \param flags     initial value for basic.flags of the returned class.
 * \param klass     the class of the returned class.
 * \return          an uninitialized Class object.
 * \pre  \p klass must refer \c Class class or an ancestor of Class.
 * \pre  \code (flags | T_CLASS) != 0  \endcode
 * \post the returned class can safely be \c #initialize 'd.
 *
 * \note this function is not Class#allocate.
 */
static VALUE
class_alloc(VALUE flags, VALUE klass)
{
    NEWOBJ_OF(obj, struct RClass, klass, (flags & T_MASK) | (RGENGC_WB_PROTECTED_CLASS ? FL_WB_PROTECTED : 0));
    obj->ptr = ALLOC(rb_classext_t);
    RCLASS_IV_TBL(obj) = 0;
    RCLASS_CONST_TBL(obj) = 0;
    RCLASS_M_TBL(obj) = 0;
    RCLASS_SET_SUPER((VALUE)obj, 0);
    RCLASS_ORIGIN(obj) = (VALUE)obj;
    RCLASS_IV_INDEX_TBL(obj) = 0;
    RCLASS_REFINED_CLASS(obj) = Qnil;
    RCLASS_EXT(obj)->allocator = 0;
    return (VALUE)obj;
}
Ejemplo n.º 20
0
/* :nodoc: */
VALUE
rb_mod_init_copy(VALUE clone, VALUE orig)
{
    if (RB_TYPE_P(clone, T_CLASS)) {
	class_init_copy_check(clone, orig);
    }
    if (!OBJ_INIT_COPY(clone, orig)) return clone;
    if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
	RBASIC_SET_CLASS(clone, rb_singleton_class_clone(orig));
	rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
    }
    RCLASS_SET_SUPER(clone, RCLASS_SUPER(orig));
    RCLASS_EXT(clone)->allocator = RCLASS_EXT(orig)->allocator;
    if (RCLASS_IV_TBL(orig)) {
	st_data_t id;

	if (RCLASS_IV_TBL(clone)) {
	    st_free_table(RCLASS_IV_TBL(clone));
	}
	RCLASS_IV_TBL(clone) = rb_st_copy(clone, RCLASS_IV_TBL(orig));
	CONST_ID(id, "__tmp_classpath__");
	st_delete(RCLASS_IV_TBL(clone), &id, 0);
	CONST_ID(id, "__classpath__");
	st_delete(RCLASS_IV_TBL(clone), &id, 0);
	CONST_ID(id, "__classid__");
	st_delete(RCLASS_IV_TBL(clone), &id, 0);
    }
    if (RCLASS_CONST_TBL(orig)) {
	struct clone_const_arg arg;
	if (RCLASS_CONST_TBL(clone)) {
	    rb_free_const_table(RCLASS_CONST_TBL(clone));
	}
	RCLASS_CONST_TBL(clone) = st_init_numtable();
	arg.klass = clone;
	arg.tbl = RCLASS_CONST_TBL(clone);
	st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)&arg);
    }
    if (RCLASS_M_TBL(orig)) {
	if (RCLASS_M_TBL_WRAPPER(clone)) {
	    rb_free_m_tbl_wrapper(RCLASS_M_TBL_WRAPPER(clone));
	}
	RCLASS_M_TBL_INIT(clone);
	st_foreach(RCLASS_M_TBL(orig), clone_method_i, (st_data_t)clone);
    }

    return clone;
}
Ejemplo n.º 21
0
/* call-seq:
 *   unextend(mod) -> mod || nil
 *
 * Unextends the given module +mod+ from the receiver.  If the receiver's class includes the
 * module, does not uninclude it, so this should not affect any other objects besides the
 * receiver.  If +mod+ already extended the object, returns +mod+, otherwise returns +nil+.
 * Raises +TypeError+ if +mod+ is not a Module or if the receiver is an immediate. */
static VALUE evilr_unextend(VALUE self, VALUE mod) {
  VALUE prev, cur;

  evilr__check_immediates(self, mod);
  evilr__check_type(T_MODULE, mod);

  self = rb_singleton_class(self);
  rb_clear_cache_by_class(self);
  for (prev = self, cur = RCLASS_SUPER(self); cur && BUILTIN_TYPE(cur) != T_CLASS; prev = cur, cur = RCLASS_SUPER(cur)) {
    if (BUILTIN_TYPE(cur) == T_ICLASS && RBASIC_KLASS(cur) == mod) {
      RCLASS_SET_SUPER(prev, RCLASS_SUPER(cur));
      return mod;
    }
  }

  return Qnil;
}
Ejemplo n.º 22
0
/* call-seq:
 *   uninclude(mod) -> mod || nil
 *
 * Unincludes the given module +mod+ from the receiver or any of the receiver's
 * ancestors.  Walks the super chain of the receiver, and if an iclass for +mod+ is
 * encountered, the super chain is modified to skip that iclass.  Returns +mod+ if
 * an iclass for mod was present in the super chain, and +nil+ otherwise. If +mod+ is
 * not a Module, a +TypeError+ is raised. */
static VALUE evilr_uninclude(VALUE klass, VALUE mod) {
  VALUE cur, prev;

  evilr__check_immediate(mod);
  evilr__check_type(T_MODULE, mod);

  for (prev = klass, cur = RCLASS_SUPER(klass); cur ; prev = cur, cur = RCLASS_SUPER(cur)) {
    if (BUILTIN_TYPE(prev) == T_CLASS) {
      rb_clear_cache_by_class(prev);
    }
    if (BUILTIN_TYPE(cur) == T_ICLASS && RBASIC_KLASS(cur) == mod) {
      RCLASS_SET_SUPER(prev, RCLASS_SUPER(cur));
      return mod;
    }
  }

  return Qnil;
}
Ejemplo n.º 23
0
VALUE
rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
{
    VALUE klass = RBASIC(obj)->klass;

    if (!FL_TEST(klass, FL_SINGLETON))
	return klass;
    else {
	/* copy singleton(unnamed) class */
	VALUE clone = class_alloc(RBASIC(klass)->flags, 0);

	if (BUILTIN_TYPE(obj) == T_CLASS) {
	    RBASIC_SET_CLASS(clone, clone);
	}
	else {
	    RBASIC_SET_CLASS(clone, rb_singleton_class_clone(klass));
	}

	RCLASS_SET_SUPER(clone, RCLASS_SUPER(klass));
	RCLASS_EXT(clone)->allocator = RCLASS_EXT(klass)->allocator;
	if (RCLASS_IV_TBL(klass)) {
	    RCLASS_IV_TBL(clone) = rb_st_copy(clone, RCLASS_IV_TBL(klass));
	}
	if (RCLASS_CONST_TBL(klass)) {
	    struct clone_const_arg arg;
	    RCLASS_CONST_TBL(clone) = st_init_numtable();
	    arg.klass = clone;
	    arg.tbl = RCLASS_CONST_TBL(clone);
	    st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)&arg);
	}
	if (attach != Qundef) {
	    rb_singleton_class_attached(clone, attach);
	}
	RCLASS_M_TBL_INIT(clone);
	st_foreach(RCLASS_M_TBL(klass), clone_method_i, (st_data_t)clone);
	rb_singleton_class_attached(RBASIC(clone)->klass, clone);
	FL_SET(clone, FL_SINGLETON);

	return clone;
    }
}
Ejemplo n.º 24
0
/* call-seq:
 *   to_module -> Module
 * 
 * Makes a copy of the class, converts the copy to a module, and returns it. The
 * returned module can be included in other classes. */
static VALUE evilr_to_module(VALUE klass) {
  VALUE mod, iclass;

  if (IS_SINGLETON_CLASS(klass)) {
    if((mod = evilr_singleton_class_instance(klass))) {
      mod = rb_singleton_class_clone(mod);
      (void)evilr_detach_singleton(mod);
    } else {
      rb_raise(rb_eTypeError, "singleton class without attached instance");
    }
  } else {
    mod = rb_obj_clone(klass);
  }

  RBASIC_SET_KLASS(mod, rb_cModule);
  iclass = RCLASS_SUPER(mod);
  RCLASS_SET_SUPER(mod, NULL);
  FL_UNSET(mod, T_MASK);
  FL_SET(mod, T_MODULE);
  evilr__include_iclasses(mod, iclass);

  return mod;
}
Ejemplo n.º 25
0
/* Set the superclass of self to the given klass, keeping all
 * modules that are included in the class. */
void evilr__reparent_class(VALUE self, VALUE klass) {
  RCLASS_SET_SUPER(evilr__iclass_before_next_class(self), klass);
  rb_clear_cache_by_class(self);
}