static VALUE make_struct(VALUE name, VALUE members, VALUE klass) { VALUE nstr, *ptr_members; ID id; long i, len; OBJ_FREEZE(members); if (NIL_P(name)) { nstr = rb_class_new(klass); rb_make_metaclass(nstr, RBASIC(klass)->klass); rb_class_inherited(klass, nstr); } else { /* old style: should we warn? */ name = rb_str_to_str(name); id = rb_to_id(name); if (!rb_is_const_id(id)) { rb_name_error(id, "identifier %s needs to be constant", StringValuePtr(name)); } if (rb_const_defined_at(klass, id)) { rb_warn("redefining constant Struct::%s", StringValuePtr(name)); rb_mod_remove_const(klass, ID2SYM(id)); } nstr = rb_define_class_id_under(klass, id, klass); } rb_ivar_set(nstr, id_members, members); rb_define_alloc_func(nstr, struct_alloc); rb_define_singleton_method(nstr, "new", rb_class_new_instance, -1); rb_define_singleton_method(nstr, "[]", rb_class_new_instance, -1); rb_define_singleton_method(nstr, "members", rb_struct_s_members_m, 0); ptr_members = RARRAY_PTR(members); len = RARRAY_LEN(members); for (i=0; i< len; i++) { ID id = SYM2ID(ptr_members[i]); if (rb_is_local_id(id) || rb_is_const_id(id)) { if (i < N_REF_FUNC) { rb_define_method_id(nstr, id, ref_func[i], 0); } else { rb_define_method_id(nstr, id, rb_struct_ref, 0); } rb_define_method_id(nstr, rb_id_attrset(id), rb_struct_set, 1); } } return nstr; }
static VALUE new_struct(VALUE name, VALUE super) { /* old style: should we warn? */ ID id; name = rb_str_to_str(name); if (!rb_is_const_name(name)) { rb_name_error_str(name, "identifier %"PRIsVALUE" needs to be constant", QUOTE(name)); } id = rb_to_id(name); if (rb_const_defined_at(super, id)) { rb_warn("redefining constant %"PRIsVALUE"::%"PRIsVALUE, super, name); rb_mod_remove_const(super, ID2SYM(id)); } return rb_define_class_id_under(super, id, super); }
VALUE rb_define_class_under(VALUE module, const char *name, VALUE superclass) { return rb_define_class_id_under(module, rb_str_new_cstr(name), superclass); }
/*! * Defines a class under the namespace of \a outer. * \param outer a class which contains the new class. * \param name name of the new class * \param super a class from which the new class will derive. * NULL means \c Object class. * \return the created class * \throw TypeError if the constant name \a name is already taken but * the constant is not a \c Class. * \throw NameError if the class is already defined but the class can not * be reopened because its superclass is not \a super. * \post top-level constant named \a name refers the returned class. * * \note if a class named \a name is already defined and its superclass is * \a super, the function just returns the defined class. */ VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super) { return rb_define_class_id_under(outer, rb_intern(name), super); }