示例#1
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;
}
示例#2
0
文件: class.c 项目: technohippy/oruby
/* :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;
}
示例#3
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);
}
示例#4
0
文件: class.c 项目: technohippy/oruby
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;
}
示例#5
0
文件: class.c 项目: technohippy/oruby
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;
    }
}
示例#6
0
文件: evilr.c 项目: jeremyevans/evilr
/* call-seq:
 *   singleton_class_instance -> Object || nil
 * 
 * Returns the object attached to the singleton class.
 * If the class does not have an object attached to it (possibly because
 * it isn't a singleton class), returns +nil+. */
static VALUE evilr_singleton_class_instance(VALUE klass) {
  VALUE obj;
  if(RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass), evilr__attached, &obj)) {
    return obj;
  }
  return Qnil;
}
示例#7
0
static VALUE
find_class_path(VALUE klass)
{
    struct fc_result arg;

    arg.name = 0;
    arg.path = 0;
    arg.klass = klass;
    arg.track = rb_cObject;
    arg.prev = 0;
    if (RCLASS_CONST_TBL(rb_cObject)) {
	st_foreach_safe(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg);
    }
    if (arg.path == 0) {
	st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg);
    }
    if (arg.path) {
	st_data_t tmp = tmp_classpath;
	if (!RCLASS_IV_TBL(klass)) {
	    RCLASS_IV_TBL(klass) = st_init_numtable();
	}
	st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, arg.path);
	st_delete(RCLASS_IV_TBL(klass), &tmp, 0);
	return arg.path;
    }
    return Qnil;
}
示例#8
0
static VALUE
classname(VALUE klass)
{
    VALUE path = Qnil;
    st_data_t n;

    if (!klass) klass = rb_cObject;
    if (RCLASS_IV_TBL(klass)) {
	if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classpath, &n)) {
	    if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classid, &n)) {
		return find_class_path(klass);
	    }
	    path = rb_str_dup(rb_id2str(SYM2ID((VALUE)n)));
	    OBJ_FREEZE(path);
	    st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, (st_data_t)path);
	    n = classid;
	    st_delete(RCLASS_IV_TBL(klass), &n, 0);
	}
	else {
	    path = (VALUE)n;
	}
	if (TYPE(path) != T_STRING) {
	    rb_bug("class path is not set properly");
	}
	return path;
    }
    return find_class_path(klass);
}
示例#9
0
VALUE
rb_class_path(VALUE klass)
{
    VALUE path = classname(klass);
    st_data_t n = (st_data_t)path;

    if (!NIL_P(path)) return path;
    if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),
					  (st_data_t)tmp_classpath, &n)) {
	return (VALUE)n;
    }
    else {
	const char *s = "Class";

	if (TYPE(klass) == T_MODULE) {
	    if (rb_obj_class(klass) == rb_cModule) {
		s = "Module";
	    }
	    else {
		s = rb_class2name(RBASIC(klass)->klass);
	    }
	}
	path = rb_sprintf("#<%s:%p>", s, (void*)klass);
	OBJ_FREEZE(path);
	rb_ivar_set(klass, tmp_classpath, path);

	return path;
    }
}
示例#10
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;
}
示例#11
0
static VALUE
fc_path(struct fc_result *fc, ID name)
{
    VALUE path, tmp;

    path = rb_str_dup(rb_id2str(name));
    while (fc) {
	st_data_t n;
	if (fc->track == rb_cObject) break;
	if (RCLASS_IV_TBL(fc->track) &&
	    st_lookup(RCLASS_IV_TBL(fc->track), (st_data_t)classpath, &n)) {
	    tmp = rb_str_dup((VALUE)n);
	    rb_str_cat2(tmp, "::");
	    rb_str_append(tmp, path);
	    path = tmp;
	    break;
	}
	tmp = rb_str_dup(rb_id2str(fc->name));
	rb_str_cat2(tmp, "::");
	rb_str_append(tmp, path);
	path = tmp;
	fc = fc->prev;
    }
    OBJ_FREEZE(path);
    return path;
}
示例#12
0
文件: evilr.c 项目: jeremyevans/evilr
/* call-seq:
 *   detach_singleton -> self
 *
 * If the receiver is a singleton class, it is transformed into a
 * regular class and it is detached from the instance.  Note that
 * this means it becomes the class of the object to which it was previous
 * attached.  If the receiver is not a singleton class, has no effect.
 * Returns the receiver. */
static VALUE evilr_detach_singleton(VALUE klass) {
  if (IS_SINGLETON_CLASS(klass)) {
    FL_UNSET(klass, FL_SINGLETON);
    if (RCLASS_IV_TBL(klass)) {
      st_delete(RCLASS_IV_TBL(klass), (st_data_t*)&evilr__attached, 0);
    }
  }
  return klass;
}
示例#13
0
文件: class.c 项目: fi8on/ruby
/*!
 * Attach a object to a singleton class.
 * @pre \a klass is the singleton class of \a obj.
 */
