made mrb_define_class to return existing class, with heavy refactoring

parent 5da7bd3a
......@@ -662,7 +662,7 @@ mrb_mruby_time_gem_init(mrb_state* mrb)
/* ISO 15.2.19.2 */
tc = mrb_define_class(mrb, "Time", mrb->object_class);
MRB_SET_INSTANCE_TT(tc, MRB_TT_DATA);
mrb_include_module(mrb, tc, mrb_class_get(mrb, "Comparable"));
mrb_include_module(mrb, tc, mrb_module_get(mrb, "Comparable"));
mrb_define_class_method(mrb, tc, "at", mrb_time_at, MRB_ARGS_ANY()); /* 15.2.19.6.1 */
mrb_define_class_method(mrb, tc, "gm", mrb_time_gm, MRB_ARGS_ARG(1,6)); /* 15.2.19.6.2 */
mrb_define_class_method(mrb, tc, "local", mrb_time_local, MRB_ARGS_ARG(1,6)); /* 15.2.19.6.3 */
......
......@@ -95,8 +95,6 @@ end
##
# Array is enumerable and comparable
module Enumerable; end
module Comparable; end
class Array
# ISO 15.2.12.3
include Enumerable
......
......@@ -187,7 +187,6 @@ end
# Hash is enumerable
#
# ISO 15.2.13.3
module Enumerable; end
class Hash
include Enumerable
end
......@@ -43,7 +43,6 @@ end
# Range is enumerable
#
# ISO 15.2.14.3
module Enumerable; end
class Range
include Enumerable
end
......@@ -3,7 +3,7 @@
#
# ISO 15.2.10
class String
include Comparable
##
# Calls the given block for each line
# and pass the respective line.
......
......@@ -1199,7 +1199,6 @@ mrb_init_array(mrb_state *mrb)
a = mrb->array_class = mrb_define_class(mrb, "Array", mrb->object_class);
MRB_SET_INSTANCE_TT(a, MRB_TT_ARRAY);
mrb_include_module(mrb, a, mrb_class_get(mrb, "Enumerable"));
mrb_define_class_method(mrb, a, "[]", mrb_ary_s_create, MRB_ARGS_ANY()); /* 15.2.12.4.1 */
......
......@@ -56,6 +56,17 @@ name_class(mrb_state *mrb, struct RClass *c, mrb_sym name)
mrb_intern_lit(mrb, "__classid__"), mrb_symbol_value(name));
}
static void
setup_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb_sym id)
{
name_class(mrb, 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))
static void
......@@ -92,31 +103,22 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o)
mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern_lit(mrb, "__attached__"), mrb_obj_value(o));
}
struct RClass*
mrb_define_module_id(mrb_state *mrb, mrb_sym name)
static struct RClass *
class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
{
struct RClass *m = mrb_module_new(mrb);
mrb_obj_iv_set(mrb, (struct RObject*)mrb->object_class,
name, mrb_obj_value(m));
name_class(mrb, m, name);
mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
return m;
mrb_check_type(mrb, c, MRB_TT_CLASS);
return mrb_class_ptr(c);
}
struct RClass*
mrb_define_module(mrb_state *mrb, const char *name)
static struct RClass *
module_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
{
return mrb_define_module_id(mrb, mrb_intern_cstr(mrb, name));
}
mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
static void
setup_class(mrb_state *mrb, mrb_value outer, struct RClass *c, mrb_sym id)
{
name_class(mrb, c, id);
mrb_const_set(mrb, outer, id, mrb_obj_value(c));
mrb_obj_iv_set(mrb, (struct RObject*)c,
mrb_intern_lit(mrb, "__outer__"), outer);
mrb_check_type(mrb, c, MRB_TT_MODULE);
return mrb_class_ptr(c);
}
struct RClass*
......@@ -129,35 +131,78 @@ mrb_class_outer_module(mrb_state *mrb, struct RClass *c)
return mrb_class_ptr(outer);
}
static struct RClass*
define_module(mrb_state *mrb, mrb_sym name, struct RClass *outer)
{
struct RClass *m;
if (mrb_const_defined_at(mrb, outer, name)) {
return module_from_sym(mrb, outer, name);
}
m = mrb_module_new(mrb);
setup_class(mrb, outer, m, name);
return m;
}
struct RClass*
mrb_define_module_id(mrb_state *mrb, mrb_sym name)
{
return define_module(mrb, name, mrb->object_class);
}
struct RClass*
mrb_define_module(mrb_state *mrb, const char *name)
{
return define_module(mrb, mrb_intern_cstr(mrb, name), mrb->object_class);
}
struct RClass*
mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id)
{
struct RClass *c;
mrb_value v;
return define_module(mrb, id, mrb_class_ptr(outer));
}
if (mrb_const_defined(mrb, outer, id)) {
v = mrb_const_get(mrb, outer, id);
c = mrb_class_ptr(v);
}
else {
c = mrb_module_new(mrb);
setup_class(mrb, outer, c, id);
}
struct RClass *
mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name)
{
mrb_sym id = mrb_intern_cstr(mrb, name);
struct RClass * c = define_module(mrb, id, outer);
setup_class(mrb, outer, c, id);
return c;
}
struct RClass*
mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super)
static struct RClass*
define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass *outer)
{
struct RClass *c = mrb_class_new(mrb, super);
struct RClass * c;
mrb_obj_iv_set(mrb, (struct RObject*)mrb->object_class,
name, mrb_obj_value(c));
name_class(mrb, c, name);
if (mrb_const_defined_at(mrb, outer, name)) {
c = class_from_sym(mrb, outer, name);
if (super && mrb_class_real(c->super) != super) {
mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %S (%S not %S)",
mrb_sym2str(mrb, name),
mrb_obj_value(c->super), mrb_obj_value(super));
}
return c;
}
c = mrb_class_new(mrb, super);
setup_class(mrb, outer, c, name);
return c;
}
struct RClass*
mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super)
{
if (!super) {
mrb_warn(mrb, "no super class for `%S', Object assumed", mrb_sym2str(mrb, name));
}
return define_class(mrb, name, super, mrb->object_class);
}
struct RClass*
mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super)
{
......@@ -167,24 +212,8 @@ mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super)
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_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", super);
}
if (!c->super || mrb_class_ptr(super) != mrb_class_real(c->super)) {
mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %S", mrb_sym2str(mrb, id));
}
}
return c;
}
struct RClass *s;
struct RClass *c;
if (!mrb_nil_p(super)) {
if (mrb_type(super) != MRB_TT_CLASS) {
......@@ -193,12 +222,18 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id
s = mrb_class_ptr(super);
}
else {
s = mrb->object_class;
s = 0;
}
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));
switch (mrb_type(outer)) {
case MRB_TT_CLASS:
case MRB_TT_MODULE:
break;
default:
mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", outer);
break;
}
c = define_class(mrb, id, s, mrb_class_ptr(outer));
mrb_funcall(mrb, mrb_obj_value(mrb_class_real(c->super)), "inherited", 1, mrb_obj_value(c));
return c;
}
......@@ -213,15 +248,10 @@ mrb_class_defined(mrb_state *mrb, const char *name)
return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_symbol(sym));
}
static struct RClass *
class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
struct RClass *
mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
{
mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
if (mrb_type(c) != MRB_TT_MODULE && mrb_type(c) != MRB_TT_CLASS) {
mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", mrb_sym2str(mrb, id));
}
return mrb_class_ptr(c);
return class_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
}
struct RClass *
......@@ -231,9 +261,15 @@ mrb_class_get(mrb_state *mrb, const char *name)
}
struct RClass *
mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
{
return class_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
return module_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
}
struct RClass *
mrb_module_get(mrb_state *mrb, const char *name)
{
return mrb_module_get_under(mrb, mrb->object_class, name);
}
/*!
......@@ -255,38 +291,17 @@ mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
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_cstr(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_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name)
{
struct RClass * c;
mrb_sym id = mrb_intern_cstr(mrb, name);
if (mrb_const_defined_at(mrb, outer, id)) {
c = class_from_sym(mrb, outer, id);
return c;
#if 0
if (!super) {
mrb_warn(mrb, "no super class for `%S::%S', Object assumed",
mrb_obj_value(outer), mrb_sym2str(mrb, id));
}
c = mrb_module_new(mrb);
setup_class(mrb, mrb_obj_value(outer), c, id);
#endif
c = define_class(mrb, id, super, outer);
setup_class(mrb, outer, c, id);
return c;
}
......
......@@ -1227,7 +1227,6 @@ mrb_init_hash(mrb_state *mrb)
h = mrb->hash_class = mrb_define_class(mrb, "Hash", mrb->object_class);
MRB_SET_INSTANCE_TT(h, MRB_TT_HASH);
mrb_include_module(mrb, h, mrb_class_get(mrb, "Enumerable"));
mrb_define_method(mrb, h, "==", mrb_hash_equal, MRB_ARGS_REQ(1)); /* 15.2.13.4.1 */
mrb_define_method(mrb, h, "[]", mrb_hash_aget, MRB_ARGS_REQ(1)); /* 15.2.13.4.2 */
mrb_define_method(mrb, h, "[]=", mrb_hash_aset, MRB_ARGS_REQ(2)); /* 15.2.13.4.3 */
......
......@@ -403,8 +403,6 @@ mrb_init_range(mrb_state *mrb)
r = mrb_define_class(mrb, "Range", mrb->object_class);
MRB_SET_INSTANCE_TT(r, MRB_TT_RANGE);
mrb_include_module(mrb, r, mrb_class_get(mrb, "Enumerable"));
mrb_define_method(mrb, r, "begin", mrb_range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.3 */
mrb_define_method(mrb, r, "end", mrb_range_end, MRB_ARGS_NONE()); /* 15.2.14.4.5 */
mrb_define_method(mrb, r, "==", mrb_range_eq, MRB_ARGS_REQ(1)); /* 15.2.14.4.1 */
......
......@@ -2485,8 +2485,6 @@ mrb_init_string(mrb_state *mrb)
s = mrb->string_class = mrb_define_class(mrb, "String", mrb->object_class);
MRB_SET_INSTANCE_TT(s, MRB_TT_STRING);
mrb_include_module(mrb, s, mrb_class_get(mrb, "Comparable"));
mrb_define_method(mrb, s, "bytesize", mrb_str_bytesize, MRB_ARGS_NONE());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment