summaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/compile.c b/compile.c
index 3315716cc5..aca710e2b0 100644
--- a/compile.c
+++ b/compile.c
@@ -3940,6 +3940,8 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_ro
else {
int opt_p = 1;
int first = 1, i;
+ int single_kw = 0;
+ int num_kw = 0;
while (node) {
const NODE *start_node = node, *end_node;
@@ -3955,11 +3957,15 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_ro
if (type == COMPILE_ARRAY_TYPE_HASH && !node->nd_head) {
kw = node->nd_next;
+ num_kw++;
node = 0;
if (kw) {
opt_p = 0;
node = kw->nd_next;
kw = kw->nd_head;
+ if (!single_kw && !node) {
+ single_kw = 1;
+ }
}
break;
}
@@ -4053,6 +4059,7 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_ro
}
case COMPILE_ARRAY_TYPE_HASH:
if (i > 0) {
+ num_kw++;
if (first) {
if (!popped) {
ADD_INSN1(anchor, line, newhash, INT2FIX(i));
@@ -4071,16 +4078,27 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_ro
}
}
if (kw) {
- if (!popped) {
- ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- if (i > 0 || !first) ADD_INSN(ret, line, swap);
- else ADD_INSN1(ret, line, newhash, INT2FIX(0));
+ int empty_kw = nd_type(kw) == NODE_LIT;
+ int first_kw = num_kw == 1;
+ int only_kw = single_kw && first_kw;
+
+ if (!popped && !empty_kw) {
+ ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ if (i > 0 || !first) ADD_INSN(ret, line, swap);
+ else ADD_INSN1(ret, line, newhash, INT2FIX(0));
}
- NO_CHECK(COMPILE(ret, "keyword splat", kw));
+
+ if (empty_kw && first_kw && !only_kw) {
+ ADD_INSN1(ret, line, newhash, INT2FIX(0));
+ }
+ else if (!empty_kw || only_kw) {
+ NO_CHECK(COMPILE(ret, "keyword splat", kw));
+ }
+
if (popped) {
ADD_INSN(ret, line, pop);
}
- else {
+ else if (!empty_kw) {
ADD_SEND(ret, line, id_core_hash_merge_kwd, INT2FIX(2));
}
}