summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2012-12-29 01:02:05 -0800
committerYukihiro "Matz" Matsumoto <[email protected]>2012-12-29 01:02:05 -0800
commit50e3a53d7377c9cf94b70d553fe4060edcec8fc9 (patch)
treeb7f76ac65c7f8648e02e7687dbe5b295755eae01
parentc836187cf27c058b9e8fd98814e9fc26f05640a5 (diff)
parent9219c856a8586fbda74fec526303d19c70290484 (diff)
downloadmruby-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.c43
-rw-r--r--test/t/module.rb19
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