From: Nobuyoshi Nakada Date: 2009-02-04T20:21:21+09:00 Subject: [ruby-dev:37903] Re: [Bug #1105] Ruby1.9でのrescue節の例外ハンドラのマッチの処理 なかだです。 At Wed, 4 Feb 2009 16:45:09 +0900, Tatsuji Kawai wrote in [ruby-dev:37898]: > Ruby1.9とRuby1.8では、例外ハンドルクラスのリストにExceptionのサブ > クラス以外のオブジェクトが含まれている場合の挙動に違いがあります。 これでどうでしょうか。 Index: compile.c =================================================================== --- compile.c (revision 22030) +++ compile.c (working copy) @@ -3488,7 +3488,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ case NODE_ARRAY: while (narg) { + ADD_INSN1(ret, nd_line(node), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); COMPILE(ret, "rescue arg", narg->nd_head); ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0)); - ADD_SEND(ret, nd_line(node), ID2SYM(idEqq), INT2FIX(1)); + ADD_SEND(ret, nd_line(node), ID2SYM(id_core_handle_rescue_single), INT2FIX(2)); ADD_INSNL(ret, nd_line(node), branchif, label_hit); narg = narg->nd_next; @@ -3498,9 +3499,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ case NODE_ARGSCAT: case NODE_ARGSPUSH: - ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0)); + ADD_INSN1(ret, nd_line(node), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); COMPILE(ret, "rescue/cond splat", narg); - ADD_INSN1(ret, nd_line(node), checkincludearray, Qtrue); - ADD_INSN(ret, nd_line(node), swap); - ADD_INSN(ret, nd_line(node), pop); + ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0)); + ADD_SEND(ret, nd_line(node), ID2SYM(id_core_handle_rescue_array), INT2FIX(2)); ADD_INSNL(ret, nd_line(node), branchif, label_hit); break; Index: id.c =================================================================== --- id.c (revision 22030) +++ id.c (working copy) @@ -22,15 +22,17 @@ Init_id(void) REGISTER_SYMID(idNULL, ""); - REGISTER_SYMID(idIFUNC, ""), - REGISTER_SYMID(idCFUNC, ""), - REGISTER_SYMID(idRespond_to, "respond_to?"), - REGISTER_SYMID(idThrowState, "#__ThrowState__"), + REGISTER_SYMID(idIFUNC, ""); + REGISTER_SYMID(idCFUNC, ""); + REGISTER_SYMID(idRespond_to, "respond_to?"); + REGISTER_SYMID(idThrowState, "#__ThrowState__"); - REGISTER_SYMID(id_core_set_method_alias, "core#set_method_alias"), - REGISTER_SYMID(id_core_set_variable_alias, "core#set_variable_alias"), - REGISTER_SYMID(id_core_undef_method, "core#undef_method"), - REGISTER_SYMID(id_core_define_method, "core#define_method"), - REGISTER_SYMID(id_core_define_singleton_method, "core#define_singleton_method"), - REGISTER_SYMID(id_core_set_postexe, "core#set_postexe"), + REGISTER_SYMID(id_core_set_method_alias, "core#set_method_alias"); + REGISTER_SYMID(id_core_set_variable_alias, "core#set_variable_alias"); + REGISTER_SYMID(id_core_undef_method, "core#undef_method"); + REGISTER_SYMID(id_core_define_method, "core#define_method"); + REGISTER_SYMID(id_core_define_singleton_method, "core#define_singleton_method"); + REGISTER_SYMID(id_core_set_postexe, "core#set_postexe"); + REGISTER_SYMID(id_core_handle_rescue_single, "core#handle_rescue_single"); + REGISTER_SYMID(id_core_handle_rescue_array, "core#handle_rescue_array"); REGISTER_SYMID(idEach, "each"); Index: id.h =================================================================== --- id.h (revision 22030) +++ id.h (working copy) @@ -69,5 +69,7 @@ enum ruby_method_ids { id_core_define_singleton_method = 374, id_core_set_postexe = 375, - tLAST_TOKEN = 376, + id_core_handle_rescue_single = 376, + id_core_handle_rescue_array = 377, + tLAST_TOKEN = 378, #endif idPLUS = '+', @@ -157,5 +159,7 @@ ruby_method_id_check_for(id_core_define_ ruby_method_id_check_for(id_core_define_singleton_method, 374); ruby_method_id_check_for(id_core_set_postexe, 375); -ruby_method_id_check_for(tLAST_TOKEN, 376); +ruby_method_id_check_for(id_core_handle_rescue_single, 376); +ruby_method_id_check_for(id_core_handle_rescue_array, 377); +ruby_method_id_check_for(tLAST_TOKEN, 378); }; #endif Index: parse.y =================================================================== --- parse.y (revision 22030) +++ parse.y (working copy) @@ -758,4 +758,6 @@ static void token_info_pop(struct parser %nonassoc id_core_define_singleton_method %nonassoc id_core_set_postexe +%nonassoc id_core_handle_rescue_single +%nonassoc id_core_handle_rescue_array %token tLAST_TOKEN Index: vm.c =================================================================== --- vm.c (revision 22030) +++ vm.c (working copy) @@ -1825,4 +1825,36 @@ nsdr(void) } +static VALUE +check_rescue_arg(VALUE klass) +{ + if (!rb_obj_is_kind_of(klass, rb_cModule)) { + VALUE args[3]; + args[0] = rb_eTypeError; + args[1] = rb_str_new2("class or module required for rescue clause"); + args[2] = vm_backtrace(GET_THREAD(), 0); + rb_exc_raise(rb_make_exception(sizeof(args) / sizeof(args[0]), args)); + } + return klass; +} + +static VALUE +m_core_handle_rescue_single(VALUE self, VALUE klass, VALUE exc) +{ + check_rescue_arg(klass); + return rb_funcall(klass, idEqq, 1, exc); +} + +static VALUE +m_core_handle_rescue_array(VALUE self, VALUE klass, VALUE ary) +{ + long i; + check_rescue_arg(klass); + for (i = 0; i < RARRAY_LEN(ary); ++i) { + VALUE result = rb_funcall(klass, idEqq, 1, RARRAY_PTR(ary)[i]); + if (RTEST(result)) return result; + } + return Qfalse; +} + void Init_VM(void) @@ -1846,4 +1878,6 @@ Init_VM(void) rb_define_method_id(klass, id_core_define_singleton_method, m_core_define_singleton_method, 3); rb_define_method_id(klass, id_core_set_postexe, m_core_set_postexe, 1); + rb_define_method_id(klass, id_core_handle_rescue_single, m_core_handle_rescue_single, 2); + rb_define_method_id(klass, id_core_handle_rescue_array, m_core_handle_rescue_array, 2); rb_obj_freeze(fcore); rb_gc_register_mark_object(fcore); -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