aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-11-01 23:24:33 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-11-01 23:24:33 +0000
commit499b5a9197f68e14873e641b737aea40a0f8bc5a (patch)
treead6295bdf751500f6577856d881bd9c27824259a
parent603fcafdc33ea5aed55240020e7287597b6b2e01 (diff)
downloadruby-499b5a9197f68e14873e641b737aea40a0f8bc5a.tar.gz
proc.c: main.define_method
* proc.c (top_define_method): new method, main.define_method. [ruby-core:45715] [Feature #6609] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37417 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog5
-rw-r--r--NEWS4
-rw-r--r--proc.c26
-rw-r--r--test/ruby/test_eval.rb18
4 files changed, 52 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 44e4aa1a47..da1712fd0b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,7 @@
-Fri Nov 2 08:23:17 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Fri Nov 2 08:24:28 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * proc.c (top_define_method): new method, main.define_method.
+ [ruby-core:45715] [Feature #6609]
* eval.c (top_include): fix a warning message, main is not a class or
module.
diff --git a/NEWS b/NEWS
index e9124a013c..7afd422ced 100644
--- a/NEWS
+++ b/NEWS
@@ -110,6 +110,10 @@ with all sufficient information, see the ChangeLog file.
* incompatible changes:
* Fiber#resume cannot resume a fiber which invokes "Fiber#transfer".
+ * toplevel
+ * added method:
+ * added main.define_method which defines a global function.
+
* net/http
* new features:
* Proxies are now automatically detected from the http_proxy environment
diff --git a/proc.c b/proc.c
index 900c3e2691..d339967220 100644
--- a/proc.c
+++ b/proc.c
@@ -1449,6 +1449,30 @@ rb_obj_define_method(int argc, VALUE *argv, VALUE obj)
}
/*
+ * define_method(symbol, method) -> new_method
+ * define_method(symbol) { block } -> proc
+ *
+ * Defines a global function by _method_ or the block.
+ */
+
+static VALUE
+top_define_method(int argc, VALUE *argv, VALUE obj)
+{
+ rb_thread_t *th = GET_THREAD();
+ VALUE klass;
+
+ rb_secure(4);
+ klass = th->top_wrapper;
+ if (klass) {
+ rb_warning("main.define_method in the wrapped load is effective only in wrapper module");
+ }
+ else {
+ klass = rb_cObject;
+ }
+ return rb_mod_define_method(argc, argv, klass);
+}
+
+/*
* call-seq:
* method.clone -> new_method
*
@@ -2290,6 +2314,8 @@ Init_Proc(void)
/* Kernel */
rb_define_method(rb_mKernel, "define_singleton_method", rb_obj_define_method, -1);
+
+ rb_define_singleton_method(rb_vm_top_self(), "define_method", top_define_method, -1);
}
/*
diff --git a/test/ruby/test_eval.rb b/test/ruby/test_eval.rb
index e7da66e149..580d3e88b1 100644
--- a/test/ruby/test_eval.rb
+++ b/test/ruby/test_eval.rb
@@ -407,6 +407,24 @@ class TestEval < Test::Unit::TestCase
assert_equal("ok", x)
end
+ def test_define_method_toplevel
+ feature6609 = '[ruby-core:45715]'
+ main = eval("self", TOPLEVEL_BINDING)
+ assert_nothing_raised(NoMethodError, feature6609) do
+ main.instance_eval do
+ define_method("feature6609_block") {feature6609}
+ end
+ end
+ assert_equal(feature6609, feature6609_block)
+
+ assert_nothing_raised(NoMethodError, feature6609) do
+ main.instance_eval do
+ define_method("feature6609_method", Object.instance_method(:feature6609_block))
+ end
+ end
+ assert_equal(feature6609, feature6609_method)
+ end
+
def test_eval_using_integer_as_binding
assert_raise(TypeError) { eval("", 1) }
end