From 499b5a9197f68e14873e641b737aea40a0f8bc5a Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 1 Nov 2012 23:24:33 +0000 Subject: [PATCH] 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 --- ChangeLog | 5 ++++- NEWS | 4 ++++ proc.c | 26 ++++++++++++++++++++++++++ test/ruby/test_eval.rb | 18 ++++++++++++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) 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 +Fri Nov 2 08:24:28 2012 Nobuyoshi Nakada + + * 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 @@ -1448,6 +1448,30 @@ rb_obj_define_method(int argc, VALUE *argv, VALUE obj) return rb_mod_define_method(argc, argv, klass); } +/* + * 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