Example #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);
    }
}
static void
remove_method(VALUE klass, ID mid)
{
    st_data_t key, data;
    rb_method_entry_t *me = 0;

    if (klass == rb_cObject) {
	rb_secure(4);
    }
    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) {
	rb_raise(rb_eSecurityError, "Insecure: can't remove method");
    }
    rb_check_frozen(klass);
    if (mid == object_id || mid == id__send__ || mid == idInitialize) {
	rb_warn("removing `%s' may cause serious problems", rb_id2name(mid));
    }

    if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) ||
	!(me = (rb_method_entry_t *)data) ||
	(!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) {
	rb_name_error(mid, "method `%s' not defined in %s",
		      rb_id2name(mid), rb_class2name(klass));
    }
    key = (st_data_t)mid;
    st_delete(RCLASS_M_TBL(klass), &key, &data);

    rb_vm_check_redefinition_opt_method(me, klass);
    rb_clear_cache_for_undef(klass, mid);
    rb_unlink_method_entry(me);

    CALL_METHOD_HOOK(klass, removed, mid);
}
Example #3
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(OBJ_WB_UNPROTECT(klass)) = RCLASS_M_TBL(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;
}
Example #4
0
static VALUE
class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (st_data_t, st_data_t, st_data_t))
{
    VALUE ary;
    int recur, prepended = 0;
    st_table *list;

    if (argc == 0) {
	recur = TRUE;
    }
    else {
	VALUE r;
	rb_scan_args(argc, argv, "01", &r);
	recur = RTEST(r);
    }

    if (!recur && RCLASS_ORIGIN(mod) != mod) {
	mod = RCLASS_ORIGIN(mod);
	prepended = 1;
    }

    list = st_init_numtable();
    for (; mod; mod = RCLASS_SUPER(mod)) {
	if (RCLASS_M_TBL(mod)) st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)list);
	if (BUILTIN_TYPE(mod) == T_ICLASS && !prepended) continue;
	if (obj && FL_TEST(mod, FL_SINGLETON)) continue;
	if (!recur) break;
    }
    ary = rb_ary_new();
    st_foreach(list, func, ary);
    st_free_table(list);

    return ary;
}
Example #5
0
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;
}
Example #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;
}
Example #7
0
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;
}
Example #8
0
/* :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;
}
Example #9
0
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;
}
Example #10
0
static void
remove_method(VALUE klass, ID mid)
{
    st_data_t key, data;
    rb_method_entry_t *me = 0;
    VALUE self = klass;

    klass = RCLASS_ORIGIN(klass);
    rb_frozen_class_p(klass);
    if (mid == object_id || mid == id__send__ || mid == idInitialize) {
	rb_warn("removing `%s' may cause serious problems", rb_id2name(mid));
    }

    if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) ||
	!(me = (rb_method_entry_t *)data) ||
	(!me->def || me->def->type == VM_METHOD_TYPE_UNDEF) ||
        UNDEFINED_REFINED_METHOD_P(me->def)) {
	rb_name_error(mid, "method `%"PRIsVALUE"' not defined in %"PRIsVALUE,
		      rb_id2str(mid), rb_class_path(klass));
    }

    key = (st_data_t)mid;
    st_delete(RCLASS_M_TBL(klass), &key, &data);

    rb_vm_check_redefinition_opt_method(me, klass);
    rb_clear_method_cache_by_class(klass);
    rb_unlink_method_entry(me);

    if (me->def->type == VM_METHOD_TYPE_REFINED) {
	rb_add_refined_method_entry(klass, mid);
    }

    CALL_METHOD_HOOK(self, removed, mid);
}
Example #11
0
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;
}
Example #12
0
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;
    }
}
Example #13
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);
    }
}
Example #14
0
void
rb_alias(VALUE klass, ID name, ID def)
{
    NODE *orig_fbody, *node, *method;
    VALUE singleton = 0;
    st_data_t data;

    rb_frozen_class_p(klass);
    if (klass == rb_cObject) {
	rb_secure(4);
    }
    orig_fbody = search_method(klass, def, 0);
    if (!orig_fbody || !orig_fbody->nd_body) {
	if (TYPE(klass) == T_MODULE) {
	    orig_fbody = search_method(rb_cObject, def, 0);
	}
    }
    if (!orig_fbody || !orig_fbody->nd_body) {
	rb_print_undef(klass, def, 0);
    }
    if (FL_TEST(klass, FL_SINGLETON)) {
	singleton = rb_iv_get(klass, "__attached__");
    }

    orig_fbody->nd_cnt++;

    if (st_lookup(RCLASS_M_TBL(klass), name, &data)) {
	node = (NODE *)data;
	if (node) {
	    if (RTEST(ruby_verbose) && node->nd_cnt == 0 && node->nd_body) {
		rb_warning("discarding old %s", rb_id2name(name));
	    }
	    if (nd_type(node->nd_body->nd_body) == NODE_CFUNC) {
		rb_vm_check_redefinition_opt_method(node);
	    }
	}
    }

    st_insert(RCLASS_M_TBL(klass), name,
	      (st_data_t) NEW_FBODY(
		  method = NEW_METHOD(orig_fbody->nd_body->nd_body,
			     orig_fbody->nd_body->nd_clss,
			     NOEX_WITH_SAFE(orig_fbody->nd_body->nd_noex)), def));
    method->nd_file = (void *)def;

    rb_clear_cache_by_id(name);

    if (!ruby_running) return;

    if (singleton) {
	rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
    }
    else {
	rb_funcall(klass, added, 1, ID2SYM(name));
    }
}
Example #15
0
/* call-seq:
 *   swap_method_tables(other) -> self
 * 
 * Swap the method table of the receiver with the method table of the given
 * class or module.  If +other+ is not a class or module, raise a +TypeError+. */
