Bug #7630 ยป proc-keyword-arg.patch
vm_insnhelper.c | ||
---|---|---|
}
|
||
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;
|
||
... | ... | |
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 */
|
||
... | ... | |
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;
|
||
... | ... | |
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]
|