diff options
author | yugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-02-22 14:05:31 +0000 |
---|---|---|
committer | yugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-02-22 14:05:31 +0000 |
commit | 41031667c9f1cbef8e88dbdb5f2988e95837f508 (patch) | |
tree | 10993c12f8f71f9728454f32759be9679822d67c /vm_eval.c | |
parent | 5fd244b440ed2898d4d4940257800bc8d8247a33 (diff) |
merges r22494 and r22495 from trunk into ruby_1_9_1.
* vm_eval.c (method_missing): should not pop cfp if missing method
is method_missing. [ruby-core:22298]
* vm_eval.c (rb_raise_method_missing): new function to directly
raise NoMethodError.
* vm_insnhelper.c (vm_call_method): fixed the case method_missing
is missing.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_9_1@22551 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_eval.c')
-rw-r--r-- | vm_eval.c | 33 |
1 files changed, 27 insertions, 6 deletions
@@ -255,6 +255,9 @@ rb_call(VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv, int scope) return rb_call0(klass, recv, mid, argc, argv, scope, Qundef); } +NORETURN(static void raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, + VALUE obj, int call_status)); + /* * call-seq: * obj.method_missing(symbol [, *args] ) => result @@ -291,11 +294,21 @@ rb_call(VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv, int scope) static VALUE rb_method_missing(int argc, const VALUE *argv, VALUE obj) { + rb_thread_t *th = GET_THREAD(); + raise_method_missing(th, argc, argv, obj, th->method_missing_reason); + return Qnil; /* not reached */ +} + +#define NOEX_MISSING 0x80 + +static void +raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, VALUE obj, + int last_call_status) +{ ID id; VALUE exc = rb_eNoMethodError; const char *format = 0; - rb_thread_t *th = GET_THREAD(); - int last_call_status = th->method_missing_reason; + if (argc == 0 || !SYMBOL_P(argv[0])) { rb_raise(rb_eArgError, "no id given"); } @@ -332,11 +345,11 @@ rb_method_missing(int argc, const VALUE *argv, VALUE obj) } exc = rb_class_new_instance(n, args, exc); - th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); + if (!(last_call_status & NOEX_MISSING)) { + th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); + } rb_exc_raise(exc); } - - return Qnil; /* not reached */ } static inline VALUE @@ -349,7 +362,7 @@ method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status) th->passed_block = 0; if (id == idMethodMissing) { - rb_method_missing(argc, argv, obj); + raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING); } else if (id == ID_ALLOCATOR) { rb_raise(rb_eTypeError, "allocator undefined for %s", @@ -371,6 +384,14 @@ method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status) return result; } +void +rb_raise_method_missing(rb_thread_t *th, int argc, VALUE *argv, + VALUE obj, int call_status) +{ + th->passed_block = 0; + raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING); +} + VALUE rb_apply(VALUE recv, ID mid, VALUE args) { |