diff options
Diffstat (limited to 'src/class.c')
| -rw-r--r-- | src/class.c | 537 |
1 files changed, 295 insertions, 242 deletions
diff --git a/src/class.c b/src/class.c index 4994b0045..33515de2c 100644 --- a/src/class.c +++ b/src/class.c @@ -4,18 +4,19 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#include <stdarg.h> #include <ctype.h> +#include <stdarg.h> +#include "mruby.h" #include "mruby/array.h" #include "mruby/class.h" #include "mruby/numeric.h" #include "mruby/proc.h" #include "mruby/string.h" #include "mruby/variable.h" -#include "error.h" +#include "mruby/error.h" +#include "mruby/data.h" -KHASH_DEFINE(mt, mrb_sym, struct RProc*, 1, kh_int_hash_func, kh_int_hash_equal) +KHASH_DEFINE(mt, mrb_sym, struct RProc*, TRUE, kh_int_hash_func, kh_int_hash_equal) void mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c) @@ -46,16 +47,27 @@ mrb_gc_mark_mt_size(mrb_state *mrb, struct RClass *c) void mrb_gc_free_mt(mrb_state *mrb, struct RClass *c) { - kh_destroy(mt, c->mt); + kh_destroy(mt, mrb, c->mt); } -void -mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name) +static void +name_class(mrb_state *mrb, struct RClass *c, mrb_sym name) { mrb_obj_iv_set(mrb, (struct RObject*)c, - mrb_intern2(mrb, "__classid__", 11), mrb_symbol_value(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 @@ -89,34 +101,25 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o) o->c = sc; mrb_field_write_barrier(mrb, (struct RBasic*)o, (struct RBasic*)sc); mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)o); - mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern2(mrb, "__attached__", 12), mrb_obj_value(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)); - mrb_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) -{ - mrb_name_class(mrb, c, id); - mrb_const_set(mrb, outer, id, mrb_obj_value(c)); - mrb_obj_iv_set(mrb, (struct RObject*)c, - mrb_intern2(mrb, "__outer__", 9), outer); + mrb_check_type(mrb, c, MRB_TT_MODULE); + return mrb_class_ptr(c); } struct RClass* @@ -124,41 +127,84 @@ mrb_class_outer_module(mrb_state *mrb, struct RClass *c) { mrb_value outer; - outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern2(mrb, "__outer__", 9)); + outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__")); if (mrb_nil_p(outer)) return 0; 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; + + 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; + } - mrb_obj_iv_set(mrb, (struct RObject*)mrb->object_class, - name, mrb_obj_value(c)); - mrb_name_class(mrb, c, name); + 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) { return mrb_define_class_id(mrb, mrb_intern_cstr(mrb, name), super); @@ -167,24 +213,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 +223,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 +249,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 +262,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 +292,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; } @@ -297,7 +313,7 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RPro khiter_t k; if (!h) h = c->mt = kh_init(mt, mrb); - k = kh_put(mt, h, mid); + k = kh_put(mt, mrb, h, mid); kh_value(h, k) = p; if (p) { mrb_field_write_barrier(mrb, (struct RBasic *)c, (struct RBasic *)p); @@ -311,6 +327,7 @@ mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t f int ai = mrb_gc_arena_save(mrb); p = mrb_proc_new_cfunc(mrb, func); + p->target_class = c; mrb_define_method_raw(mrb, c, mid, p); mrb_gc_arena_restore(mrb, ai); } @@ -329,7 +346,7 @@ mrb_define_method_vm(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_value b struct RProc *p; if (!h) h = c->mt = kh_init(mt, mrb); - k = kh_put(mt, h, name); + k = kh_put(mt, mrb, h, name); p = mrb_proc_ptr(body); kh_value(h, k) = p; if (p) { @@ -379,6 +396,7 @@ to_hash(mrb_state *mrb, mrb_value val) string mruby type C type note ---------------------------------------------------------------------------------------------- o: Object [mrb_value] + C: class/module [mrb_value] S: String [mrb_value] A: Array [mrb_value] H: Hash [mrb_value] @@ -389,9 +407,11 @@ to_hash(mrb_state *mrb, mrb_value val) i: Integer [mrb_int] b: Boolean [mrb_bool] n: Symbol [mrb_sym] + d: Data [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified &: Block [mrb_value] *: rest argument [mrb_value*,int] Receive the rest of the arguments as an array. |: optional Next argument of '|' and later are optional. + ?: optional given [mrb_bool] true if preceding argument (optional) is given. */ int mrb_get_args(mrb_state *mrb, const char *format, ...) @@ -401,7 +421,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *sp = mrb->c->stack + 1; va_list ap; int argc = mrb->c->ci->argc; - int opt = 0; + mrb_bool opt = 0; + mrb_bool given = 1; va_start(ap, format); if (argc < 0) { @@ -412,11 +433,16 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) } while ((c = *format++)) { switch (c) { - case '|': case '*': case '&': + case '|': case '*': case '&': case '?': break; default: - if (argc <= i && !opt) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); + if (argc <= i) { + if (opt) { + given = 0; + } + else { + mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); + } } break; } @@ -433,6 +459,29 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) } } break; + case 'C': + { + mrb_value *p; + + p = va_arg(ap, mrb_value*); + if (i < argc) { + mrb_value ss; + + ss = *sp++; + switch (mrb_type(ss)) { + case MRB_TT_CLASS: + case MRB_TT_MODULE: + case MRB_TT_SCLASS: + break; + default: + mrb_raisef(mrb, E_TYPE_ERROR, "%S is not class/module", ss); + break; + } + *p = ss; + i++; + } + } + break; case 'S': { mrb_value *p; @@ -469,7 +518,6 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) case 's': { mrb_value ss; - struct RString *s; char **ps = 0; int *pl = 0; @@ -477,9 +525,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) pl = va_arg(ap, int*); if (i < argc) { ss = to_str(mrb, *sp++); - s = mrb_str_ptr(ss); - *ps = s->ptr; - *pl = s->len; + *ps = RSTRING_PTR(ss); + *pl = RSTRING_LEN(ss); i++; } } @@ -487,17 +534,12 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) case 'z': { mrb_value ss; - struct RString *s; char **ps; ps = va_arg(ap, char**); if (i < argc) { ss = to_str(mrb, *sp++); - s = mrb_str_ptr(ss); - if (strlen(s->ptr) < s->len) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "String contains NUL"); - } - *ps = s->ptr; + *ps = mrb_string_value_cstr(mrb, &ss); i++; } } @@ -526,25 +568,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, mrb_float*); if (i < argc) { - switch (mrb_type(*sp)) { - case MRB_TT_FLOAT: - *p = mrb_float(*sp); - break; - case MRB_TT_FIXNUM: - *p = (mrb_float)mrb_fixnum(*sp); - break; - case MRB_TT_STRING: - mrb_raise(mrb, E_TYPE_ERROR, "String can't be coerced into Float"); - break; - default: - { - mrb_value tmp; - - tmp = mrb_convert_type(mrb, *sp, MRB_TT_FLOAT, "Float", "to_f"); - *p = mrb_float(tmp); - } - break; - } + *p = mrb_to_flo(mrb, *sp); sp++; i++; } @@ -570,16 +594,11 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) *p = (mrb_int)f; } break; - case MRB_TT_FALSE: - *p = 0; + case MRB_TT_STRING: + mrb_raise(mrb, E_TYPE_ERROR, "no implicit conversion of String into Integer"); break; default: - { - mrb_value tmp; - - tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int"); - *p = mrb_fixnum(tmp); - } + *p = mrb_fixnum(mrb_Integer(mrb, *sp)); break; } sp++; @@ -621,6 +640,19 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) } } break; + case 'd': + { + void** datap; + struct mrb_data_type const* type; + + datap = va_arg(ap, void**); + type = va_arg(ap, struct mrb_data_type const*); + if (i < argc) { + *datap = mrb_data_get_ptr(mrb, *sp++, type); + ++i; + } + } + break; case '&': { @@ -639,6 +671,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) case '|': opt = 1; break; + case '?': + { + mrb_bool *p; + + p = va_arg(ap, mrb_bool*); + *p = given; + } + break; case '*': { @@ -679,8 +719,13 @@ boot_defclass(mrb_state *mrb, struct RClass *super) struct RClass *c; c = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_CLASS, mrb->class_class); - c->super = super ? super : mrb->object_class; - mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)super); + if (super) { + c->super = super; + mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)super); + } + else { + c->super = mrb->object_class; + } c->mt = kh_init(mt, mrb); return c; } @@ -734,7 +779,7 @@ mrb_mod_append_features(mrb_state *mrb, mrb_value mod) mrb_value klass; mrb_check_type(mrb, mod, MRB_TT_MODULE); - mrb_get_args(mrb, "o", &klass); + mrb_get_args(mrb, "C", &klass); mrb_include_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod)); return mod; } @@ -782,7 +827,7 @@ mrb_mod_include_p(mrb_state *mrb, mrb_value mod) mrb_value mod2; struct RClass *c = mrb_class_ptr(mod); - mrb_get_args(mrb, "o", &mod2); + mrb_get_args(mrb, "C", &mod2); mrb_check_type(mrb, mod2, MRB_TT_MODULE); while (c) { @@ -844,7 +889,7 @@ mrb_mod_included_modules(mrb_state *mrb, mrb_value self) return result; } -mrb_value class_instance_method_list(mrb_state*, mrb_bool, struct RClass*, int); +mrb_value mrb_class_instance_method_list(mrb_state*, mrb_bool, struct RClass*, int); /* 15.2.2.4.33 */ /* @@ -880,11 +925,9 @@ mrb_mod_instance_methods(mrb_state *mrb, mrb_value mod) struct RClass *c = mrb_class_ptr(mod); mrb_bool recur = TRUE; mrb_get_args(mrb, "|b", &recur); - return class_instance_method_list(mrb, recur, c, 0); + return mrb_class_instance_method_list(mrb, recur, c, 0); } -mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c); - /* 15.2.2.4.35 */ /* * call-seq: @@ -906,7 +949,7 @@ mrb_mod_module_eval(mrb_state *mrb, mrb_value mod) mrb_raise(mrb, E_NOTIMP_ERROR, "module_eval/class_eval with string not implemented"); } c = mrb_class_ptr(mod); - return mrb_yield_internal(mrb, b, 0, 0, mod, c); + return mrb_yield_with_class(mrb, b, 0, 0, mod, c); } mrb_value @@ -927,7 +970,7 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v) return mrb_obj_value(mrb->false_class); case MRB_TT_TRUE: return mrb_obj_value(mrb->true_class); - case MRB_TT_VOIDP: + case MRB_TT_CPTR: return mrb_obj_value(mrb->object_class); case MRB_TT_SYMBOL: case MRB_TT_FIXNUM: @@ -939,6 +982,10 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v) } obj = mrb_basic_ptr(v); prepare_singleton_class(mrb, obj); + if (mrb->c && mrb->c->ci && mrb->c->ci->target_class) { + mrb_obj_iv_set(mrb, (struct RObject*)obj->c, mrb_intern_lit(mrb, "__outer__"), + mrb_obj_value(mrb->c->ci->target_class)); + } return mrb_obj_value(obj->c); } @@ -973,7 +1020,7 @@ mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid) khash_t(mt) *h = c->mt; if (h) { - k = kh_get(mt, h, mid); + k = kh_get(mt, mrb, h, mid); if (k != kh_end(h)) { m = kh_value(h, k); if (!m) break; @@ -1003,10 +1050,19 @@ mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid) return m; } -void -mrb_obj_call_init(mrb_state *mrb, mrb_value obj, int argc, mrb_value *argv) +static mrb_value +mrb_instance_alloc(mrb_state *mrb, mrb_value cv) { - mrb_funcall_argv(mrb, obj, mrb->init_sym, argc, argv); + struct RClass *c = mrb_class_ptr(cv); + struct RObject *o; + enum mrb_vtype ttype = MRB_INSTANCE_TT(c); + + if (c->tt == MRB_TT_SCLASS) + mrb_raise(mrb, E_TYPE_ERROR, "can't create instance of singleton class"); + + if (ttype == 0) ttype = MRB_TT_OBJECT; + o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c); + return mrb_obj_value(o); } /* @@ -1020,70 +1076,47 @@ mrb_obj_call_init(mrb_state *mrb, mrb_value obj, int argc, mrb_value *argv) * an object is constructed using .new. * */ -mrb_value -mrb_class_new_instance(mrb_state *mrb, int argc, mrb_value *argv, struct RClass * klass) -{ - mrb_value obj; - struct RClass * c = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, klass); - c->super = klass; - obj = mrb_obj_value(c); - mrb_obj_call_init(mrb, obj, argc, argv); - return obj; -} mrb_value -mrb_class_new_instance_m(mrb_state *mrb, mrb_value klass) +mrb_instance_new(mrb_state *mrb, mrb_value cv) { + mrb_value obj, blk; mrb_value *argv; - mrb_value blk; - struct RClass *k = mrb_class_ptr(klass); - struct RClass *c; int argc; - mrb_value obj; + obj = mrb_instance_alloc(mrb, cv); mrb_get_args(mrb, "*&", &argv, &argc, &blk); - c = (struct RClass*)mrb_obj_alloc(mrb, k->tt, k); - c->super = k; - obj = mrb_obj_value(c); - mrb_funcall_with_block(mrb, obj, mrb->init_sym, argc, argv, blk); + mrb_funcall_with_block(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv, blk); return obj; } mrb_value -mrb_instance_new(mrb_state *mrb, mrb_value cv) +mrb_obj_new(mrb_state *mrb, struct RClass *c, int argc, const mrb_value *argv) { - struct RClass *c = mrb_class_ptr(cv); - struct RObject *o; - enum mrb_vtype ttype = MRB_INSTANCE_TT(c); - mrb_value obj, blk; - mrb_value *argv; - int argc; - - if (c->tt == MRB_TT_SCLASS) - mrb_raise(mrb, E_TYPE_ERROR, "can't create instance of singleton class"); + mrb_value obj; - if (ttype == 0) ttype = MRB_TT_OBJECT; - o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c); - obj = mrb_obj_value(o); - mrb_get_args(mrb, "*&", &argv, &argc, &blk); - mrb_funcall_with_block(mrb, obj, mrb->init_sym, argc, argv, blk); + obj = mrb_instance_alloc(mrb, mrb_obj_value(c)); + mrb_funcall_argv(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv); return obj; } -mrb_value +static mrb_value mrb_class_new_class(mrb_state *mrb, mrb_value cv) { - mrb_value super; - struct RClass *new_class; + mrb_value super, blk; + mrb_value new_class; - if (mrb_get_args(mrb, "|o", &super) == 0) { + if (mrb_get_args(mrb, "|C&", &super, &blk) == 0) { super = mrb_obj_value(mrb->object_class); } - new_class = mrb_class_new(mrb, mrb_class_ptr(super)); - mrb_funcall(mrb, super, "inherited", 1, mrb_obj_value(new_class)); - return mrb_obj_value(new_class); + new_class = mrb_obj_value(mrb_class_new(mrb, mrb_class_ptr(super))); + if (!mrb_nil_p(blk)) { + mrb_funcall_with_block(mrb, new_class, mrb_intern_lit(mrb, "class_eval"), 0, NULL, blk); + } + mrb_funcall(mrb, super, "inherited", 1, new_class); + return new_class; } mrb_value @@ -1151,28 +1184,34 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod) mrb_sym name; mrb_value *a; int alen; - mrb_value inspect; + mrb_sym inspect; + mrb_value repr; mrb_get_args(mrb, "n*", &name, &a, &alen); - if (mrb_respond_to(mrb,mod,mrb_intern2(mrb, "inspect",7))){ - inspect = mrb_funcall(mrb, mod, "inspect", 0); - if (RSTRING_LEN(inspect) > 64) { - inspect = mrb_any_to_s(mrb, mod); + inspect = mrb_intern_lit(mrb, "inspect"); + if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) { + /* method missing in inspect; avoid recursion */ + repr = mrb_any_to_s(mrb, mod); + } + else if (mrb_respond_to(mrb, mod, inspect)) { + repr = mrb_funcall_argv(mrb, mod, inspect, 0, 0); + if (RSTRING_LEN(repr) > 64) { + repr = mrb_any_to_s(mrb, mod); } } else { - inspect = mrb_any_to_s(mrb, mod); + repr = mrb_any_to_s(mrb, mod); } mrb_raisef(mrb, E_NOMETHOD_ERROR, "undefined method '%S' for %S", - mrb_sym2str(mrb, name), inspect); + mrb_sym2str(mrb, name), repr); /* not reached */ return mrb_nil_value(); } mrb_bool -mrb_obj_respond_to(struct RClass* c, mrb_sym mid) +mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid) { khiter_t k; @@ -1180,7 +1219,7 @@ mrb_obj_respond_to(struct RClass* c, mrb_sym mid) khash_t(mt) *h = c->mt; if (h) { - k = kh_get(mt, h, mid); + k = kh_get(mt, mrb, h, mid); if (k != kh_end(h)) { if (kh_value(h, k)) { return TRUE; /* method exists */ @@ -1198,7 +1237,7 @@ mrb_obj_respond_to(struct RClass* c, mrb_sym mid) mrb_bool mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid) { - return mrb_obj_respond_to(mrb_class(mrb, obj), mid); + return mrb_obj_respond_to(mrb, mrb_class(mrb, obj), mid); } mrb_value @@ -1206,8 +1245,8 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) { mrb_value path; const char *name; - size_t len; - mrb_sym classpath = mrb_intern2(mrb, "__classpath__", 13); + mrb_int len; + mrb_sym classpath = mrb_intern_lit(mrb, "__classpath__"); path = mrb_obj_iv_get(mrb, (struct RObject*)c, classpath); if (mrb_nil_p(path)) { @@ -1218,7 +1257,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) } else if (outer && outer != mrb->object_class) { mrb_value base = mrb_class_path(mrb, outer); - path = mrb_str_plus(mrb, base, mrb_str_new(mrb, "::", 2)); + path = mrb_str_plus(mrb, base, mrb_str_new_lit(mrb, "::")); name = mrb_sym2name_len(mrb, sym, &len); mrb_str_concat(mrb, path, mrb_str_new(mrb, name, len)); } @@ -1245,11 +1284,11 @@ mrb_class_name(mrb_state *mrb, struct RClass* c) { mrb_value path = mrb_class_path(mrb, c); if (mrb_nil_p(path)) { - path = mrb_str_new(mrb, "#<Class:", 8); + path = mrb_str_new_lit(mrb, "#<Class:"); mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c)); - mrb_str_cat(mrb, path, ">", 1); + mrb_str_cat_lit(mrb, path, ">"); } - return mrb_str_ptr(path)->ptr; + return RSTRING_PTR(path); } const char* @@ -1368,9 +1407,9 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass) mrb_value str; if (mrb_type(klass) == MRB_TT_SCLASS) { - mrb_value v = mrb_iv_get(mrb, klass, mrb_intern2(mrb, "__attached__", 12)); + mrb_value v = mrb_iv_get(mrb, klass, mrb_intern_lit(mrb, "__attached__")); - str = mrb_str_new(mrb, "#<Class:", 8); + str = mrb_str_new_lit(mrb, "#<Class:"); switch (mrb_type(v)) { case MRB_TT_CLASS: @@ -1382,7 +1421,7 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass) mrb_str_append(mrb, str, mrb_any_to_s(mrb, v)); break; } - mrb_str_cat(mrb, str, ">", 1); + mrb_str_cat_lit(mrb, str, ">"); } else { struct RClass *c; @@ -1395,20 +1434,20 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass) if (mrb_nil_p(path)) { switch (mrb_type(klass)) { case MRB_TT_CLASS: - mrb_str_cat(mrb, str, "#<Class:", 8); + mrb_str_cat_lit(mrb, str, "#<Class:"); break; case MRB_TT_MODULE: - mrb_str_cat(mrb, str, "#<Module:", 9); + mrb_str_cat_lit(mrb, str, "#<Module:"); break; default: /* Shouldn't be happened? */ - mrb_str_cat(mrb, str, "#<??????:", 9); + mrb_str_cat_lit(mrb, str, "#<??????:"); break; } mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, c)); - mrb_str_cat(mrb, str, ">", 1); + mrb_str_cat_lit(mrb, str, ">"); } else { str = path; @@ -1434,7 +1473,7 @@ undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a) { mrb_value m; - if (!mrb_obj_respond_to(c, a)) { + if (!mrb_obj_respond_to(mrb, c, a)) { mrb_name_error(mrb, a, "undefined method '%S' for class '%S'", mrb_sym2str(mrb, a), mrb_obj_value(c)); } else { @@ -1484,15 +1523,16 @@ mod_define_method(mrb_state *mrb, mrb_value self) } p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class); mrb_proc_copy(p, mrb_proc_ptr(blk)); + p->flags |= MRB_PROC_STRICT; mrb_define_method_raw(mrb, c, mid, p); - return blk; + return mrb_symbol_value(mid); } static void check_cv_name_sym(mrb_state *mrb, mrb_sym id) { const char *s; - size_t len; + mrb_int len; s = mrb_sym2name_len(mrb, id, &len); if (len < 3 || !(s[0] == '@' && s[1] == '@')) { @@ -1504,7 +1544,8 @@ static void check_cv_name_str(mrb_state *mrb, mrb_value str) { const char *s = RSTRING_PTR(str); - size_t const len = RSTRING_LEN(str); + mrb_int len = RSTRING_LEN(str); + if (len < 3 || !(s[0] == '@' && s[1] == '@')) { mrb_name_error(mrb, mrb_intern_str(mrb, str), "`%S' is not allowed as a class variable name", str); } @@ -1704,7 +1745,7 @@ mrb_mod_method_defined(mrb_state *mrb, mrb_value mod) id = get_sym_or_str_arg(mrb); if (mrb_symbol_p(id)) { - method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), mrb_symbol(id)); + method_defined_p = mrb_obj_respond_to(mrb, mrb_class_ptr(mod), mrb_symbol(id)); } else { mrb_value sym = mrb_check_intern_str(mrb, id); @@ -1712,7 +1753,7 @@ mrb_mod_method_defined(mrb_state *mrb, mrb_value mod) method_defined_p = FALSE; } else { - method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), mrb_symbol(sym)); + method_defined_p = mrb_obj_respond_to(mrb, mrb_class_ptr(mod), mrb_symbol(sym)); } } return mrb_bool_value(method_defined_p); @@ -1726,9 +1767,9 @@ remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid) khiter_t k; if (h) { - k = kh_get(mt, h, mid); + k = kh_get(mt, mrb, h, mid); if (k != kh_end(h)) { - kh_del(mt, h, k); + kh_del(mt, mrb, h, k); return; } } @@ -1764,7 +1805,7 @@ static void check_const_name_sym(mrb_state *mrb, mrb_sym id) { const char *s; - size_t len; + mrb_int len; s = mrb_sym2name_len(mrb, id, &len); if (len < 1 || !ISUPPER(*s)) { @@ -1843,6 +1884,18 @@ mrb_mod_remove_const(mrb_state *mrb, mrb_value mod) return val; } +mrb_value +mrb_mod_const_missing(mrb_state *mrb, mrb_value mod) +{ + mrb_sym sym; + + mrb_get_args(mrb, "n", &sym); + mrb_name_error(mrb, sym, "uninitialized constant %S", + mrb_sym2str(mrb, sym)); + /* not reached */ + return mrb_nil_value(); +} + static mrb_value mrb_mod_s_constants(mrb_state *mrb, mrb_value mod) { @@ -1869,7 +1922,6 @@ mrb_init_class(mrb_state *mrb) struct RClass *obj; /* Object */ struct RClass *mod; /* Module */ struct RClass *cls; /* Class */ - //struct RClass *krn; /* Kernel */ /* boot class hierarchy */ bob = boot_defclass(mrb, 0); @@ -1891,10 +1943,10 @@ mrb_init_class(mrb_state *mrb) mrb_define_const(mrb, obj, "Class", mrb_obj_value(cls)); /* name each classes */ - mrb_name_class(mrb, bob, mrb_intern2(mrb, "BasicObject", 11)); /* 15.2.1 */ - mrb_name_class(mrb, obj, mrb_intern2(mrb, "Object", 6)); /* 15.2.1 */ - mrb_name_class(mrb, mod, mrb_intern2(mrb, "Module", 6)); /* 15.2.2 */ - mrb_name_class(mrb, cls, mrb_intern2(mrb, "Class", 5)); /* 15.2.3 */ + 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_SET_INSTANCE_TT(cls, MRB_TT_CLASS); mrb_define_method(mrb, bob, "initialize", mrb_bob_init, MRB_ARGS_NONE()); @@ -1936,6 +1988,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, mod, "const_set", mrb_mod_const_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.23 */ mrb_define_method(mrb, mod, "constants", mrb_mod_constants, MRB_ARGS_NONE()); /* 15.2.2.4.24 */ mrb_define_method(mrb, mod, "remove_const", mrb_mod_remove_const, MRB_ARGS_REQ(1)); /* 15.2.2.4.40 */ + mrb_define_method(mrb, mod, "const_missing", mrb_mod_const_missing, MRB_ARGS_REQ(1)); mrb_define_method(mrb, mod, "define_method", mod_define_method, MRB_ARGS_REQ(1)); mrb_define_method(mrb, mod, "class_variables", mrb_mod_class_variables, MRB_ARGS_NONE()); /* 15.2.2.4.19 */ mrb_define_method(mrb, mod, "===", mrb_mod_eqq, MRB_ARGS_REQ(1)); |
