[前][次][番号順一覧][スレッド一覧]

ruby-changes:57741

From: Jeremy <ko1@a...>
Date: Sat, 14 Sep 2019 08:54:10 +0900 (JST)
Subject: [ruby-changes:57741] 3cfbfa9628 (master): Consolidate empty keyword handling

https://git.ruby-lang.org/ruby.git/commit/?id=3cfbfa9628

From 3cfbfa9628435e3b09316a18c2db9e4f250fdd77 Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@j...>
Date: Fri, 13 Sep 2019 16:42:27 -0700
Subject: 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.

diff --git a/enumerator.c b/enumerator.c
index 43008bc..2a94aa3 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -370,7 +370,7 @@ enumerator_allocate(VALUE klass) https://github.com/ruby/ruby/blob/trunk/enumerator.c#L370
     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
 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 https://github.com/ruby/ruby/blob/trunk/enumerator.c#L386
 
     ptr->obj  = obj;
     ptr->meth = rb_to_id(meth);
-    if (kw_splat == 2) {
-        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);
-    }
+    if (argc) ptr->args = rb_ary_new4(argc, argv);
     ptr->fib = 0;
     ptr->dst = Qnil;
     ptr->lookahead = Qundef;
diff --git a/eval.c b/eval.c
index fbdde7d..ca4456d 100644
--- a/eval.c
+++ b/eval.c
@@ -914,14 +914,6 @@ rb_empty_keyword_given_p(void) https://github.com/ruby/ruby/blob/trunk/eval.c#L914
 {
     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;
 
@@ -1680,12 +1672,7 @@ void https://github.com/ruby/ruby/blob/trunk/eval.c#L1672
 rb_obj_call_init(VALUE obj, int argc, const VALUE *argv)
 {
     PASS_PASSED_BLOCK_HANDLER();
-    if (rb_empty_keyword_given_p()) {
-        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());
-    }
+    rb_funcallv_kw(obj, idInitialize, argc, argv, RB_PASS_CALLED_KEYWORDS);
 }
 
 /*!
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 0bede6f..1b396f4 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -1967,6 +1967,10 @@ VALUE rb_yield_values(int n, ...); https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L1967
 VALUE rb_yield_values2(int n, const VALUE *argv);
 VALUE rb_yield_splat(VALUE);
 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_block_given_p(void);
 void rb_need_block(void);
diff --git a/internal.h b/internal.h
index cf0c3c9..3dbe9ad 100644
--- a/internal.h
+++ b/internal.h
@@ -1554,7 +1554,6 @@ NORETURN(VALUE rb_f_raise(int argc, VALUE *argv)); https://github.com/ruby/ruby/blob/trunk/internal.h#L1554
 
 /* -- Remove In 3.0 -- */
 int rb_empty_keyword_given_p(void);
-VALUE * rb_add_empty_keyword(int argc, const VALUE *argv);
 
 /* eval_error.c */
 VALUE rb_get_backtrace(VALUE info);
diff --git a/proc.c b/proc.c
index 3c65d3d..92264af 100644
--- a/proc.c
+++ b/proc.c
@@ -2223,14 +2223,8 @@ call_method_data(rb_execution_context_t *ec, const struct METHOD *data, https://github.com/ruby/ruby/blob/trunk/proc.c#L2223
 		 int argc, const VALUE *argv, VALUE 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+1, rb_add_empty_keyword(argc, argv),
-                      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());
-    }
+    return rb_vm_call_kw(ec, data->recv, data->me->called_id, argc, argv,
+                         method_callable_method_entry(data), RB_PASS_CALLED_KEYWORDS);
 }
 
 static VALUE
diff --git a/vm_eval.c b/vm_eval.c
index 434e1dc..7609d19 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -235,6 +235,26 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, const https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L235
     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
 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 https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L264
 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)
 {
+    add_empty_keyword(&argc, &argv, &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) https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L290
 	return method_missing(recv, id, argc, argv, MISSING_SUPER);
     }
     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) https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L930
 VALUE
 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);
 }
 
@@ -976,6 +998,7 @@ rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L998
         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);
 }
 
@@ -1340,6 +1363,7 @@ rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE * argv, https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1363
 {
     struct iter_method_arg arg;
 
+    add_empty_keyword(&argc, &argv, &kw_splat);
     arg.obj = obj;
     arg.mid = mid;
     arg.argc = argc;
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]