diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2012-12-29 01:02:05 -0800 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2012-12-29 01:02:05 -0800 |
| commit | 50e3a53d7377c9cf94b70d553fe4060edcec8fc9 (patch) | |
| tree | b7f76ac65c7f8648e02e7687dbe5b295755eae01 | |
| parent | c836187cf27c058b9e8fd98814e9fc26f05640a5 (diff) | |
| parent | 9219c856a8586fbda74fec526303d19c70290484 (diff) | |
| download | mruby-50e3a53d7377c9cf94b70d553fe4060edcec8fc9.tar.gz mruby-50e3a53d7377c9cf94b70d553fe4060edcec8fc9.zip | |
Merge pull request #677 from skandhas/pr-add-Module-remove_method
Add Module#remove_method for mruby
| -rw-r--r-- | src/class.c | 43 | ||||
| -rw-r--r-- | test/t/module.rb | 19 |
2 files changed, 62 insertions, 0 deletions
diff --git a/src/class.c b/src/class.c index db334cf3a..ace34eb34 100644 --- a/src/class.c +++ b/src/class.c @@ -1596,6 +1596,48 @@ mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod) } static void +remove_method(mrb_state *mrb, struct RClass *c, mrb_sym mid) +{ + khash_t(mt) *h = c->mt; + khiter_t k; + + if (h) { + k = kh_get(mt, h, mid); + if (k != kh_end(h)) { + kh_del(mt, h, k); + return; + } + } + + mrb_name_error(mrb, mid, "method `%s' not defined in %s", + mrb_sym2name(mrb, mid), mrb_class_name(mrb, c)); +} + +/* 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>. + */ + +mrb_value +mrb_mod_remove_method(mrb_state *mrb, mrb_value mod) +{ + struct RClass *c = mrb_class_ptr(mod); + int argc; + mrb_value *argv; + + mrb_get_args(mrb, "*", &argv, &argc); + while (argc--) { + remove_method(mrb, c, mrb_symbol(*argv)); + argv++; + } + return mod; +} + +static void check_const_name(mrb_state *mrb, mrb_sym id) { const char *s; @@ -1710,6 +1752,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, mod, "instance_methods", mrb_mod_instance_methods, ARGS_ANY()); /* 15.2.2.4.33 */ mrb_define_method(mrb, mod, "module_eval", mrb_mod_module_eval, ARGS_ANY()); /* 15.2.2.4.35 */ mrb_define_method(mrb, mod, "remove_class_variable", mrb_mod_remove_cvar, ARGS_REQ(1)); /* 15.2.2.4.39 */ + mrb_define_method(mrb, mod, "remove_method", mrb_mod_remove_method, ARGS_ANY()); /* 15.2.2.4.41 */ mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, ARGS_NONE()); mrb_define_method(mrb, mod, "inspect", mrb_mod_to_s, ARGS_NONE()); diff --git a/test/t/module.rb b/test/t/module.rb index deacb3309..bf9626c2d 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -217,6 +217,25 @@ assert('Module#remove_class_variable', '15.2.2.4.39') do not Test4RemoveClassVariable.class_variables.include? :@@cv end +assert('Module#remove_method', '15.2.2.4.41') do + module Test4RemoveMethod + class Parent + def hello + end + end + + class Child < Parent + def hello + end + end + end + + Test4RemoveMethod::Child.class_eval{ remove_method :hello } + + Test4RemoveMethod::Child.instance_methods.include? :hello and + not Test4RemoveMethod::Child.instance_methods(false).include? :hello +end + # Not ISO specified |
