summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authorktsj <ktsj@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-12-30 02:06:28 +0000
committerktsj <ktsj@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-12-30 02:06:28 +0000
commit371c07f2a2ce59ff9a045181b997826b3da3ef8a (patch)
tree88071fd4b0226109772dafc1ce71b2019735a21b /vm_insnhelper.c
parentb0767cf8c03ad9a656dec63712a8b3f8cf00394f (diff)
* vm_insnhelper.c: set keyword hash on Proc/block calls.
[ruby-core:51172] [Bug #7630] * test/ruby/test_keyword.rb: add tests for above. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38657 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c58
1 files changed, 35 insertions, 23 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 144fc1fb4a..d6cc9f90ef 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1065,6 +1065,34 @@ vm_caller_setup_args(const rb_thread_t *th, rb_control_frame_t *cfp, rb_call_inf
}
static inline int
+vm_callee_setup_keyword_arg(const rb_iseq_t *iseq, int argc, VALUE *orig_argv)
+{
+ VALUE keyword_hash = Qnil;
+ int i, j;
+
+ if (argc > 0) keyword_hash = rb_check_hash_type(orig_argv[argc-1]);
+ if (!NIL_P(keyword_hash)) {
+ argc--;
+ keyword_hash = rb_hash_dup(keyword_hash);
+ if (iseq->arg_keyword_check) {
+ for (i = j = 0; i < iseq->arg_keywords; i++) {
+ if (st_lookup(RHASH_TBL(keyword_hash), ID2SYM(iseq->arg_keyword_table[i]), 0)) j++;
+ }
+ if (RHASH_TBL(keyword_hash)->num_entries > (unsigned int) j) {
+ unknown_keyword_error(iseq, keyword_hash);
+ }
+ }
+ }
+ else {
+ keyword_hash = rb_hash_new();
+ }
+
+ orig_argv[iseq->arg_keyword] = keyword_hash;
+
+ return argc;
+}
+
+static inline int
vm_callee_setup_arg_complex(rb_thread_t *th, rb_call_info_t *ci, const rb_iseq_t *iseq, VALUE *orig_argv)
{
const int m = iseq->argc;
@@ -1074,29 +1102,13 @@ vm_callee_setup_arg_complex(rb_thread_t *th, rb_call_info_t *ci, const rb_iseq_t
const int orig_argc = ci->argc;
int argc = orig_argc;
VALUE *argv = orig_argv;
- VALUE keyword_hash = Qnil;
rb_num_t opt_pc = 0;
th->mark_stack_len = argc + iseq->arg_size;
+ /* keyword argument */
if (iseq->arg_keyword != -1) {
- int i, j;
- 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);
- if (iseq->arg_keyword_check) {
- for (i = j = 0; i < iseq->arg_keywords; i++) {
- if (st_lookup(RHASH_TBL(keyword_hash), ID2SYM(iseq->arg_keyword_table[i]), 0)) j++;
- }
- if (RHASH_TBL(keyword_hash)->num_entries > (unsigned int) j) {
- unknown_keyword_error(iseq, keyword_hash);
- }
- }
- }
- else {
- keyword_hash = rb_hash_new();
- }
+ argc = vm_callee_setup_keyword_arg(iseq, argc, orig_argv);
}
/* mandatory */
@@ -1142,11 +1154,6 @@ vm_callee_setup_arg_complex(rb_thread_t *th, rb_call_info_t *ci, const rb_iseq_t
argc = 0;
}
- /* keyword argument */
- if (iseq->arg_keyword != -1) {
- orig_argv[iseq->arg_keyword] = keyword_hash;
- }
-
/* block arguments */
if (iseq->arg_block != -1) {
VALUE blockval = Qnil;
@@ -2085,6 +2092,11 @@ vm_yield_setup_block_args(rb_thread_t *th, const rb_iseq_t * iseq,
th->mark_stack_len = argc;
+ /* keyword argument */
+ if (iseq->arg_keyword != -1) {
+ argc = vm_callee_setup_keyword_arg(iseq, argc, argv);
+ }
+
/*
* yield [1, 2]
* => {|a|} => a = [1, 2]