summaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-08-05 06:58:44 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-08-05 06:58:44 +0000
commit26aed9c5779cadf6d8a2030e4cc25958efbda522 (patch)
treee86f7f48de3660eb536cd32a39a8f58db1425568 /compile.c
parentd11dfab56911ff3daefc1d9e552ff14b5e53c665 (diff)
splat keyword hash
* compile.c (compile_array_keyword_arg): set keyword splat flag if explicitly splatted. [ruby-core:68124] [Bug #10856] * vm_args.c (setup_parameters_complex): try keyword hash splat if given. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59519 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/compile.c b/compile.c
index d3612b3995..b21f002c9d 100644
--- a/compile.c
+++ b/compile.c
@@ -1088,7 +1088,7 @@ new_callinfo(rb_iseq_t *iseq, ID mid, int argc, unsigned int flag, struct rb_cal
iseq->body->ci_size++;
}
- if (!(ci->flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG)) &&
+ if (!(ci->flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG | VM_CALL_KW_SPLAT)) &&
kw_arg == NULL && !has_blockiseq) {
ci->flag |= VM_CALL_ARGS_SIMPLE;
}
@@ -3040,7 +3040,8 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *cond,
static int
compile_array_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
const NODE *const root_node,
- struct rb_call_info_kw_arg **const kw_arg_ptr)
+ struct rb_call_info_kw_arg **const kw_arg_ptr,
+ unsigned int *flag)
{
if (kw_arg_ptr == NULL) return FALSE;
@@ -3055,6 +3056,7 @@ compile_array_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
/* can be keywords */
}
else {
+ if (flag) *flag |= VM_CALL_KW_SPLAT;
return FALSE;
}
node = node->nd_next; /* skip value node */
@@ -3124,7 +3126,8 @@ static_literal_value(NODE *node)
static int
compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE* node_root,
- enum compile_array_type_t type, struct rb_call_info_kw_arg **keywords_ptr, int popped)
+ enum compile_array_type_t type, struct rb_call_info_kw_arg **keywords_ptr,
+ unsigned int *flag, int popped)
{
NODE *node = node_root;
int line = (int)nd_line(node);
@@ -3169,7 +3172,9 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE* node_root,
opt_p = 0;
}
- if (type == COMPILE_ARRAY_TYPE_ARGS && node->nd_next == NULL /* last node */ && compile_array_keyword_arg(iseq, anchor, node->nd_head, keywords_ptr)) {
+ if (type == COMPILE_ARRAY_TYPE_ARGS &&
+ node->nd_next == NULL /* last node */ &&
+ compile_array_keyword_arg(iseq, anchor, node->nd_head, keywords_ptr, flag)) {
len--;
}
else {
@@ -3981,7 +3986,7 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *const args, NODE *argn,
*flag |= VM_CALL_ARGS_SPLAT;
if (next_is_array) {
- int len = compile_array(iseq, args, argn->nd_head, COMPILE_ARRAY_TYPE_ARGS, NULL, FALSE);
+ int len = compile_array(iseq, args, argn->nd_head, COMPILE_ARRAY_TYPE_ARGS, NULL, flag, FALSE);
if (len < 0) return Qnil;
argc = INT2FIX(len + 1);
}
@@ -3993,7 +3998,7 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *const args, NODE *argn,
}
case NODE_ARRAY:
{
- int len = compile_array(iseq, args, argn, COMPILE_ARRAY_TYPE_ARGS, keywords, FALSE);
+ int len = compile_array(iseq, args, argn, COMPILE_ARRAY_TYPE_ARGS, keywords, flag, FALSE);
if (len < 0) return Qnil;
argc = INT2FIX(len);
break;
@@ -5620,7 +5625,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popp
break;
}
case NODE_ARRAY:{
- CHECK(compile_array(iseq, ret, node, COMPILE_ARRAY_TYPE_ARRAY, NULL, popped) >= 0);
+ CHECK(compile_array(iseq, ret, node, COMPILE_ARRAY_TYPE_ARRAY, NULL, NULL, popped) >= 0);
break;
}
case NODE_ZARRAY:{
@@ -5648,7 +5653,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popp
INIT_ANCHOR(list);
switch (type) {
case NODE_ARRAY:
- CHECK(compile_array(iseq, list, node->nd_head, COMPILE_ARRAY_TYPE_HASH, NULL, popped) >= 0);
+ CHECK(compile_array(iseq, list, node->nd_head, COMPILE_ARRAY_TYPE_HASH, NULL, NULL, popped) >= 0);
ADD_SEQ(ret, list);
break;