static VALUE evilr_swap_method_tables(VALUE self, VALUE other) {
  struct st_table *tmp;

  evilr__check_immediate(other);
  if(BUILTIN_TYPE(other) != T_MODULE && BUILTIN_TYPE(other) != T_CLASS) {
    rb_raise(rb_eTypeError, "non-class or module used");
  }

  tmp = RCLASS_M_TBL(self);
  RCLASS(self)->m_tbl = RCLASS_M_TBL(other);
  RCLASS(other)->m_tbl = tmp;
  rb_clear_cache_by_class(self);
  rb_clear_cache_by_class(other);
  return self;
}
Example #16
0
VALUE
rb_reset_tbls(VALUE self)
{
    RCLASS_IV_TBL(self) = (struct st_table *) 0;
    RCLASS_M_TBL(self) = (struct st_table *) st_init_numtable();
    return Qnil;
}
Example #17
0
static VALUE internal_instance_methods(VALUE klass, long visibility) {
  add_method_if_matching_arg_t arg;
  arg.names = rb_ary_new();
  arg.visibility = visibility;
  st_foreach(RCLASS_M_TBL(klass), add_method_if_matching, (st_data_t)&arg);
  return arg.names;
}
Example #18
0
static VALUE create_class_restorer(VALUE klass)
{
  /* On Ruby 1.8, there is a check in marshal_dump() to ensure that
   * the object being dumped has no modifications to its singleton
   * class (e.g. no singleton instance variables, and no singleton
   * methods defined).  Since we need to dump the class's singleton
   * class in order to dump class methods, we need a way around this
   * restriction.  The solution found here temporarily removes the
   * singleton instance variables and singleton methods while the
   * class is being dumped, and sets a special singleton instance
   * variable that restores the tables when dumping is complete.  A
   * hack for sure, but it seems to work.
   */
  struct RClass * singleton_class = RCLASS(CLASS_OF(klass));
  struct Class_Restorer * class_restorer;

  if(!RCLASS_IV_TBL(singleton_class))
  {
    rb_raise(
        rb_eTypeError,
        "can't dump singleton class on Ruby 1.8 without iv_tbl");
  }

  class_restorer = ALLOC(struct Class_Restorer);
  class_restorer->klass = CLASS_OF(klass);
  class_restorer->m_tbl = *RCLASS_M_TBL(singleton_class);
  class_restorer->iv_tbl = *RCLASS_IV_TBL(singleton_class);
#ifndef RUBY_VM
  class_restorer->thread_critical = rb_thread_critical;
#endif
  return Data_Wrap_Struct(
      rb_cClass_Restorer, mark_class_restorer, ruby_xfree,
      class_restorer);
}
Example #19
0
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;
}
Example #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;
}
Example #21
0
/* a modified version of include_class_new from class.c */
static VALUE
j_class_new(VALUE module, VALUE sup)
{

#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) = (struct st_table *)st_init_numtable();
    }

    /* assign iv_tbl, m_tbl and super */
    RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
    RCLASS_SUPER(klass) = sup;
    if(TYPE(module) != T_OBJECT) {

        RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
    }
    else {
        RCLASS_M_TBL(klass) = RCLASS_M_TBL(CLASS_OF(module));
    }

    /* */

    if (TYPE(module) == T_ICLASS) {
        KLASS_OF(klass) = KLASS_OF(module);
    }
    else {
        KLASS_OF(klass) = module;
    }

    if(TYPE(module) != T_OBJECT) {
        OBJ_INFECT(klass, module);
        OBJ_INFECT(klass, sup);
    }
    return (VALUE)klass;
}
Example #22
0
File: mri.c Project: hkraji/looksee
static VALUE internal_instance_methods(VALUE klass, VISIBILITY_TYPE visibility) {
  add_method_if_matching_arg_t arg;
  arg.names = rb_ary_new();
  arg.visibility = visibility;

  Looksee_method_table_foreach(RCLASS_M_TBL(klass), add_method_if_matching, (st_data_t)&arg);
  return arg.names;
}
Example #23
0
File: class.c Project: fi8on/ruby
void
rb_include_module(VALUE klass, VALUE module)
{
    VALUE p, c;
    int changed = 0;

    rb_frozen_class_p(klass);
    if (!OBJ_UNTRUSTED(klass)) {
	rb_secure(4);
    }

    if (TYPE(module) != T_MODULE) {
	Check_Type(module, T_MODULE);
    }

    OBJ_INFECT(klass, module);
    c = klass;
    while (module) {
	int superclass_seen = FALSE;

	if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module))
	    rb_raise(rb_eArgError, "cyclic include detected");
	/* 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(p) == RCLASS_M_TBL(module)) {
		    if (!superclass_seen) {
			c = p;  /* move insertion point */
		    }
		    goto skip;
		}
		break;
	      case T_CLASS:
		superclass_seen = TRUE;
		break;
	    }
	}
	c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c));
	if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries)
	    changed = 1;
      skip:
	module = RCLASS_SUPER(module);
    }
    if (changed) rb_clear_cache();
}
Example #24
0
File: class.c Project: amtep/ruby
/* :nodoc: */
VALUE
rb_mod_init_copy(VALUE clone, VALUE orig)
{
    if (RB_TYPE_P(clone, T_CLASS)) {
	class_init_copy_check(clone, orig);
    }
    rb_obj_init_copy(clone, orig);
    if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
	RBASIC(clone)->klass = rb_singleton_class_clone(orig);
	rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
    }
    RCLASS_SUPER(clone) = RCLASS_SUPER(orig);
    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) = st_copy(RCLASS_IV_TBL(orig));
	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)) {
	if (RCLASS_CONST_TBL(clone)) {
	    rb_free_const_table(RCLASS_CONST_TBL(clone));
	}
	RCLASS_CONST_TBL(clone) = st_init_numtable();
	st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone));
    }
    if (RCLASS_M_TBL(orig)) {
	struct clone_method_data data;

	if (RCLASS_M_TBL(clone)) {
	    rb_free_m_table(RCLASS_M_TBL(clone));
	}
	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;
}
Example #25
0
static void set_class_restore_state(VALUE klass)
{
  struct RClass * singleton_class = RCLASS(CLASS_OF(klass));
  RCLASS_IV_TBL(singleton_class)->num_entries = 1;
  RCLASS_M_TBL(singleton_class)->num_entries = 0;
#ifndef RUBY_VM
  rb_thread_critical = 1;
#endif
}
Example #26
0
VALUE
rb_module_new(void)
{
    VALUE mdl = class_alloc(T_MODULE, rb_cModule);

    RCLASS_M_TBL(mdl) = st_init_numtable();

    return (VALUE)mdl;
}
Example #27
0
static void
remove_method(VALUE klass, ID mid)
{
    st_data_t data;
    NODE *body = 0;

    if (klass == rb_cObject) {
	rb_secure(4);
    }
    if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
	rb_raise(rb_eSecurityError, "Insecure: can't remove method");
    }
    if (OBJ_FROZEN(klass))
	rb_error_frozen("class/module");
    if (mid == object_id || mid == __send__ || mid == idInitialize) {
	rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
    }
    if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
	body = (NODE *)data;
	if (!body || !body->nd_body) body = 0;
	else {
	    st_delete(RCLASS_M_TBL(klass), &mid, &data);
	}
    }
    if (!body) {
	rb_name_error(mid, "method `%s' not defined in %s",
		      rb_id2name(mid), rb_class2name(klass));
    }

    if (nd_type(body->nd_body->nd_body) == NODE_CFUNC) {
	rb_vm_check_redefinition_opt_method(body);
    }

    rb_clear_cache_for_undef(klass, mid);
    if (FL_TEST(klass, FL_SINGLETON)) {
	rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1,
		   ID2SYM(mid));
    }
    else {
	rb_funcall(klass, removed, 1, ID2SYM(mid));
    }
}
Example #28
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_SUPER(klass) = super;
    RCLASS_M_TBL(klass) = st_init_numtable();

    OBJ_INFECT(klass, super);
    return (VALUE)klass;
}
Example #29
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(clone) = st_init_numtable();
	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;
    }
}
Example #30
0
static inline rb_method_entry_t *
lookup_method_table(VALUE klass, ID id)
{
    st_data_t body;
    st_table *m_tbl = RCLASS_M_TBL(klass);
    if (st_lookup(m_tbl, id, &body)) {
	return (rb_method_entry_t *) body;
    }
    else {
	return 0;
    }
}