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:
Yukihiro "Matz" Matsumoto
2017-08-01 22:17:51 +09:00
parent 2170fad406
commit da24af34b9
5 changed files with 82 additions and 112 deletions
+2 -1
View File
@@ -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*);
-1
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}