From: wanabe Date: 2009-10-18T06:16:55+09:00 Subject: [ruby-dev:39506] [Bug:1.9] case 文の式が省略され when 節に配列展開があるときの挙動 ワナベと申します。 case 文の式が省略され、かつ when 節に配列展開があるときの挙動、 より具体的には NODE_ARGSCAT, NODE_ARGSPUSH の コンパイル結果が正しくないように思います。 通常の NODE_CASE と同じように処理するのはどうでしょうか。 $ cat test.rb case when *[], false p :ng1 else p :ok end case when *false, [] p :ok else p :ng2 end begin case when false, *nonexistent_var, false p :ng3 else p :ng4 end rescue NameError p :ok end $ ruby -v test.rb ruby 1.9.2dev (2009-10-17 trunk 25387) [i386-mingw32] :ng1 :ng2 :ng3 Index: compile.c =================================================================== --- compile.c (revision 25387) +++ compile.c (working copy) @@ -3116,41 +3116,31 @@ ADD_INSNL(body_seq, nd_line(node), jump, endlabel); vals = node->nd_head; - if (vals && nd_type(vals) == NODE_ARRAY) { + if (!vals) { + rb_bug("NODE_WHEN: must be NODE_ARRAY, but 0"); + } + switch (nd_type(vals)) { + case NODE_ARRAY: while (vals) { val = vals->nd_head; COMPILE(ret, "when2", val); ADD_INSNL(ret, nd_line(val), branchif, l1); vals = vals->nd_next; } + break; + case NODE_SPLAT: + case NODE_ARGSCAT: + case NODE_ARGSPUSH: + ADD_INSN(ret, nd_line(vals), putnil); + COMPILE(ret, "when2/cond splat", vals); + ADD_INSN1(ret, nd_line(vals), checkincludearray, Qfalse); + ADD_INSN(ret, nd_line(vals), pop); + ADD_INSNL(ret, nd_line(vals), branchif, l1); + break; + default: + rb_bug("NODE_WHEN: unknown node (%s)", + ruby_node_name(nd_type(vals))); } - else if (nd_type(vals) == NODE_SPLAT || - nd_type(vals) == NODE_ARGSCAT || - nd_type(vals) == NODE_ARGSPUSH) { - - NODE *val = vals->nd_head; - - if (nd_type(vals) == NODE_ARGSCAT || nd_type(vals) == NODE_ARGSPUSH) { - NODE *vs = vals->nd_head; - val = vals->nd_body; - - while (vs) { - NODE* val = vs->nd_head; - COMPILE(ret, "when/argscat", val); - ADD_INSNL(ret, nd_line(val), branchif, l1); - vs = vs->nd_next; - } - } - - ADD_INSN(ret, nd_line(val), putnil); - COMPILE(ret, "when2/splat", val); - ADD_INSN1(ret, nd_line(val), checkincludearray, Qfalse); - ADD_INSN(ret, nd_line(val), pop); - ADD_INSNL(ret, nd_line(val), branchif, l1); - } - else { - rb_bug("err"); - } node = node->nd_next; } /* else */ -- ワナベ