void
rb_singleton_class_attached(VALUE klass, VALUE obj)
{
    if (FL_TEST(klass, FL_SINGLETON)) {
	if (!RCLASS_IV_TBL(klass)) {
	    RCLASS_IV_TBL(klass) = st_init_numtable();
	}
	st_insert(RCLASS_IV_TBL(klass), id_attached, obj);
    }
}
示例#14
0
文件: class.c 项目: technohippy/oruby
void
rb_singleton_class_attached(VALUE klass, VALUE obj)
{
    if (FL_TEST(klass, FL_SINGLETON)) {
	ID attached;
	if (!RCLASS_IV_TBL(klass)) {
	    RCLASS_IV_TBL(klass) = st_init_numtable();
	}
	CONST_ID(attached, "__attached__");
	st_insert(RCLASS_IV_TBL(klass), attached, obj);
    }
}
示例#15
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;
}
示例#16
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;
}
示例#17
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
}
示例#18
0
文件: evilr.c 项目: jeremyevans/evilr
/* call-seq:
 *   swap_instance_variables(other) -> self
 * 
 * Swaps only the instance variables of the receiver and +other+.
 * You can only swap the instance variables between two objects that
 * use the internal type number T_OBJECT, or between Classes and Modules.
 * You cannot swap instance variables of immediate values, since they
 * do not have instance variables. Invalid swap attempts will raise
 * +TypeError+. */
static VALUE evilr_swap_instance_variables(VALUE self, VALUE other) {
#ifndef RUBY19
  struct st_table *tmp;
#endif
  evilr__check_immediates(self, other);

  switch(BUILTIN_TYPE(self)) {
    case T_OBJECT:
      if (BUILTIN_TYPE(other) != T_OBJECT) {
        goto bad_types;
      }
      break;
    case T_MODULE:
    case T_CLASS:
      if (BUILTIN_TYPE(other) != T_MODULE && BUILTIN_TYPE(other) != T_CLASS) {
        goto bad_types;
      }
      break;
    default:
bad_types:
      rb_raise(rb_eTypeError, "incompatible types used");
  }

#ifdef RUBY19
  if (BUILTIN_TYPE(self) == T_MODULE || BUILTIN_TYPE(self) == T_CLASS) {
    struct st_table *tmp;
    tmp = RCLASS_IV_TBL(self);
    RCLASS(self)->ptr->iv_tbl = RCLASS_IV_TBL(other);
    RCLASS(other)->ptr->iv_tbl = tmp;
  } else {
    char tmp[OBJECT_SIZE];
    memcpy(tmp, &(ROBJECT(self)->as), sizeof(ROBJECT(tmp)->as));
    memcpy(&(ROBJECT(self)->as), &(ROBJECT(other)->as), sizeof(ROBJECT(self)->as));
    memcpy(&(ROBJECT(other)->as), tmp, sizeof(ROBJECT(other)->as));
  }
#else
  /* RClass and RObject have iv_tbl at same position in the structure
   * so no funny business is needed */
  tmp = ROBJECT_IVPTR(self);
  ROBJECT(self)->iv_tbl = ROBJECT_IVPTR(other);
  ROBJECT(other)->iv_tbl = tmp;
#endif
  return self;
}
示例#19
0
VALUE Looksee_singleton_instance(VALUE self, VALUE klass) {
  if (!SPECIAL_CONST_P(klass) && BUILTIN_TYPE(klass) == T_CLASS && FL_TEST(klass, FL_SINGLETON)) {
    VALUE object;
    if (!Looksee_method_table_lookup(RCLASS_IV_TBL(klass), rb_intern("__attached__"), (st_data_t *)&object))
      rb_raise(rb_eRuntimeError, "[looksee bug] can't find singleton object");
    return object;
  } else {
    return Qnil;
  }
}
示例#20
0
文件: mri.c 项目: hkraji/looksee
VALUE Looksee_singleton_instance(VALUE self, VALUE singleton_class) {
  if (BUILTIN_TYPE(singleton_class) == T_CLASS && FL_TEST(singleton_class, FL_SINGLETON)) {
    VALUE object;
    if (!Looksee_method_table_lookup(RCLASS_IV_TBL(singleton_class), rb_intern("__attached__"), (st_data_t *)&object))
      rb_raise(rb_eRuntimeError, "[looksee bug] can't find singleton object");
    return object;
  } else {
    rb_raise(rb_eTypeError, "expected singleton class, got %s", rb_obj_classname(singleton_class));
  }
}
示例#21
0
static int
fc_i(ID key, VALUE value, struct fc_result *res)
{
    if (!rb_is_const_id(key)) return ST_CONTINUE;

    if (value == res->klass) {
	res->path = fc_path(res, key);
	return ST_STOP;
    }
    switch (TYPE(value)) {
      case T_MODULE:
      case T_CLASS:
	if (!RCLASS_IV_TBL(value)) return ST_CONTINUE;
	else {
	    struct fc_result arg;
	    struct fc_result *list;

	    list = res;
	    while (list) {
		if (list->track == value) return ST_CONTINUE;
		list = list->prev;
	    }

	    arg.name = key;
	    arg.path = 0;
	    arg.klass = res->klass;
	    arg.track = value;
	    arg.prev = res;
	    st_foreach(RCLASS_IV_TBL(value), fc_i, (st_data_t)&arg);
	    if (arg.path) {
		res->path = arg.path;
		return ST_STOP;
	    }
	}
	break;

      default:
	break;
    }
    return ST_CONTINUE;
}
示例#22
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;
    }
}
示例#23
0
文件: class.c 项目: technohippy/oruby
/**
 * 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)
{
    rb_classext_t *ext = ALLOC(rb_classext_t);
    NEWOBJ(obj, struct RClass);
    OBJSETUP(obj, klass, flags);
    obj->ptr = ext;
    RCLASS_IV_TBL(obj) = 0;
    RCLASS_M_TBL(obj) = 0;
    RCLASS_SUPER(obj) = 0;
    RCLASS_IV_INDEX_TBL(obj) = 0;
    return (VALUE)obj;
}
示例#24
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;
}
示例#25
0
文件: class.c 项目: takuto-h/ruby
/**
 * 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;
}
示例#26
0
static void restore_class(VALUE ruby_class_restorer)
{
  struct Class_Restorer * class_restorer;
  struct RClass * klass;

  Data_Get_Struct(
      ruby_class_restorer,
      struct Class_Restorer,
      class_restorer);
  klass = RCLASS(class_restorer->klass);
  *RCLASS_M_TBL(klass) = class_restorer->m_tbl;
  *RCLASS_IV_TBL(klass) = class_restorer->iv_tbl;
#ifndef RUBY_VM
  rb_thread_critical = class_restorer->thread_critical;
#endif
}
示例#27
0
/*
 *  call-seq:
 *     obj.instance_variable_defined?(symbol)    -> true or false
 *
 *  Returns <code>true</code> if the given instance variable is
 *  defined in <i>obj</i>.
 *
 *     class Fred
 *       def initialize(p1, p2)
 *         @a, @b = p1, p2
 *       end
 *     end
 *     fred = Fred.new('cat', 99)
 *     fred.instance_variable_defined?(:@a)    #=> true
 *     fred.instance_variable_defined?("@b")   #=> true
 *     fred.instance_variable_defined?("@c")   #=> false
 */
