diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2018-08-25 09:10:37 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2018-08-25 09:41:21 +0900 |
| commit | 49d1b168221221b7e810f001d88e16ebc94378fd (patch) | |
| tree | 10ff0f8b4e9b8bb7e8dea4003f2126e9e2c3bf5b | |
| parent | 306732e02da5f0d47f44033ec1a3af1a77c5f418 (diff) | |
| download | mruby-49d1b168221221b7e810f001d88e16ebc94378fd.tar.gz mruby-49d1b168221221b7e810f001d88e16ebc94378fd.zip | |
Hash splat `**` should not be ignored.
Implemented by adding `OP_HASHCAT` that merges hashes.
| -rw-r--r-- | include/mruby/ops.h | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-compiler/core/codegen.c | 37 | ||||
| -rw-r--r-- | src/codedump.c | 6 | ||||
| -rw-r--r-- | src/vm.c | 5 |
4 files changed, 39 insertions, 10 deletions
diff --git a/include/mruby/ops.h b/include/mruby/ops.h index b8fc89d43..f23bb1b0b 100644 --- a/include/mruby/ops.h +++ b/include/mruby/ops.h @@ -94,6 +94,7 @@ OPCODE(STRING, BB) /* R(a) = str_dup(Lit(b)) */ 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(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(BLOCK, BB) /* R(a) = lambda(SEQ[b],L_BLOCK) */ OPCODE(METHOD, BB) /* R(a) = lambda(SEQ[b],L_METHOD) */ diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 8e72abda2..bf5cc14b0 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1874,15 +1874,32 @@ codegen(codegen_scope *s, node *tree, int val) mrb_bool update = FALSE; while (tree) { - if (nt == NODE_KW_HASH && - nint(tree->car->car->car) == NODE_KW_REST_ARGS) { - tree = tree->cdr; - continue; + if (nint(tree->car->car->car) == NODE_KW_REST_ARGS) { + if (len > 0) { + pop_n(len*2); + 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; if (val && len == 255) { pop_n(len*2); @@ -1905,7 +1922,9 @@ codegen(codegen_scope *s, node *tree, int val) } else { pop(); - genop_2(s, OP_HASHADD, cursp(), len); + if (len > 0) { + genop_2(s, OP_HASHADD, cursp(), len); + } } push(); } diff --git a/src/codedump.c b/src/codedump.c index 842d40bdf..9174ebe3d 100644 --- a/src/codedump.c +++ b/src/codedump.c @@ -416,7 +416,11 @@ codedump(mrb_state *mrb, mrb_irep *irep) print_lv_a(mrb, irep, a); break; 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); break; @@ -2710,6 +2710,11 @@ RETRY_TRY_BLOCK: mrb_gc_arena_restore(mrb, ai); 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) c = OP_L_LAMBDA; |
