From df27d91fc4de9215d6af58de191b2c105ef88678 Mon Sep 17 00:00:00 2001 From: matz Date: Mon, 5 Sep 2005 08:40:27 +0000 Subject: * lib/observer.rb: a patch from nornagon merged to allow arbitrary names for update methods. [ruby-core:05416] * eval.c (rb_f_fcall): new method to avoid inefficiency of obj.instance_eval{send(...)} tricks. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9082 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- eval.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 13 deletions(-) (limited to 'eval.c') diff --git a/eval.c b/eval.c index c52d889d62..3e7504ae05 100644 --- a/eval.c +++ b/eval.c @@ -6062,6 +6062,25 @@ rb_apply(recv, mid, args) return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1); } +static VALUE +send_fcall(argc, argv, recv, scope) + int argc; + VALUE *argv; + VALUE recv; + int scope; +{ + VALUE vid; + + if (argc == 0) rb_raise(rb_eArgError, "no method name given"); + + vid = *argv++; argc--; + PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT); + vid = rb_call(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, scope); + POP_ITER(); + + return vid; +} + /* * call-seq: * obj.send(symbol [, args...]) => obj @@ -6069,7 +6088,9 @@ rb_apply(recv, mid, args) * * Invokes the method identified by _symbol_, passing it any * arguments specified. You can use __send__ if the name - * +send+ clashes with an existing method in _obj_. + * +send+ clashes with an existing method in _obj_. Raises an + * NoMethodError exception for private methods except when it is + * called in function call style. * * class Klass * def hello(*args) @@ -6078,6 +6099,9 @@ rb_apply(recv, mid, args) * end * k = Klass.new * k.send :hello, "gentle", "readers" #=> "Hello gentle readers" + * + * 1.send(:puts, "foo") # NoMethodError exception + * send(:puts, "foo") # prints "foo" */ static VALUE @@ -6086,17 +6110,30 @@ rb_f_send(argc, argv, recv) VALUE *argv; VALUE recv; { - VALUE vid; int scope = (ruby_frame->flags & FRAME_FUNC) ? 1 : 0; - if (argc == 0) rb_raise(rb_eArgError, "no method name given"); + return send_fcall(argc, argv, recv, scope); +} - vid = *argv++; argc--; - PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT); - vid = rb_call(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, scope); - POP_ITER(); +/* + * call-seq: + * obj.fcall(symbol [, args...]) => obj + * + * Invokes the method identified by _symbol_, passing it any + * arguments specified. Unlike send, which calls private methods only + * when it is invoked in function call style, fcall always aware of + * private methods. + * + * 1.fcall(:puts, "hello") # prints "foo" + */ - return vid; +static VALUE +rb_f_fcall(argc, argv, recv) + int argc; + VALUE *argv; + VALUE recv; +{ + return send_fcall(argc, argv, recv, 1); } VALUE @@ -7458,18 +7495,18 @@ rb_mod_modfunc(argc, argv, module) */ static VALUE -rb_mod_append_features(module, include) - VALUE module, include; +rb_mod_append_features(module, dest) + VALUE module, dest; { - switch (TYPE(include)) { + switch (TYPE(dest)) { case T_CLASS: case T_MODULE: break; default: - Check_Type(include, T_CLASS); + Check_Type(dest, T_CLASS); break; } - rb_include_module(include, module); + rb_include_module(dest, module); return module; } @@ -7907,6 +7944,7 @@ Init_eval() rb_define_method(rb_mKernel, "send", rb_f_send, -1); rb_define_method(rb_mKernel, "__send__", rb_f_send, -1); + rb_define_method(rb_mKernel, "fcall", rb_f_fcall, -1); rb_define_method(rb_mKernel, "instance_eval", rb_obj_instance_eval, -1); rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1); -- cgit v1.2.3