mrb_value
mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self)
{
  mrb_value arg;
  khiter_t k;
  kh_iv_t *h = RCLASS_IV_TBL(self);

  mrb_get_args(mrb, "o", &arg);
  mrb_sym mid = mrb_to_id(mrb, arg);

  if (h) {
    k = kh_get(iv, h, mid);
    if (k != kh_end(h)) {
      return mrb_true_value();
    }
  }
  return mrb_false_value();
}
示例#28
0
static VALUE class_alloc(VALUE flags, VALUE klass)
{
#ifdef RUBY_193
    rb_deprecated_classext_t *ext = ALLOC(rb_deprecated_classext_t);
#else
    rb_classext_t *ext = ALLOC(rb_classext_t);
#endif
    NEWOBJ(obj, struct RClass);
    OBJSETUP(obj, klass, flags);
    obj->ptr = ext;
    RCLASS_IV_TBL(obj) = 0;
    RCLASS_M_TBL(obj) = 0;
    RCLASS_SUPER(obj) = 0;
#ifndef RUBY_193
    RCLASS_IV_INDEX_TBL(obj) = 0;
#endif
    return (VALUE)obj;
}
示例#29
0
文件: class.c 项目: 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;
}
示例#30
0
文件: kernel.c 项目: beeplove/mruby
/*
 *  call-seq:
 *     obj.instance_variables    -> array
 *
 *  Returns an array of instance variable names for the receiver. Note
 *  that simply defining an accessor does not create the corresponding
 *  instance variable.
 *
 *     class Fred
 *       attr_accessor :a1
 *       def initialize
 *         @iv = 3
 *       end
 *     end
 *     Fred.new.instance_variables   #=> [:@iv]
 */
mrb_value
mrb_obj_instance_variables(mrb_state *mrb, mrb_value self)
{
    mrb_value ary;
    kh_iv_t *h = RCLASS_IV_TBL(self);
    int i;
    const char* p;

    ary = mrb_ary_new(mrb);
    if (h) {
      for (i=0;i<kh_end(h);i++) {
        if (kh_exist(h, i)) {
          p = mrb_sym2name(mrb, kh_key(h,i));
          if (*p == '@') {
            if (mrb_type(kh_value(h, i)) != MRB_TT_UNDEF)
              mrb_ary_push(mrb, ary, mrb_str_new_cstr(mrb, p));
          }
        }
      }
    }
    return ary;
}