* compile.c (iseq_set_arguments): keyword rest arg without keyword args.

* node.c (dump_node): dump kw_rest_arg too.
* parse.y (block_param, f_arg): more kwrest patterns.
  [ruby-core:42455][Bug #5989]
* parse.y (new_args_gen): no extra kw_rest_arg if no keyword rest arg.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34999 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2012-03-13 13:00:17 +00:00
Родитель d6a977f667
Коммит 8fe3fb4c0f
6 изменённых файлов: 241 добавлений и 708 удалений

Просмотреть файл

@ -1,3 +1,14 @@
Tue Mar 13 22:00:14 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* compile.c (iseq_set_arguments): keyword rest arg without keyword args.
* node.c (dump_node): dump kw_rest_arg too.
* parse.y (block_param, f_arg): more kwrest patterns.
[ruby-core:42455][Bug #5989]
* parse.y (new_args_gen): no extra kw_rest_arg if no keyword rest arg.
Tue Mar 13 15:17:03 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* parse.y (block_param, f_args): add rules for the case arguments

Просмотреть файл

@ -1166,6 +1166,12 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args)
}
ADD_INSN(optargs, nd_line(args->kw_args), pop);
}
else if (args->kw_rest_arg) {
iseq->arg_keyword = get_dyna_var_idx_at_raw(iseq, args->kw_rest_arg->nd_vid);
COMPILE(optargs, "kwarg", args->kw_rest_arg);
iseq->arg_keyword_check = (args->kw_rest_arg->nd_vid & ID_SCOPE_MASK) == ID_JUNK;
ADD_INSN(optargs, nd_line(args->kw_rest_arg), pop);
}
else {
iseq->arg_keyword = -1;
}
@ -4992,17 +4998,17 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
ADD_INSN1(ret, nd_line(node), putobject, ID2SYM(id));
ADD_SEND(ret, nd_line(node), ID2SYM(rb_intern("delete")), INT2FIX(1));
switch (nd_type(node->nd_body)) {
case NODE_LASGN:
idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id);
ADD_INSN1(ret, nd_line(node), setlocal, INT2FIX(idx));
break;
case NODE_DASGN:
case NODE_DASGN_CURR:
idx = get_dyna_var_idx(iseq, id, &lv, &ls);
ADD_INSN2(ret, nd_line(node), setdynamic, INT2FIX(ls - idx), INT2FIX(lv));
break;
default:
rb_bug("iseq_compile_each (NODE_KW_ARG): unknown node: %s", ruby_node_name(nd_type(node->nd_body)));
case NODE_LASGN:
idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id);
ADD_INSN1(ret, nd_line(node), setlocal, INT2FIX(idx));
break;
case NODE_DASGN:
case NODE_DASGN_CURR:
idx = get_dyna_var_idx(iseq, id, &lv, &ls);
ADD_INSN2(ret, nd_line(node), setdynamic, INT2FIX(ls - idx), INT2FIX(lv));
break;
default:
rb_bug("iseq_compile_each (NODE_KW_ARG): unknown node: %s", ruby_node_name(nd_type(node->nd_body)));
}
ADD_INSNL(ret, nd_line(node), jump, end_label);
ADD_LABEL(ret, default_label);

1
node.c
Просмотреть файл

@ -860,6 +860,7 @@ dump_node(VALUE buf, VALUE indent, int comment, NODE *node)
F_NODE(nd_ainfo->opt_args, "optional arguments");
LAST_NODE;
F_NODE(nd_ainfo->kw_args, "keyword arguments");
F_NODE(nd_ainfo->kw_rest_arg, "keyword rest argument");
break;
case NODE_SCOPE:

898
parse.y

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -79,8 +79,13 @@ class TestSyntax < Test::Unit::TestCase
def test_keyword_rest
bug5989 = '[ruby-core:42455]'
assert_valid_syntax("def kwrest_test(**a) end", __FILE__)
assert_valid_syntax("def kwrest_test(**a, &b) end", __FILE__)
assert_valid_syntax("def kwrest_test(**a) a; end", __FILE__)
assert_valid_syntax("def kwrest_test2(**a, &b) end", __FILE__)
o = Object.new
def o.kw(**a) a end
assert_equal({}, o.kw)
assert_equal({foo: 1}, o.kw(foo: 1))
assert_equal({foo: 1, bar: 2}, o.kw(foo: 1, bar: 2))
end
private

Просмотреть файл

@ -177,7 +177,7 @@ vm_callee_setup_arg_complex(rb_thread_t *th, const rb_iseq_t * iseq,
if (iseq->arg_keyword != -1) {
int i, j;
if (argc > 0) keyword_hash = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
if (argc > 0) keyword_hash = rb_check_hash_type(argv[argc-1]);
if (!NIL_P(keyword_hash)) {
argc--;
keyword_hash = rb_hash_dup(keyword_hash);