/*! * Defines a class under the namespace of \a outer. * \param outer a class which contains the new class. * \param id 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. */ struct RClass * mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super) { struct RClass * c; mrb_sym id = mrb_intern(mrb, name); if (mrb_const_defined_at(mrb, outer, id)) { c = mrb_class_from_sym(mrb, outer, id); if (c->tt != MRB_TT_CLASS) { mrb_raise(mrb, E_TYPE_ERROR, "%s is not a class", mrb_sym2name(mrb, id)); } if (mrb_class_real(c->super) != super) { mrb_name_error(mrb, id, "%s is already defined", mrb_sym2name(mrb, id)); } return c; } if (!super) { mrb_warn("no super class for `%s::%s', Object assumed", mrb_obj_classname(mrb, mrb_obj_value(outer)), mrb_sym2name(mrb, id)); } c = mrb_class_new(mrb, super); setup_class(mrb, mrb_obj_value(outer), c, id); mrb_const_set(mrb, mrb_obj_value(outer), id, mrb_obj_value(c)); return c; }
static mrb_value make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * klass) { mrb_value nstr; mrb_sym id; struct RClass *c; if (mrb_nil_p(name)) { c = mrb_class_new(mrb, klass); } else { /* old style: should we warn? */ name = mrb_str_to_str(mrb, name); id = mrb_obj_to_sym(mrb, name); if (!is_const_id(mrb, mrb_sym2name_len(mrb, id, NULL))) { mrb_name_error(mrb, id, "identifier %S needs to be constant", name); } if (mrb_const_defined_at(mrb, mrb_obj_value(klass), id)) { mrb_warn(mrb, "redefining constant Struct::%S", name); /* ?rb_mod_remove_const(klass, mrb_sym2name(mrb, id)); */ } c = mrb_define_class_under(mrb, klass, RSTRING_PTR(name), klass); } MRB_SET_INSTANCE_TT(c, MRB_TT_ARRAY); nstr = mrb_obj_value(c); mrb_iv_set(mrb, nstr, mrb_intern_lit(mrb, "__members__"), members); mrb_define_class_method(mrb, c, "new", mrb_instance_new, MRB_ARGS_ANY()); mrb_define_class_method(mrb, c, "[]", mrb_instance_new, MRB_ARGS_ANY()); mrb_define_class_method(mrb, c, "members", mrb_struct_s_members_m, MRB_ARGS_NONE()); /* RSTRUCT(nstr)->basic.c->super = c->c; */ make_struct_define_accessors(mrb, members, c); return nstr; }
struct RClass* mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id) { struct RClass *c = 0; if (mrb_const_defined(mrb, outer, id)) { mrb_value v = mrb_const_get(mrb, outer, id); c = mrb_class_ptr(v); if (!mrb_nil_p(super) && (c->tt != MRB_TT_CLASS || c->super != mrb_class_ptr(super))) { c = 0; } } if (!c) { struct RClass *s = 0; if (!mrb_nil_p(super)) { mrb_check_type(mrb, super, MRB_TT_CLASS); s = mrb_class_ptr(super); } if (!s) { s = mrb->object_class; } c = mrb_class_new(mrb, s); setup_class(mrb, outer, c, id); mrb_funcall(mrb, mrb_obj_value(s), "inherited", 1, mrb_obj_value(c)); } return c; }
struct RClass* mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id) { struct RClass *c = 0; if (mrb_const_defined(mrb, outer, id)) { mrb_value v = mrb_const_get(mrb, outer, id); c = mrb_class_ptr(v); if (!mrb_nil_p(super) && (c->tt != MRB_TT_CLASS || c->super != mrb_class_ptr(super))) { c = 0; } } if (!c) { struct RClass *s = 0; if (!mrb_nil_p(super)) { mrb_check_type(mrb, super, MRB_TT_CLASS); s = mrb_class_ptr(super); } c = mrb_class_new(mrb, s); setup_class(mrb, outer, c, id); } return c; }
struct RClass* mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super) { struct RClass *c = mrb_class_new(mrb, super); mrb_obj_iv_set(mrb, (struct RObject*)mrb->object_class, name, mrb_obj_value(c)); mrb_name_class(mrb, c, name); return c; }
static mrb_value make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * klass) { mrb_value nstr, *ptr_members; mrb_sym id; long i, len; struct RClass *c; //OBJ_FREEZE(members); if (mrb_nil_p(name)) { c = mrb_class_new(mrb, klass); //mrb_make_metaclass(nstr, RBASIC(klass)->c); //mrb_class_inherited(klass, nstr); } else { /* old style: should we warn? */ name = mrb_str_to_str(mrb, name); id = mrb_to_id(mrb, name); if (!mrb_is_const_id(id)) { //mrb_name_error(id, "identifier %s needs to be constant", StringValuePtr(name)); mrb_name_error(mrb, id, "identifier %s needs to be constant", mrb_string_value_ptr(mrb, name)); } if (mrb_const_defined_at(mrb, klass, id)) { //mrb_warn("redefining constant Struct::%s", StringValuePtr(name)); mrb_warn("redefining constant Struct::%s", mrb_string_value_ptr(mrb, name)); //?rb_mod_remove_const(klass, mrb_sym2name(mrb, id)); } c = mrb_define_class_under(mrb, klass, RSTRING_PTR(name), klass); } MRB_SET_INSTANCE_TT(c, MRB_TT_STRUCT); nstr = mrb_obj_value(c); mrb_iv_set(mrb, nstr, mrb_intern(mrb, "__members__"), members); mrb_define_class_method(mrb, c, "new", mrb_class_new_instance_m, ARGS_ANY()); mrb_define_class_method(mrb, c, "[]", mrb_class_new_instance_m, ARGS_ANY()); mrb_define_class_method(mrb, c, "members", mrb_struct_s_members_m, ARGS_NONE()); //RSTRUCT(nstr)->basic.c->super = c->c; ptr_members = RARRAY_PTR(members); len = RARRAY_LEN(members); for (i=0; i< len; i++) { mrb_sym id = SYM2ID(ptr_members[i]); if (mrb_is_local_id(id) || mrb_is_const_id(id)) { if (i < N_REF_FUNC) { mrb_define_method_id(mrb, c, id, (mrb_func_t)ref_func[i], 0); } else { mrb_define_method_id(mrb, c, id, mrb_struct_ref, 0); } mrb_define_method_id(mrb, c, mrb_id_attrset(id), (mrb_func_t)mrb_struct_set, 1); } } return nstr; }
mrb_value mrb_class_new_class(mrb_state *mrb, mrb_value cv) { mrb_value super; struct RClass *new_class; if (mrb_get_args(mrb, "|o", &super) == 0) { super = mrb_obj_value(mrb->object_class); } new_class = mrb_class_new(mrb, mrb_class_ptr(super)); return mrb_obj_value(new_class); }
static mrb_value make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * klass) { mrb_value nstr, *ptr_members; mrb_sym id; mrb_int i, len; struct RClass *c; int ai; if (mrb_nil_p(name)) { c = mrb_class_new(mrb, klass); } else { /* old style: should we warn? */ name = mrb_str_to_str(mrb, name); id = mrb_obj_to_sym(mrb, name); if (!mrb_is_const_id(id)) { mrb_name_error(mrb, id, "identifier %S needs to be constant", name); } if (mrb_const_defined_at(mrb, klass, id)) { mrb_warn(mrb, "redefining constant Struct::%S", name); /* ?rb_mod_remove_const(klass, mrb_sym2name(mrb, id)); */ } c = mrb_define_class_under(mrb, klass, RSTRING_PTR(name), klass); } MRB_SET_INSTANCE_TT(c, MRB_TT_ARRAY); nstr = mrb_obj_value(c); mrb_iv_set(mrb, nstr, mrb_intern_lit(mrb, "__members__"), members); mrb_define_class_method(mrb, c, "new", mrb_instance_new, MRB_ARGS_ANY()); mrb_define_class_method(mrb, c, "[]", mrb_instance_new, MRB_ARGS_ANY()); mrb_define_class_method(mrb, c, "members", mrb_struct_s_members_m, MRB_ARGS_NONE()); /* RSTRUCT(nstr)->basic.c->super = c->c; */ ptr_members = RARRAY_PTR(members); len = RARRAY_LEN(members); ai = mrb_gc_arena_save(mrb); for (i=0; i< len; i++) { mrb_sym id = mrb_symbol(ptr_members[i]); if (mrb_is_local_id(id) || mrb_is_const_id(id)) { if (i < N_REF_FUNC) { mrb_define_method_id(mrb, c, id, ref_func[i], MRB_ARGS_NONE()); } else { mrb_define_method_id(mrb, c, id, mrb_struct_ref, MRB_ARGS_NONE()); } mrb_define_method_id(mrb, c, mrb_id_attrset(mrb, id), mrb_struct_set_m, MRB_ARGS_REQ(1)); mrb_gc_arena_restore(mrb, ai); } } return nstr; }
/*! * Defines a class under the namespace of \a outer. * \param outer a class which contains the new class. * \param id 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. */ struct RClass * mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super) { struct RClass * c; mrb_sym id = mrb_intern(mrb, name); if (mrb_const_defined_at(mrb, outer, id)) { c = class_from_sym(mrb, outer, id); if (mrb_class_real(c->super) != super) { mrb_name_error(mrb, id, "%S is already defined", name); } return c; } if (!super) { mrb_warn(mrb, "no super class for `%S::%S', Object assumed", outer, name); } c = mrb_class_new(mrb, super); setup_class(mrb, mrb_obj_value(outer), c, id); return c; }
struct RClass* mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id) { struct RClass *c, *s; if (mrb_const_defined(mrb, outer, id)) { mrb_value v = mrb_const_get(mrb, outer, id); mrb_check_type(mrb, v, MRB_TT_CLASS); c = mrb_class_ptr(v); if (!mrb_nil_p(super)) { if (mrb_type(super) != MRB_TT_CLASS) { mrb_raise(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super)); } if (!c->super || mrb_class_ptr(super) != mrb_class_real(c->super)) { mrb_raise(mrb, E_TYPE_ERROR, "superclass mismatch for class %s", mrb_sym2name(mrb, id)); } } return c; } if (!mrb_nil_p(super)) { if (mrb_type(super) != MRB_TT_CLASS) { mrb_raise(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super)); } s = mrb_class_ptr(super); } else { s = mrb->object_class; } c = mrb_class_new(mrb, s); setup_class(mrb, outer, c, id); mrb_funcall(mrb, mrb_obj_value(s), "inherited", 1, mrb_obj_value(c)); return c; }