mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Better class name management.
The change removes several internal instance variables used by class name management. The variables `__classid__` and `__classpath__` are no longer available. `__outer__` is used only for unnamed outer classes/modules (and will be removed after they are named). [Important note] Along with this change we removed several public functions. - mrb_class_outer_module() - mrb_class_sym() We believe no one have used those functions, but if you do, please ask us for the workaround.
This commit is contained in:
@@ -75,12 +75,13 @@ MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, struct R
|
||||
MRB_API void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec);
|
||||
MRB_API void mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b);
|
||||
|
||||
MRB_API struct RClass *mrb_class_outer_module(mrb_state*, struct RClass *);
|
||||
MRB_API struct RProc *mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym);
|
||||
MRB_API struct RProc *mrb_method_search(mrb_state*, struct RClass*, mrb_sym);
|
||||
|
||||
MRB_API struct RClass* mrb_class_real(struct RClass* cl);
|
||||
|
||||
void mrb_class_name_class(mrb_state*, struct RClass*, struct RClass*, mrb_sym);
|
||||
mrb_value mrb_class_find_path(mrb_state*, struct RClass*);
|
||||
void mrb_gc_mark_mt(mrb_state*, struct RClass*);
|
||||
size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
|
||||
void mrb_gc_free_mt(mrb_state*, struct RClass*);
|
||||
|
||||
@@ -126,7 +126,6 @@ mrb_value mrb_obj_instance_variables(mrb_state*, mrb_value);
|
||||
mrb_value mrb_mod_class_variables(mrb_state*, mrb_value);
|
||||
mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym);
|
||||
mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym);
|
||||
mrb_sym mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer);
|
||||
|
||||
/* GC functions */
|
||||
void mrb_gc_mark_gv(mrb_state*);
|
||||
|
||||
@@ -112,17 +112,6 @@ check_file_lineno(struct mrb_irep *irep, const char *file, uint16_t lineno)
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char*
|
||||
get_class_name(mrb_state *mrb, struct RClass *class_obj)
|
||||
{
|
||||
struct RClass *outer;
|
||||
mrb_sym class_sym;
|
||||
|
||||
outer = mrb_class_outer_module(mrb, class_obj);
|
||||
class_sym = mrb_class_sym(mrb, class_obj, outer);
|
||||
return mrb_sym2name(mrb, class_sym);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc)
|
||||
{
|
||||
@@ -139,7 +128,7 @@ compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *cl
|
||||
|
||||
method_p = &bp->point.methodpoint;
|
||||
if (strcmp(method_p->method_name, method_name) == 0) {
|
||||
class_name = get_class_name(mrb, class_obj);
|
||||
class_name = mrb_class_name(mrb, class_obj);
|
||||
if (class_name == NULL) {
|
||||
if (method_p->class_name == NULL) {
|
||||
return bp->bpno;
|
||||
@@ -166,8 +155,8 @@ compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *cl
|
||||
return MRB_DEBUG_OK;
|
||||
}
|
||||
|
||||
class_name = get_class_name(mrb, class_obj);
|
||||
sn = get_class_name(mrb, sc);
|
||||
class_name = mrb_class_name(mrb, class_obj);
|
||||
sn = mrb_class_name(mrb, sc);
|
||||
if (strcmp(sn, class_name) == 0) {
|
||||
return bp->bpno;
|
||||
}
|
||||
|
||||
+37
-64
@@ -50,22 +50,36 @@ mrb_gc_free_mt(mrb_state *mrb, struct RClass *c)
|
||||
kh_destroy(mt, mrb, c->mt);
|
||||
}
|
||||
|
||||
static void
|
||||
name_class(mrb_state *mrb, struct RClass *c, mrb_sym name)
|
||||
void
|
||||
mrb_class_name_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb_sym id)
|
||||
{
|
||||
mrb_obj_iv_set(mrb, (struct RObject*)c,
|
||||
mrb_intern_lit(mrb, "__classid__"), mrb_symbol_value(name));
|
||||
mrb_value name;
|
||||
mrb_sym nsym = mrb_intern_lit(mrb, "__classname__");
|
||||
|
||||
if (mrb_obj_iv_defined(mrb, (struct RObject*)c, nsym)) return;
|
||||
if (outer == NULL || outer == mrb->object_class) {
|
||||
name = mrb_symbol_value(id);
|
||||
}
|
||||
else {
|
||||
name = mrb_class_path(mrb, outer);
|
||||
if (mrb_nil_p(name)) { /* unnamed outer class */
|
||||
if (outer != mrb->object_class) {
|
||||
mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"),
|
||||
mrb_obj_value(outer));
|
||||
}
|
||||
return;
|
||||
}
|
||||
mrb_str_cat_cstr(mrb, name, "::");
|
||||
mrb_str_cat_cstr(mrb, name, mrb_sym2name(mrb, id));
|
||||
}
|
||||
mrb_obj_iv_set(mrb, (struct RObject*)c, nsym, name);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb_sym id)
|
||||
{
|
||||
name_class(mrb, c, id);
|
||||
mrb_class_name_class(mrb, outer, c, id);
|
||||
mrb_obj_iv_set(mrb, (struct RObject*)outer, id, mrb_obj_value(c));
|
||||
if (outer != mrb->object_class) {
|
||||
mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"),
|
||||
mrb_obj_value(outer));
|
||||
}
|
||||
}
|
||||
|
||||
#define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c))
|
||||
@@ -136,27 +150,6 @@ class_ptr_p(mrb_value obj)
|
||||
}
|
||||
}
|
||||
|
||||
MRB_API struct RClass*
|
||||
mrb_class_outer_module(mrb_state *mrb, struct RClass *c)
|
||||
{
|
||||
mrb_value outer;
|
||||
struct RClass *cls;
|
||||
|
||||
outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"));
|
||||
if (mrb_nil_p(outer)) return NULL;
|
||||
cls = mrb_class_ptr(outer);
|
||||
if (cls->tt == MRB_TT_SCLASS)
|
||||
{
|
||||
mrb_value klass;
|
||||
klass = mrb_obj_iv_get(mrb, (struct RObject *)cls,
|
||||
mrb_intern_lit(mrb, "__attached__"));
|
||||
if (class_ptr_p(klass)) {
|
||||
cls = mrb_class_ptr(klass);
|
||||
}
|
||||
}
|
||||
return cls;
|
||||
}
|
||||
|
||||
static void
|
||||
check_if_class_or_module(mrb_state *mrb, mrb_value obj)
|
||||
{
|
||||
@@ -1601,40 +1594,20 @@ MRB_API mrb_value
|
||||
mrb_class_path(mrb_state *mrb, struct RClass *c)
|
||||
{
|
||||
mrb_value path;
|
||||
const char *name;
|
||||
mrb_sym classpath = mrb_intern_lit(mrb, "__classpath__");
|
||||
mrb_sym nsym = mrb_intern_lit(mrb, "__classname__");
|
||||
|
||||
path = mrb_obj_iv_get(mrb, (struct RObject*)c, classpath);
|
||||
path = mrb_obj_iv_get(mrb, (struct RObject*)c, nsym);
|
||||
if (mrb_nil_p(path)) {
|
||||
struct RClass *outer = mrb_class_outer_module(mrb, c);
|
||||
mrb_sym sym = mrb_class_sym(mrb, c, outer);
|
||||
/* no name (yet) */
|
||||
return mrb_class_find_path(mrb, c);
|
||||
}
|
||||
else if (mrb_symbol_p(path)) {
|
||||
/* topleve class/module */
|
||||
const char *str;
|
||||
mrb_int len;
|
||||
|
||||
if (sym == 0) {
|
||||
return mrb_nil_value();
|
||||
}
|
||||
else if (outer && outer != c && outer != mrb->object_class) {
|
||||
mrb_value base = mrb_class_path(mrb, outer);
|
||||
path = mrb_str_buf_new(mrb, 0);
|
||||
if (mrb_nil_p(base)) {
|
||||
mrb_str_cat_lit(mrb, path, "#<Class:");
|
||||
mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, outer));
|
||||
mrb_str_cat_lit(mrb, path, ">");
|
||||
}
|
||||
else {
|
||||
mrb_str_concat(mrb, path, base);
|
||||
}
|
||||
mrb_str_cat_lit(mrb, path, "::");
|
||||
name = mrb_sym2name_len(mrb, sym, &len);
|
||||
mrb_str_cat(mrb, path, name, len);
|
||||
}
|
||||
else {
|
||||
name = mrb_sym2name_len(mrb, sym, &len);
|
||||
path = mrb_str_new(mrb, name, len);
|
||||
}
|
||||
if (!MRB_FROZEN_P(c)) {
|
||||
mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path);
|
||||
}
|
||||
str = mrb_sym2name_len(mrb, mrb_symbol(path), &len);
|
||||
return mrb_str_new(mrb, str, len);
|
||||
}
|
||||
return mrb_str_dup(mrb, path);
|
||||
}
|
||||
@@ -2338,10 +2311,10 @@ mrb_init_class(mrb_state *mrb)
|
||||
mrb_define_const(mrb, obj, "Class", mrb_obj_value(cls));
|
||||
|
||||
/* name each classes */
|
||||
name_class(mrb, bob, mrb_intern_lit(mrb, "BasicObject"));
|
||||
name_class(mrb, obj, mrb_intern_lit(mrb, "Object")); /* 15.2.1 */
|
||||
name_class(mrb, mod, mrb_intern_lit(mrb, "Module")); /* 15.2.2 */
|
||||
name_class(mrb, cls, mrb_intern_lit(mrb, "Class")); /* 15.2.3 */
|
||||
mrb_class_name_class(mrb, NULL, bob, mrb_intern_lit(mrb, "BasicObject"));
|
||||
mrb_class_name_class(mrb, NULL, obj, mrb_intern_lit(mrb, "Object")); /* 15.2.1 */
|
||||
mrb_class_name_class(mrb, NULL, mod, mrb_intern_lit(mrb, "Module")); /* 15.2.2 */
|
||||
mrb_class_name_class(mrb, NULL, cls, mrb_intern_lit(mrb, "Class")); /* 15.2.3 */
|
||||
|
||||
mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class); /* 15.2.17 */
|
||||
MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC);
|
||||
|
||||
+40
-32
@@ -869,18 +869,9 @@ mrb_vm_const_get(mrb_state *mrb, mrb_sym sym)
|
||||
MRB_API void
|
||||
mrb_const_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v)
|
||||
{
|
||||
mrb_sym id = mrb_intern_lit(mrb, "__classid__");
|
||||
|
||||
mod_const_check(mrb, mod);
|
||||
if ((mrb_type(v) == MRB_TT_CLASS || mrb_type(v) == MRB_TT_MODULE)
|
||||
&& !mrb_obj_iv_defined(mrb, mrb_obj_ptr(v), id)) {
|
||||
struct RObject *c = mrb_obj_ptr(v);
|
||||
|
||||
/* name unnamed classes/modules */
|
||||
mrb_obj_iv_set(mrb, c, id, mrb_symbol_value(sym));
|
||||
if (mrb_class_ptr(mod) != mrb->object_class) {
|
||||
mrb_obj_iv_set(mrb, c, mrb_intern_lit(mrb, "__outer__"), mod);
|
||||
}
|
||||
if (mrb_type(v) == MRB_TT_CLASS || mrb_type(v) == MRB_TT_MODULE) {
|
||||
mrb_class_name_class(mrb, mrb_class_ptr(mod), mrb_class_ptr(v), sym);
|
||||
}
|
||||
mrb_iv_set(mrb, mod, sym, v);
|
||||
}
|
||||
@@ -1077,37 +1068,54 @@ struct csym_arg {
|
||||
struct RClass *c;
|
||||
mrb_sym sym;
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
csym_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
|
||||
{
|
||||
struct csym_arg *a = (struct csym_arg*)p;
|
||||
struct RClass *c = a->c;
|
||||
|
||||
|
||||
if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) {
|
||||
a->sym = sym;
|
||||
return 1; /* stop iteration */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
mrb_sym
|
||||
mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer)
|
||||
|
||||
static mrb_sym
|
||||
find_class_sym(mrb_state *mrb, struct RClass *outer, struct RClass *c)
|
||||
{
|
||||
mrb_value name;
|
||||
|
||||
name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__classid__"));
|
||||
if (mrb_nil_p(name)) {
|
||||
|
||||
if (!outer) return 0;
|
||||
else {
|
||||
struct csym_arg arg;
|
||||
|
||||
arg.c = c;
|
||||
arg.sym = 0;
|
||||
iv_foreach(mrb, outer->iv, csym_i, &arg);
|
||||
return arg.sym;
|
||||
}
|
||||
}
|
||||
return mrb_symbol(name);
|
||||
struct csym_arg arg;
|
||||
|
||||
if (!outer) return 0;
|
||||
arg.c = c;
|
||||
arg.sym = 0;
|
||||
iv_foreach(mrb, outer->iv, csym_i, &arg);
|
||||
return arg.sym;
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_class_find_path(mrb_state *mrb, struct RClass *c)
|
||||
{
|
||||
mrb_value outer, path;
|
||||
mrb_sym name;
|
||||
const char *str;
|
||||
mrb_int len;
|
||||
mrb_sym osym = mrb_intern_lit(mrb, "__outer__");
|
||||
|
||||
outer = mrb_obj_iv_get(mrb, (struct RObject*)c, osym);
|
||||
if (mrb_nil_p(outer)) return outer;
|
||||
name = find_class_sym(mrb, mrb_class_ptr(outer), c);
|
||||
if (name == 0) return mrb_nil_value();
|
||||
str = mrb_class_name(mrb, mrb_class_ptr(outer));
|
||||
path = mrb_str_buf_new(mrb, 0);
|
||||
mrb_str_cat_cstr(mrb, path, str);
|
||||
mrb_str_cat_cstr(mrb, path, "::");
|
||||
|
||||
str = mrb_sym2name_len(mrb, name, &len);
|
||||
mrb_str_cat(mrb, path, str, len);
|
||||
iv_del(mrb, c->iv, osym, NULL);
|
||||
iv_put(mrb, c->iv, mrb_intern_lit(mrb, "__classname__"), path);
|
||||
mrb_field_write_barrier_value(mrb, (struct RBasic*)c, path);
|
||||
return path;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user