diff options
Diffstat (limited to 'src/class.c')
| -rw-r--r-- | src/class.c | 695 |
1 files changed, 174 insertions, 521 deletions
diff --git a/src/class.c b/src/class.c index c761f46af..edee95678 100644 --- a/src/class.c +++ b/src/class.c @@ -65,16 +65,22 @@ mrb_class_name_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb 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)); + if (outer != mrb->object_class && outer != c) { + mrb_obj_iv_set_force(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); + mrb_obj_iv_set_force(mrb, (struct RObject*)c, nsym, name); +} + +mrb_bool +mrb_const_name_p(mrb_state *mrb, const char *name, mrb_int len) +{ + return len > 0 && ISUPPER(name[0]) && mrb_ident_p(name+1, len-1); } static void @@ -93,7 +99,7 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o) if (o->c->tt == MRB_TT_SCLASS) return; sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class); - sc->flags |= MRB_FLAG_IS_INHERITED; + sc->flags |= MRB_FL_CLASS_IS_INHERITED; sc->mt = kh_init(mt, mrb); sc->iv = 0; if (o->tt == MRB_TT_CLASS) { @@ -120,6 +126,20 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o) 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_intern_lit(mrb, "__attached__"), mrb_obj_value(o)); + sc->flags |= o->flags & MRB_FL_OBJ_IS_FROZEN; +} + +static mrb_value +class_name_str(mrb_state *mrb, struct RClass* c) +{ + mrb_value path = mrb_class_path(mrb, c); + if (mrb_nil_p(path)) { + path = c->tt == MRB_TT_MODULE ? mrb_str_new_lit(mrb, "#<Module:") : + mrb_str_new_lit(mrb, "#<Class:"); + mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c)); + mrb_str_cat_lit(mrb, path, ">"); + } + return path; } static struct RClass* @@ -275,7 +295,7 @@ mrb_class_inherited(mrb_state *mrb, struct RClass *super, struct RClass *klass) if (!super) super = mrb->object_class; - super->flags |= MRB_FLAG_IS_INHERITED; + super->flags |= MRB_FL_CLASS_IS_INHERITED; s = mrb_obj_value(super); mc_clear_by_class(mrb, klass); mid = mrb_intern_lit(mrb, "inherited"); @@ -428,12 +448,7 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_method_ MRB_CLASS_ORIGIN(c); h = c->mt; - if (MRB_FROZEN_P(c)) { - if (c->tt == MRB_TT_MODULE) - mrb_raise(mrb, E_FROZEN_ERROR, "can't modify frozen module"); - else - mrb_raise(mrb, E_FROZEN_ERROR, "can't modify frozen class"); - } + mrb_check_frozen(mrb, c); if (!h) h = c->mt = kh_init(mt, mrb); k = kh_put(mt, mrb, h, mid); kh_value(h, k) = m; @@ -471,15 +486,11 @@ mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t MRB_API void mrb_notimplement(mrb_state *mrb) { - const char *str; - mrb_int len; mrb_callinfo *ci = mrb->c->ci; if (ci->mid) { - str = mrb_sym2name_len(mrb, ci->mid, &len); - mrb_raisef(mrb, E_NOTIMP_ERROR, - "%S() function is unimplemented on this machine", - mrb_str_new_static(mrb, str, (size_t)len)); + mrb_value str = mrb_sym2str(mrb, ci->mid); + mrb_raisef(mrb, E_NOTIMP_ERROR, "%S() function is unimplemented on this machine", str); } } @@ -492,52 +503,34 @@ mrb_notimplement_m(mrb_state *mrb, mrb_value self) return mrb_nil_value(); } -static mrb_value -check_type(mrb_state *mrb, mrb_value val, enum mrb_vtype t, const char *c, const char *m) -{ - mrb_value tmp; - - tmp = mrb_check_convert_type(mrb, val, t, c, m); - if (mrb_nil_p(tmp)) { - mrb_raisef(mrb, E_TYPE_ERROR, "expected %S", mrb_str_new_cstr(mrb, c)); - } - return tmp; -} +#define CHECK_TYPE(mrb, val, t, c) do { \ + if (mrb_type(val) != (t)) {\ + mrb_raisef(mrb, E_TYPE_ERROR, "expected %S", mrb_str_new_lit(mrb, c));\ + }\ +} while (0) static mrb_value to_str(mrb_state *mrb, mrb_value val) { - return check_type(mrb, val, MRB_TT_STRING, "String", "to_str"); + CHECK_TYPE(mrb, val, MRB_TT_STRING, "String"); + return val; } static mrb_value to_ary(mrb_state *mrb, mrb_value val) { - return check_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary"); + CHECK_TYPE(mrb, val, MRB_TT_ARRAY, "Array"); + return val; } static mrb_value to_hash(mrb_state *mrb, mrb_value val) { - return check_type(mrb, val, MRB_TT_HASH, "Hash", "to_hash"); + CHECK_TYPE(mrb, val, MRB_TT_HASH, "Hash"); + return val; } -static mrb_sym -to_sym(mrb_state *mrb, mrb_value ss) -{ - if (mrb_type(ss) == MRB_TT_SYMBOL) { - return mrb_symbol(ss); - } - else if (mrb_string_p(ss)) { - return mrb_intern_str(mrb, to_str(mrb, ss)); - } - else { - mrb_value obj = mrb_funcall(mrb, ss, "inspect", 0); - mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", obj); - /* not reached */ - return 0; - } -} +#define to_sym(mrb, ss) mrb_obj_to_sym(mrb, ss) MRB_API mrb_int mrb_get_argc(mrb_state *mrb) @@ -580,20 +573,20 @@ mrb_get_argv(mrb_state *mrb) string mruby type C type note ---------------------------------------------------------------------------------------------- o: Object [mrb_value] - C: class/module [mrb_value] + C: Class/Module [mrb_value] S: String [mrb_value] when ! follows, the value may be nil A: Array [mrb_value] when ! follows, the value may be nil H: Hash [mrb_value] when ! follows, the value may be nil s: String [char*,mrb_int] Receive two arguments; s! gives (NULL,0) for nil z: String [char*] NUL terminated string; z! gives NULL for nil a: Array [mrb_value*,mrb_int] Receive two arguments; a! gives (NULL,0) for nil - f: Float [mrb_float] - 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 - I: Inline struct [void*] - &: Block [mrb_value] &! raises exception if no block given + f: Fixnum/Float [mrb_float] + i: Fixnum/Float [mrb_int] + b: boolean [mrb_bool] + n: String/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; when ! follows, the value may be nil + I: inline struct [void*] + &: block [mrb_value] &! raises exception if no block given *: rest argument [mrb_value*,mrb_int] The rest of the arguments as an array; *! avoid copy of the stack |: optional Following arguments are optional ?: optional given [mrb_bool] true if preceding argument (optional) is given @@ -851,29 +844,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, mrb_int*); if (i < argc) { - switch (mrb_type(ARGV[arg_i])) { - case MRB_TT_FIXNUM: - *p = mrb_fixnum(ARGV[arg_i]); - break; -#ifndef MRB_WITHOUT_FLOAT - case MRB_TT_FLOAT: - { - mrb_float f = mrb_float(ARGV[arg_i]); - - if (!FIXABLE_FLOAT(f)) { - mrb_raise(mrb, E_RANGE_ERROR, "float too big for int"); - } - *p = (mrb_int)f; - } - break; -#endif - case MRB_TT_STRING: - mrb_raise(mrb, E_TYPE_ERROR, "no implicit conversion of String into Integer"); - break; - default: - *p = mrb_fixnum(mrb_Integer(mrb, ARGV[arg_i])); - break; - } + *p = mrb_fixnum(mrb_to_int(mrb, ARGV[arg_i])); arg_i++; i++; } @@ -1061,7 +1032,7 @@ include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, stru while (m) { int superclass_seen = 0; - if (m->flags & MRB_FLAG_IS_PREPENDED) + if (m->flags & MRB_FL_CLASS_IS_PREPENDED) goto skip; if (klass_mt && klass_mt == m->mt) @@ -1084,7 +1055,7 @@ include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, stru } ic = include_class_new(mrb, m, ins_pos->super); - m->flags |= MRB_FLAG_IS_INHERITED; + m->flags |= MRB_FL_CLASS_IS_INHERITED; ins_pos->super = ic; mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ic); mc_clear_by_class(mrb, ins_pos); @@ -1099,8 +1070,8 @@ include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, stru MRB_API void mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) { - int changed = include_module_at(mrb, c, find_origin(c), m, 1); - if (changed < 0) { + mrb_check_frozen(mrb, c); + if (include_module_at(mrb, c, find_origin(c), m, 1) < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected"); } } @@ -1111,15 +1082,16 @@ mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m) struct RClass *origin; int changed = 0; - if (!(c->flags & MRB_FLAG_IS_PREPENDED)) { + mrb_check_frozen(mrb, c); + if (!(c->flags & MRB_FL_CLASS_IS_PREPENDED)) { origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c); - origin->flags |= MRB_FLAG_IS_ORIGIN | MRB_FLAG_IS_INHERITED; + origin->flags |= MRB_FL_CLASS_IS_ORIGIN | MRB_FL_CLASS_IS_INHERITED; origin->super = c->super; c->super = origin; origin->mt = c->mt; c->mt = kh_init(mt, mrb); mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)origin); - c->flags |= MRB_FLAG_IS_PREPENDED; + c->flags |= MRB_FL_CLASS_IS_PREPENDED; } changed = include_module_at(mrb, c, c, m, 0); if (changed < 0) { @@ -1196,7 +1168,7 @@ mrb_mod_ancestors(mrb_state *mrb, mrb_value self) if (c->tt == MRB_TT_ICLASS) { mrb_ary_push(mrb, result, mrb_obj_value(c->c)); } - else if (!(c->flags & MRB_FLAG_IS_PREPENDED)) { + else if (!(c->flags & MRB_FL_CLASS_IS_PREPENDED)) { mrb_ary_push(mrb, result, mrb_obj_value(c)); } c = c->super; @@ -1217,27 +1189,6 @@ mrb_mod_extend_object(mrb_state *mrb, mrb_value mod) } static mrb_value -mrb_mod_included_modules(mrb_state *mrb, mrb_value self) -{ - mrb_value result; - struct RClass *c = mrb_class_ptr(self); - struct RClass *origin = c; - - MRB_CLASS_ORIGIN(origin); - result = mrb_ary_new(mrb); - while (c) { - if (c != origin && c->tt == MRB_TT_ICLASS) { - if (c->c->tt == MRB_TT_MODULE) { - mrb_ary_push(mrb, result, mrb_obj_value(c->c)); - } - } - c = c->super; - } - - return result; -} - -static mrb_value mrb_mod_initialize(mrb_state *mrb, mrb_value mod) { mrb_value b; @@ -1250,45 +1201,6 @@ mrb_mod_initialize(mrb_state *mrb, mrb_value mod) return mod; } -mrb_value mrb_class_instance_method_list(mrb_state*, mrb_bool, struct RClass*, int); - -/* 15.2.2.4.33 */ -/* - * call-seq: - * mod.instance_methods(include_super=true) -> array - * - * Returns an array containing the names of the public and protected instance - * methods in the receiver. For a module, these are the public and protected methods; - * for a class, they are the instance (not singleton) methods. With no - * argument, or with an argument that is <code>false</code>, the - * instance methods in <i>mod</i> are returned, otherwise the methods - * in <i>mod</i> and <i>mod</i>'s superclasses are returned. - * - * module A - * def method1() end - * end - * class B - * def method2() end - * end - * class C < B - * def method3() end - * end - * - * A.instance_methods #=> [:method1] - * B.instance_methods(false) #=> [:method2] - * C.instance_methods(false) #=> [:method3] - * C.instance_methods(true).length #=> 43 - */ - -static mrb_value -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 mrb_class_instance_method_list(mrb, recur, c, 0); -} - /* implementation of module_eval/class_eval */ mrb_value mrb_mod_module_eval(mrb_state*, mrb_value); @@ -1365,9 +1277,9 @@ mc_clear_by_class(mrb_state *mrb, struct RClass *c) struct mrb_cache_entry *mc = mrb->cache; int i; - if (c->flags & MRB_FLAG_IS_INHERITED) { + if (c->flags & MRB_FL_CLASS_IS_INHERITED) { mc_clear_all(mrb); - c->flags &= ~MRB_FLAG_IS_INHERITED; + c->flags &= ~MRB_FL_CLASS_IS_INHERITED; return; } for (i=0; i<MRB_METHOD_CACHE_SIZE; i++) { @@ -1381,9 +1293,9 @@ mc_clear_by_id(mrb_state *mrb, struct RClass *c, mrb_sym mid) struct mrb_cache_entry *mc = mrb->cache; int i; - if (c->flags & MRB_FLAG_IS_INHERITED) { + if (c->flags & MRB_FL_CLASS_IS_INHERITED) { mc_clear_all(mrb); - c->flags &= ~MRB_FLAG_IS_INHERITED; + c->flags &= ~MRB_FL_CLASS_IS_INHERITED; return; } for (i=0; i<MRB_METHOD_CACHE_SIZE; i++) { @@ -1480,7 +1392,7 @@ mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod) mrb_str_cat_lit(mrb, str, "@"); mrb_str_cat_str(mrb, str, name); sym = mrb_intern_str(mrb, str); - mrb_iv_check(mrb, sym); + mrb_iv_name_sym_check(mrb, sym); name = mrb_symbol_value(sym); p = mrb_proc_new_cfunc_with_env(mrb, attr_reader, 1, &name); MRB_METHOD_FROM_PROC(m, p); @@ -1525,7 +1437,7 @@ mrb_mod_attr_writer(mrb_state *mrb, mrb_value mod) mrb_str_cat_lit(mrb, str, "@"); mrb_str_cat_str(mrb, str, name); sym = mrb_intern_str(mrb, str); - mrb_iv_check(mrb, sym); + mrb_iv_name_sym_check(mrb, sym); attr = mrb_symbol_value(sym); /* prepare method name (name=) */ @@ -1572,29 +1484,20 @@ mrb_instance_alloc(mrb_state *mrb, mrb_value cv) * */ -MRB_API mrb_value +mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv) { mrb_value obj, blk; mrb_value *argv; mrb_int argc; mrb_sym init; - mrb_method_t m; mrb_get_args(mrb, "*&", &argv, &argc, &blk); obj = mrb_instance_alloc(mrb, cv); init = mrb_intern_lit(mrb, "initialize"); - m = mrb_method_search(mrb, mrb_class(mrb, obj), init); - if (MRB_METHOD_CFUNC_P(m)) { - mrb_func_t f = MRB_METHOD_CFUNC(m); - if (f != mrb_bob_init) { - f(mrb, obj); - } - } - else { + if (!mrb_func_basic_p(mrb, obj, init, mrb_bob_init)) { mrb_funcall_with_block(mrb, obj, init, argc, argv, blk); } - return obj; } @@ -1751,11 +1654,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) } else if (mrb_symbol_p(path)) { /* toplevel class/module */ - const char *str; - mrb_int len; - - str = mrb_sym2name_len(mrb, mrb_symbol(path), &len); - return mrb_str_new(mrb, str, len); + return mrb_sym2str(mrb, mrb_symbol(path)); } return mrb_str_dup(mrb, path); } @@ -1763,10 +1662,10 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) MRB_API struct RClass* mrb_class_real(struct RClass* cl) { - if (cl == 0) - return NULL; + if (cl == 0) return NULL; while ((cl->tt == MRB_TT_SCLASS) || (cl->tt == MRB_TT_ICLASS)) { cl = cl->super; + if (cl == 0) return NULL; } return cl; } @@ -1774,13 +1673,8 @@ mrb_class_real(struct RClass* cl) MRB_API const char* 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_lit(mrb, "#<Class:"); - mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c)); - mrb_str_cat_lit(mrb, path, ">"); - } - return RSTRING_PTR(path); + mrb_value name = class_name_str(mrb, c); + return RSTRING_PTR(name); } MRB_API const char* @@ -1892,15 +1786,13 @@ mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const * show information on the thing we're attached to as well. */ -static mrb_value +mrb_value 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_intern_lit(mrb, "__attached__")); - - str = mrb_str_new_lit(mrb, "#<Class:"); + mrb_value str = mrb_str_new_lit(mrb, "#<Class:"); if (class_ptr_p(v)) { mrb_str_cat_str(mrb, str, mrb_inspect(mrb, v)); @@ -1911,34 +1803,7 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass) return mrb_str_cat_lit(mrb, str, ">"); } else { - struct RClass *c; - mrb_value path; - - str = mrb_str_new_capa(mrb, 32); - c = mrb_class_ptr(klass); - path = mrb_class_path(mrb, c); - - if (mrb_nil_p(path)) { - switch (mrb_type(klass)) { - case MRB_TT_CLASS: - mrb_str_cat_lit(mrb, str, "#<Class:"); - break; - - case MRB_TT_MODULE: - mrb_str_cat_lit(mrb, str, "#<Module:"); - break; - - default: - /* Shouldn't be happened? */ - mrb_str_cat_lit(mrb, str, "#<??????:"); - break; - } - mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, c)); - return mrb_str_cat_lit(mrb, str, ">"); - } - else { - return path; - } + return class_name_str(mrb, mrb_class_ptr(klass)); } } @@ -1950,11 +1815,11 @@ mrb_mod_alias(mrb_state *mrb, mrb_value mod) mrb_get_args(mrb, "nn", &new_name, &old_name); mrb_alias_method(mrb, c, new_name, old_name); - return mrb_nil_value(); + return mod; } -static void -undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a) +void +mrb_undef_method_id(mrb_state *mrb, struct RClass *c, mrb_sym 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)); @@ -1970,7 +1835,7 @@ undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a) MRB_API void mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name) { - undef_method(mrb, c, mrb_intern_cstr(mrb, name)); + mrb_undef_method_id(mrb, c, mrb_intern_cstr(mrb, name)); } MRB_API void @@ -1988,297 +1853,20 @@ mrb_mod_undef(mrb_state *mrb, mrb_value mod) mrb_get_args(mrb, "*", &argv, &argc); while (argc--) { - undef_method(mrb, c, to_sym(mrb, *argv)); + mrb_undef_method_id(mrb, c, to_sym(mrb, *argv)); argv++; } return mrb_nil_value(); } -static mrb_value -mod_define_method(mrb_state *mrb, mrb_value self) -{ - struct RClass *c = mrb_class_ptr(self); - struct RProc *p; - mrb_method_t m; - mrb_sym mid; - mrb_value proc = mrb_undef_value(); - mrb_value blk; - - mrb_get_args(mrb, "n|o&", &mid, &proc, &blk); - switch (mrb_type(proc)) { - case MRB_TT_PROC: - blk = proc; - break; - case MRB_TT_UNDEF: - /* ignored */ - break; - default: - mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected Proc)", mrb_obj_value(mrb_obj_class(mrb, proc))); - break; - } - if (mrb_nil_p(blk)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); - } - 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_METHOD_FROM_PROC(m, p); - mrb_define_method_raw(mrb, c, mid, m); - return mrb_symbol_value(mid); -} - -static mrb_value -top_define_method(mrb_state *mrb, mrb_value self) -{ - return mod_define_method(mrb, mrb_obj_value(mrb->object_class)); -} - -static void -check_cv_name_str(mrb_state *mrb, mrb_value str) -{ - const char *s = RSTRING_PTR(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); - } -} - -static void -check_cv_name_sym(mrb_state *mrb, mrb_sym id) -{ - check_cv_name_str(mrb, mrb_sym2str(mrb, id)); -} - -/* 15.2.2.4.16 */ -/* - * call-seq: - * obj.class_variable_defined?(symbol) -> true or false - * - * Returns <code>true</code> if the given class variable is defined - * in <i>obj</i>. - * - * class Fred - * @@foo = 99 - * end - * Fred.class_variable_defined?(:@@foo) #=> true - * Fred.class_variable_defined?(:@@bar) #=> false - */ - -static mrb_value -mrb_mod_cvar_defined(mrb_state *mrb, mrb_value mod) -{ - mrb_sym id; - - mrb_get_args(mrb, "n", &id); - check_cv_name_sym(mrb, id); - return mrb_bool_value(mrb_cv_defined(mrb, mod, id)); -} - -/* 15.2.2.4.17 */ -/* - * call-seq: - * mod.class_variable_get(symbol) -> obj - * - * Returns the value of the given class variable (or throws a - * <code>NameError</code> exception). The <code>@@</code> part of the - * variable name should be included for regular class variables - * - * class Fred - * @@foo = 99 - * end - * Fred.class_variable_get(:@@foo) #=> 99 - */ - -static mrb_value -mrb_mod_cvar_get(mrb_state *mrb, mrb_value mod) -{ - mrb_sym id; - - mrb_get_args(mrb, "n", &id); - check_cv_name_sym(mrb, id); - return mrb_cv_get(mrb, mod, id); -} - -/* 15.2.2.4.18 */ -/* - * call-seq: - * obj.class_variable_set(symbol, obj) -> obj - * - * Sets the class variable names by <i>symbol</i> to - * <i>object</i>. - * - * class Fred - * @@foo = 99 - * def foo - * @@foo - * end - * end - * Fred.class_variable_set(:@@foo, 101) #=> 101 - * Fred.new.foo #=> 101 - */ - -static mrb_value -mrb_mod_cvar_set(mrb_state *mrb, mrb_value mod) -{ - mrb_value value; - mrb_sym id; - - mrb_get_args(mrb, "no", &id, &value); - check_cv_name_sym(mrb, id); - mrb_cv_set(mrb, mod, id, value); - return value; -} - -/* 15.2.2.4.39 */ -/* - * call-seq: - * remove_class_variable(sym) -> obj - * - * Removes the definition of the <i>sym</i>, returning that - * constant's value. - * - * class Dummy - * @@var = 99 - * puts @@var - * p class_variables - * remove_class_variable(:@@var) - * p class_variables - * end - * - * <em>produces:</em> - * - * 99 - * [:@@var] - * [] - */ - -static mrb_value -mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod) -{ - mrb_value val; - mrb_sym id; - - mrb_get_args(mrb, "n", &id); - check_cv_name_sym(mrb, id); - - val = mrb_iv_remove(mrb, mod, id); - if (!mrb_undef_p(val)) return val; - - if (mrb_cv_defined(mrb, mod, id)) { - mrb_name_error(mrb, id, "cannot remove %S for %S", - mrb_sym2str(mrb, id), mod); - } - - mrb_name_error(mrb, id, "class variable %S not defined for %S", - mrb_sym2str(mrb, id), mod); - - /* not reached */ - return mrb_nil_value(); -} - -/* 15.2.2.4.34 */ -/* - * call-seq: - * mod.method_defined?(symbol) -> true or false - * - * Returns +true+ if the named method is defined by - * _mod_ (or its included modules and, if _mod_ is a class, - * its ancestors). Public and protected methods are matched. - * - * module A - * def method1() end - * end - * class B - * def method2() end - * end - * class C < B - * include A - * def method3() end - * end - * - * A.method_defined? :method1 #=> true - * C.method_defined? "method1" #=> true - * C.method_defined? "method2" #=> true - * C.method_defined? "method3" #=> true - * C.method_defined? "method4" #=> false - */ - -static mrb_value -mrb_mod_method_defined(mrb_state *mrb, mrb_value mod) -{ - mrb_sym id; - - mrb_get_args(mrb, "n", &id); - return mrb_bool_value(mrb_obj_respond_to(mrb, mrb_class_ptr(mod), id)); -} - -static void -remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid) -{ - struct RClass *c = mrb_class_ptr(mod); - khash_t(mt) *h = find_origin(c)->mt; - khiter_t k; - - if (h) { - k = kh_get(mt, mrb, h, mid); - if (k != kh_end(h)) { - kh_del(mt, mrb, h, k); - mrb_funcall(mrb, mod, "method_removed", 1, mrb_symbol_value(mid)); - return; - } - } - - mrb_name_error(mrb, mid, "method '%S' not defined in %S", - mrb_sym2str(mrb, mid), mod); -} - -/* 15.2.2.4.41 */ -/* - * call-seq: - * remove_method(symbol) -> self - * - * Removes the method identified by _symbol_ from the current - * class. For an example, see <code>Module.undef_method</code>. - */ - -static mrb_value -mrb_mod_remove_method(mrb_state *mrb, mrb_value mod) -{ - mrb_int argc; - mrb_value *argv; - - mrb_get_args(mrb, "*", &argv, &argc); - while (argc--) { - remove_method(mrb, mod, to_sym(mrb, *argv)); - argv++; - } - return mod; -} - - - -static void -check_const_name_str(mrb_state *mrb, mrb_value str) -{ - if (RSTRING_LEN(str) < 1 || !ISUPPER(*RSTRING_PTR(str))) { - mrb_name_error(mrb, mrb_intern_str(mrb, str), "wrong constant name %S", str); - } -} - static void check_const_name_sym(mrb_state *mrb, mrb_sym id) { - check_const_name_str(mrb, mrb_sym2str(mrb, id)); -} - -static mrb_value -const_defined(mrb_state *mrb, mrb_value mod, mrb_sym id, mrb_bool inherit) -{ - if (inherit) { - return mrb_bool_value(mrb_const_defined(mrb, mod, id)); + mrb_int len; + const char *name = mrb_sym2name_len(mrb, id, &len); + if (!mrb_const_name_p(mrb, name, len)) { + mrb_name_error(mrb, id, "wrong constant name %S", mrb_sym2str(mrb, id)); } - return mrb_bool_value(mrb_const_defined_at(mrb, mod, id)); } static mrb_value @@ -2289,7 +1877,10 @@ mrb_mod_const_defined(mrb_state *mrb, mrb_value mod) mrb_get_args(mrb, "n|b", &id, &inherit); check_const_name_sym(mrb, id); - return const_defined(mrb, mod, id, inherit); + if (inherit) { + return mrb_bool_value(mrb_const_defined(mrb, mod, id)); + } + return mrb_bool_value(mrb_const_defined_at(mrb, mod, id)); } static mrb_value @@ -2316,7 +1907,7 @@ mrb_mod_const_get(mrb_state *mrb, mrb_value mod) } /* const get with class path string */ - path = mrb_string_type(mrb, path); + path = mrb_ensure_string_type(mrb, path); ptr = RSTRING_PTR(path); len = RSTRING_LEN(path); off = 0; @@ -2326,7 +1917,14 @@ mrb_mod_const_get(mrb_state *mrb, mrb_value mod) end = (end == -1) ? len : end; id = mrb_intern(mrb, ptr+off, end-off); mod = mrb_const_get_sym(mrb, mod, id); - off = (end == len) ? end : end+2; + if (end == len) + off = end; + else { + off = end + 2; + if (off == len) { /* trailing "::" */ + mrb_name_error(mrb, id, "wrong constant name '%S'", path); + } + } } return mod; @@ -2379,11 +1977,79 @@ mrb_mod_const_missing(mrb_state *mrb, mrb_value mod) return mrb_nil_value(); } +/* 15.2.2.4.34 */ +/* + * call-seq: + * mod.method_defined?(symbol) -> true or false + * + * Returns +true+ if the named method is defined by + * _mod_ (or its included modules and, if _mod_ is a class, + * its ancestors). Public and protected methods are matched. + * + * module A + * def method1() end + * end + * class B + * def method2() end + * end + * class C < B + * include A + * def method3() end + * end + * + * A.method_defined? :method1 #=> true + * C.method_defined? "method1" #=> true + * C.method_defined? "method2" #=> true + * C.method_defined? "method3" #=> true + * C.method_defined? "method4" #=> false + */ + +static mrb_value +mrb_mod_method_defined(mrb_state *mrb, mrb_value mod) +{ + mrb_sym id; + + mrb_get_args(mrb, "n", &id); + return mrb_bool_value(mrb_obj_respond_to(mrb, mrb_class_ptr(mod), id)); +} + +static mrb_value +mod_define_method(mrb_state *mrb, mrb_value self) +{ + struct RClass *c = mrb_class_ptr(self); + struct RProc *p; + mrb_method_t m; + mrb_sym mid; + mrb_value proc = mrb_undef_value(); + mrb_value blk; + + mrb_get_args(mrb, "n|o&", &mid, &proc, &blk); + switch (mrb_type(proc)) { + case MRB_TT_PROC: + blk = proc; + break; + case MRB_TT_UNDEF: + /* ignored */ + break; + default: + mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected Proc)", mrb_obj_value(mrb_obj_class(mrb, proc))); + break; + } + if (mrb_nil_p(blk)) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); + } + 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_METHOD_FROM_PROC(m, p); + mrb_define_method_raw(mrb, c, mid, m); + return mrb_symbol_value(mid); +} + static mrb_value -mrb_mod_s_constants(mrb_state *mrb, mrb_value mod) +top_define_method(mrb_state *mrb, mrb_value self) { - mrb_raise(mrb, E_NOTIMP_ERROR, "Module.constants not implemented"); - return mrb_nil_value(); /* not reached */ + return mod_define_method(mrb, mrb_obj_value(mrb->object_class)); } static mrb_value @@ -2398,7 +2064,7 @@ mrb_mod_eqq(mrb_state *mrb, mrb_value mod) return mrb_bool_value(eqq); } -MRB_API mrb_value +static mrb_value mrb_mod_module_function(mrb_state *mrb, mrb_value mod) { mrb_value *argv; @@ -2439,8 +2105,6 @@ mrb_mod_module_function(mrb_state *mrb, mrb_value mod) mrb_value mrb_obj_id_m(mrb_state *mrb, mrb_value self); /* implementation of instance_eval */ mrb_value mrb_obj_instance_eval(mrb_state*, mrb_value); -/* implementation of Module.nesting */ -mrb_value mrb_mod_s_nesting(mrb_state*, mrb_value); static mrb_value inspect_main(mrb_state *mrb, mrb_value mod) @@ -2489,8 +2153,9 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE()); mrb_define_method(mrb, bob, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */ mrb_define_method(mrb, bob, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, bob, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.3 */ - mrb_define_method(mrb, bob, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */ + mrb_define_method(mrb, bob, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.4 */ + mrb_define_method(mrb, bob, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.5 */ + mrb_define_method(mrb, bob, "equal?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.11 */ mrb_define_method(mrb, bob, "instance_eval", mrb_obj_instance_eval, MRB_ARGS_ANY()); /* 15.3.1.3.18 */ mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, MRB_ARGS_OPT(1)); @@ -2500,9 +2165,6 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, cls, "inherited", mrb_bob_init, MRB_ARGS_REQ(1)); MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE); - mrb_define_method(mrb, mod, "class_variable_defined?", mrb_mod_cvar_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.16 */ - mrb_define_method(mrb, mod, "class_variable_get", mrb_mod_cvar_get, MRB_ARGS_REQ(1)); /* 15.2.2.4.17 */ - mrb_define_method(mrb, mod, "class_variable_set", mrb_mod_cvar_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.18 */ mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, MRB_ARGS_REQ(1)); /* 15.2.2.4.25 */ mrb_define_method(mrb, mod, "extended", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */ mrb_define_method(mrb, mod, "prepended", mrb_bob_init, MRB_ARGS_REQ(1)); @@ -2511,18 +2173,12 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, mod, "append_features", mrb_mod_append_features, MRB_ARGS_REQ(1)); /* 15.2.2.4.10 */ mrb_define_method(mrb, mod, "class_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.15 */ mrb_define_method(mrb, mod, "included", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.29 */ - mrb_define_method(mrb, mod, "included_modules", mrb_mod_included_modules, MRB_ARGS_NONE()); /* 15.2.2.4.30 */ mrb_define_method(mrb, mod, "initialize", mrb_mod_initialize, MRB_ARGS_NONE()); /* 15.2.2.4.31 */ - mrb_define_method(mrb, mod, "instance_methods", mrb_mod_instance_methods, MRB_ARGS_ANY()); /* 15.2.2.4.33 */ - mrb_define_method(mrb, mod, "method_defined?", mrb_mod_method_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.34 */ mrb_define_method(mrb, mod, "module_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.35 */ mrb_define_method(mrb, mod, "module_function", mrb_mod_module_function, MRB_ARGS_ANY()); mrb_define_method(mrb, mod, "private", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.36 */ mrb_define_method(mrb, mod, "protected", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.37 */ mrb_define_method(mrb, mod, "public", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.38 */ - mrb_define_method(mrb, mod, "remove_class_variable", mrb_mod_remove_cvar, MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */ - mrb_define_method(mrb, mod, "remove_method", mrb_mod_remove_method, MRB_ARGS_ANY()); /* 15.2.2.4.41 */ - mrb_define_method(mrb, mod, "method_removed", mrb_bob_init, MRB_ARGS_REQ(1)); mrb_define_method(mrb, mod, "attr_reader", mrb_mod_attr_reader, MRB_ARGS_ANY()); /* 15.2.2.4.13 */ mrb_define_method(mrb, mod, "attr_writer", mrb_mod_attr_writer, MRB_ARGS_ANY()); /* 15.2.2.4.14 */ mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, MRB_ARGS_NONE()); @@ -2533,14 +2189,11 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, mod, "const_defined?", mrb_mod_const_defined, MRB_ARGS_ARG(1,1)); /* 15.2.2.4.20 */ mrb_define_method(mrb, mod, "const_get", mrb_mod_const_get, MRB_ARGS_REQ(1)); /* 15.2.2.4.21 */ 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_OPT(1)); /* 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, "method_defined?", mrb_mod_method_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.34 */ mrb_define_method(mrb, mod, "define_method", mod_define_method, MRB_ARGS_ARG(1,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)); - mrb_define_class_method(mrb, mod, "constants", mrb_mod_s_constants, MRB_ARGS_ANY()); /* 15.2.2.3.1 */ - mrb_define_class_method(mrb, mod, "nesting", mrb_mod_s_nesting, MRB_ARGS_REQ(0)); /* 15.2.2.3.2 */ + mrb_define_method(mrb, mod, "===", mrb_mod_eqq, MRB_ARGS_REQ(1)); /* 15.2.2.4.7 */ mrb_undef_method(mrb, cls, "append_features"); mrb_undef_method(mrb, cls, "extend_object"); |
