summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-08-01 22:17:51 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2017-08-01 22:25:49 +0900
commitda24af34b9c46120376fdf3e42dd5c9949fecd5c (patch)
treefc1ec07883875bbd01d5505de4bb9dc25316e579
parent2170fad406ecbb7a9ace6f762a376b3bdc860352 (diff)
downloadmruby-da24af34b9c46120376fdf3e42dd5c9949fecd5c.tar.gz
mruby-da24af34b9c46120376fdf3e42dd5c9949fecd5c.zip
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.
-rw-r--r--include/mruby/class.h3
-rw-r--r--include/mruby/variable.h1
-rw-r--r--mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c17
-rw-r--r--src/class.c101
-rw-r--r--src/variable.c70
5 files changed, 81 insertions, 111 deletions
diff --git a/include/mruby/class.h b/include/mruby/class.h
index 0526386d6..0853bd7f4 100644
--- a/include/mruby/class.h
+++ b/include/mruby/class.h
@@ -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*);
diff --git a/include/mruby/variable.h b/include/mruby/variable.h
index 2f2bbbf98..addd5f703 100644
--- a/include/mruby/variable.h
+++ b/include/mruby/variable.h
@@ -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*);
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c b/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
index 4553a965a..a948216e9 100644
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
@@ -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;
}
diff --git a/src/class.c b/src/class.c
index f2fc126ef..97a4c9c57 100644
--- a/src/class.c
+++ b/src/class.c
@@ -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);
diff --git a/src/variable.c b/src/variable.c
index b700081a5..91081e867 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -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;
+ 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;
+}
- arg.c = c;
- arg.sym = 0;
- iv_foreach(mrb, outer->iv, csym_i, &arg);
- return arg.sym;
- }
- }
- return mrb_symbol(name);
+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;
}