Hash splat `**` should not be ignored.

Implemented by adding `OP_HASHCAT` that merges hashes.
parent 306732e0
...@@ -94,6 +94,7 @@ OPCODE(STRING, BB) /* R(a) = str_dup(Lit(b)) */ ...@@ -94,6 +94,7 @@ OPCODE(STRING, BB) /* R(a) = str_dup(Lit(b)) */
OPCODE(STRCAT, B) /* str_cat(R(a),R(a+1)) */ OPCODE(STRCAT, B) /* str_cat(R(a),R(a+1)) */
OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b)) */ OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b)) */
OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b)) */ OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b)) */
OPCODE(HASHCAT, B) /* R(a) = hash_cat(R(a),R(a+1)) */
OPCODE(LAMBDA, BB) /* R(a) = lambda(SEQ[b],L_LAMBDA) */ OPCODE(LAMBDA, BB) /* R(a) = lambda(SEQ[b],L_LAMBDA) */
OPCODE(BLOCK, BB) /* R(a) = lambda(SEQ[b],L_BLOCK) */ OPCODE(BLOCK, BB) /* R(a) = lambda(SEQ[b],L_BLOCK) */
OPCODE(METHOD, BB) /* R(a) = lambda(SEQ[b],L_METHOD) */ OPCODE(METHOD, BB) /* R(a) = lambda(SEQ[b],L_METHOD) */
......
...@@ -1874,15 +1874,32 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -1874,15 +1874,32 @@ codegen(codegen_scope *s, node *tree, int val)
mrb_bool update = FALSE; mrb_bool update = FALSE;
while (tree) { while (tree) {
if (nt == NODE_KW_HASH && if (nint(tree->car->car->car) == NODE_KW_REST_ARGS) {
nint(tree->car->car->car) == NODE_KW_REST_ARGS) { if (len > 0) {
tree = tree->cdr; pop_n(len*2);
continue; if (!update) {
genop_2(s, OP_HASH, cursp(), len);
}
else {
pop();
genop_2(s, OP_HASHADD, cursp(), len);
}
push();
}
codegen(s, tree->car->cdr, VAL);
if (len > 0) {
pop(); pop();
genop_1(s, OP_HASHCAT, cursp());
push();
}
update = TRUE;
len = 0;
}
else {
codegen(s, tree->car->car, VAL);
codegen(s, tree->car->cdr, VAL);
len++;
} }
codegen(s, tree->car->car, val);
codegen(s, tree->car->cdr, val);
len++;
tree = tree->cdr; tree = tree->cdr;
if (val && len == 255) { if (val && len == 255) {
pop_n(len*2); pop_n(len*2);
...@@ -1905,7 +1922,9 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -1905,7 +1922,9 @@ codegen(codegen_scope *s, node *tree, int val)
} }
else { else {
pop(); pop();
genop_2(s, OP_HASHADD, cursp(), len); if (len > 0) {
genop_2(s, OP_HASHADD, cursp(), len);
}
} }
push(); push();
} }
......
...@@ -416,7 +416,11 @@ codedump(mrb_state *mrb, mrb_irep *irep) ...@@ -416,7 +416,11 @@ codedump(mrb_state *mrb, mrb_irep *irep)
print_lv_a(mrb, irep, a); print_lv_a(mrb, irep, a);
break; break;
CASE(OP_HASHADD, BB): CASE(OP_HASHADD, BB):
printf("OP_HASHADD\tR%d\t%d", a, b); printf("OP_HASHADD\tR%d\t%d\t", a, b);
print_lv_a(mrb, irep, a);
break;
CASE(OP_HASHCAT, B):
printf("OP_HASHCAT\tR%d\t", a);
print_lv_a(mrb, irep, a); print_lv_a(mrb, irep, a);
break; break;
......
...@@ -2710,6 +2710,11 @@ RETRY_TRY_BLOCK: ...@@ -2710,6 +2710,11 @@ RETRY_TRY_BLOCK:
mrb_gc_arena_restore(mrb, ai); mrb_gc_arena_restore(mrb, ai);
NEXT; NEXT;
} }
CASE(OP_HASHCAT, B) {
mrb_hash_merge(mrb, regs[a], regs[a+1]);
mrb_gc_arena_restore(mrb, ai);
NEXT;
}
CASE(OP_LAMBDA, BB) CASE(OP_LAMBDA, BB)
c = OP_L_LAMBDA; c = OP_L_LAMBDA;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment