mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Consolidate empty keyword handling
Remove rb_add_empty_keyword, and instead of calling that every place you need to add empty keyword hashes, run that code in a single static function in vm_eval.c. Add 4 defines to include/ruby/ruby.h, these are to be used as int kw_splat values when calling the various rb_*_kw functions: RB_NO_KEYWORDS :: Do not pass keywords RB_PASS_KEYWORDS :: Pass final argument (which should be hash) as keywords RB_PASS_EMPTY_KEYWORDS :: Add an empty hash to arguments and pass as keywords RB_PASS_CALLED_KEYWORDS :: Passes same keyword type as current method was called with (for method delegation) rb_empty_keyword_given_p needs to stay. It is required if argument delegation is done but delayed to a later point, which Enumerator does. Use RB_PASS_CALLED_KEYWORDS in rb_call_super to correctly delegate keyword arguments to super method.
This commit is contained in:
parent
24b1b33975
commit
3cfbfa9628
6 changed files with 34 additions and 32 deletions
10
enumerator.c
10
enumerator.c
|
@ -370,7 +370,7 @@ enumerator_allocate(VALUE klass)
|
||||||
return enum_obj;
|
return enum_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PASS_KW_SPLAT (rb_empty_keyword_given_p() ? 2 : rb_keyword_given_p())
|
#define PASS_KW_SPLAT (rb_empty_keyword_given_p() ? RB_PASS_EMPTY_KEYWORDS : rb_keyword_given_p())
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, VALUE size, int kw_splat)
|
enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, VALUE size, int kw_splat)
|
||||||
|
@ -386,13 +386,7 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *ar
|
||||||
|
|
||||||
ptr->obj = obj;
|
ptr->obj = obj;
|
||||||
ptr->meth = rb_to_id(meth);
|
ptr->meth = rb_to_id(meth);
|
||||||
if (kw_splat == 2) {
|
if (argc) ptr->args = rb_ary_new4(argc, argv);
|
||||||
if (argc) ptr->args = rb_ary_new4(argc+1, rb_add_empty_keyword(argc, argv));
|
|
||||||
else ptr->args = rb_ary_new_from_args(1, rb_hash_new());
|
|
||||||
kw_splat = 1;
|
|
||||||
} else {
|
|
||||||
if (argc) ptr->args = rb_ary_new4(argc, argv);
|
|
||||||
}
|
|
||||||
ptr->fib = 0;
|
ptr->fib = 0;
|
||||||
ptr->dst = Qnil;
|
ptr->dst = Qnil;
|
||||||
ptr->lookahead = Qundef;
|
ptr->lookahead = Qundef;
|
||||||
|
|
15
eval.c
15
eval.c
|
@ -914,14 +914,6 @@ rb_empty_keyword_given_p(void)
|
||||||
{
|
{
|
||||||
return rb_vm_cframe_empty_keyword_p(GET_EC()->cfp);
|
return rb_vm_cframe_empty_keyword_p(GET_EC()->cfp);
|
||||||
}
|
}
|
||||||
VALUE *
|
|
||||||
rb_add_empty_keyword(int argc, const VALUE *argv)
|
|
||||||
{
|
|
||||||
VALUE *ptr = ALLOC_N(VALUE,argc+1);
|
|
||||||
memcpy(ptr, argv, sizeof(VALUE)*(argc));
|
|
||||||
ptr[argc] = rb_hash_new();
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
VALUE rb_eThreadError;
|
VALUE rb_eThreadError;
|
||||||
|
|
||||||
|
@ -1680,12 +1672,7 @@ void
|
||||||
rb_obj_call_init(VALUE obj, int argc, const VALUE *argv)
|
rb_obj_call_init(VALUE obj, int argc, const VALUE *argv)
|
||||||
{
|
{
|
||||||
PASS_PASSED_BLOCK_HANDLER();
|
PASS_PASSED_BLOCK_HANDLER();
|
||||||
if (rb_empty_keyword_given_p()) {
|
rb_funcallv_kw(obj, idInitialize, argc, argv, RB_PASS_CALLED_KEYWORDS);
|
||||||
rb_funcallv_kw(obj, idInitialize, argc+1, rb_add_empty_keyword(argc, argv), 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rb_funcallv_kw(obj, idInitialize, argc, argv, rb_keyword_given_p());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -1967,6 +1967,10 @@ VALUE rb_yield_values(int n, ...);
|
||||||
VALUE rb_yield_values2(int n, const VALUE *argv);
|
VALUE rb_yield_values2(int n, const VALUE *argv);
|
||||||
VALUE rb_yield_splat(VALUE);
|
VALUE rb_yield_splat(VALUE);
|
||||||
VALUE rb_yield_block(VALUE, VALUE, int, const VALUE *, VALUE); /* rb_block_call_func */
|
VALUE rb_yield_block(VALUE, VALUE, int, const VALUE *, VALUE); /* rb_block_call_func */
|
||||||
|
#define RB_NO_KEYWORDS 0
|
||||||
|
#define RB_PASS_KEYWORDS 1
|
||||||
|
#define RB_PASS_EMPTY_KEYWORDS 2
|
||||||
|
#define RB_PASS_CALLED_KEYWORDS 3
|
||||||
int rb_keyword_given_p(void);
|
int rb_keyword_given_p(void);
|
||||||
int rb_block_given_p(void);
|
int rb_block_given_p(void);
|
||||||
void rb_need_block(void);
|
void rb_need_block(void);
|
||||||
|
|
|
@ -1554,7 +1554,6 @@ NORETURN(VALUE rb_f_raise(int argc, VALUE *argv));
|
||||||
|
|
||||||
/* -- Remove In 3.0 -- */
|
/* -- Remove In 3.0 -- */
|
||||||
int rb_empty_keyword_given_p(void);
|
int rb_empty_keyword_given_p(void);
|
||||||
VALUE * rb_add_empty_keyword(int argc, const VALUE *argv);
|
|
||||||
|
|
||||||
/* eval_error.c */
|
/* eval_error.c */
|
||||||
VALUE rb_get_backtrace(VALUE info);
|
VALUE rb_get_backtrace(VALUE info);
|
||||||
|
|
10
proc.c
10
proc.c
|
@ -2223,14 +2223,8 @@ call_method_data(rb_execution_context_t *ec, const struct METHOD *data,
|
||||||
int argc, const VALUE *argv, VALUE passed_procval)
|
int argc, const VALUE *argv, VALUE passed_procval)
|
||||||
{
|
{
|
||||||
vm_passed_block_handler_set(ec, proc_to_block_handler(passed_procval));
|
vm_passed_block_handler_set(ec, proc_to_block_handler(passed_procval));
|
||||||
if (rb_empty_keyword_given_p()) {
|
return rb_vm_call_kw(ec, data->recv, data->me->called_id, argc, argv,
|
||||||
return rb_vm_call_kw(ec, data->recv, data->me->called_id, argc+1, rb_add_empty_keyword(argc, argv),
|
method_callable_method_entry(data), RB_PASS_CALLED_KEYWORDS);
|
||||||
method_callable_method_entry(data), 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return rb_vm_call_kw(ec, data->recv, data->me->called_id, argc, argv,
|
|
||||||
method_callable_method_entry(data), rb_keyword_given_p());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
|
26
vm_eval.c
26
vm_eval.c
|
@ -235,6 +235,26 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, const
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_empty_keyword(int *argc, const VALUE **argv, int *kw_splat)
|
||||||
|
{
|
||||||
|
if (*kw_splat == RB_PASS_CALLED_KEYWORDS || *kw_splat == RB_PASS_EMPTY_KEYWORDS) {
|
||||||
|
if (*kw_splat == RB_PASS_EMPTY_KEYWORDS || rb_empty_keyword_given_p()) {
|
||||||
|
int n = *argc;
|
||||||
|
VALUE *ptr = ALLOC_N(VALUE,n+1);
|
||||||
|
|
||||||
|
memcpy(ptr, *argv, sizeof(VALUE)*n);
|
||||||
|
ptr[n] = rb_hash_new();
|
||||||
|
*argc = ++n;
|
||||||
|
*argv = ptr;
|
||||||
|
*kw_splat = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*kw_splat = rb_keyword_given_p();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_vm_call(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me)
|
rb_vm_call(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me)
|
||||||
{
|
{
|
||||||
|
@ -244,6 +264,7 @@ rb_vm_call(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VAL
|
||||||
VALUE
|
VALUE
|
||||||
rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat)
|
rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat)
|
||||||
{
|
{
|
||||||
|
add_empty_keyword(&argc, &argv, &kw_splat);
|
||||||
return rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat);
|
return rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +290,7 @@ vm_call_super(rb_execution_context_t *ec, int argc, const VALUE *argv)
|
||||||
return method_missing(recv, id, argc, argv, MISSING_SUPER);
|
return method_missing(recv, id, argc, argv, MISSING_SUPER);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return rb_vm_call0(ec, recv, id, argc, argv, me, VM_NO_KEYWORDS);
|
return rb_vm_call0(ec, recv, id, argc, argv, me, RB_PASS_CALLED_KEYWORDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -909,6 +930,7 @@ rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
|
||||||
VALUE
|
VALUE
|
||||||
rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
|
rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
|
||||||
{
|
{
|
||||||
|
add_empty_keyword(&argc, &argv, &kw_splat);
|
||||||
return rb_call(recv, mid, argc, argv, kw_splat ? CALL_FCALL_KW : CALL_FCALL);
|
return rb_call(recv, mid, argc, argv, kw_splat ? CALL_FCALL_KW : CALL_FCALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -976,6 +998,7 @@ rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE
|
||||||
vm_passed_block_handler_set(GET_EC(), passed_procval);
|
vm_passed_block_handler_set(GET_EC(), passed_procval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add_empty_keyword(&argc, &argv, &kw_splat);
|
||||||
return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
|
return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1340,6 +1363,7 @@ rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE * argv,
|
||||||
{
|
{
|
||||||
struct iter_method_arg arg;
|
struct iter_method_arg arg;
|
||||||
|
|
||||||
|
add_empty_keyword(&argc, &argv, &kw_splat);
|
||||||
arg.obj = obj;
|
arg.obj = obj;
|
||||||
arg.mid = mid;
|
arg.mid = mid;
|
||||||
arg.argc = argc;
|
arg.argc = argc;
|
||||||
|
|
Loading…
Add table
Reference in a new issue