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

ruby-changes:59911

From: Nobuyoshi <ko1@a...>
Date: Mon, 3 Feb 2020 12:54:59 +0900 (JST)
Subject: [ruby-changes:59911] 48c851f868 (master): Moved runtime assignemnts

https://git.ruby-lang.org/ruby.git/commit/?id=48c851f868

From 48c851f86846b273fba0692d5eae1eadf8bf9445 Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Mon, 3 Feb 2020 10:49:17 +0900
Subject: Moved runtime assignemnts

Separate assignemnts of dynamically given runtime values in
`rb_scan_args_assign` from parsing statically given format in
`rb_scan_args_parse`.

diff --git a/class.c b/class.c
index 7cb31b6..a29d1df 100644
--- a/class.c
+++ b/class.c
@@ -1952,8 +1952,7 @@ rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, V https://github.com/ruby/ruby/blob/trunk/class.c#L1952
 }
 
 struct rb_scan_args_t {
-    int argc;
-    const VALUE *argv;
+    int kw_flag;
     int f_var;
     int f_hash;
     int f_block;
@@ -1962,30 +1961,15 @@ struct rb_scan_args_t { https://github.com/ruby/ruby/blob/trunk/class.c#L1961
     int n_trail;
     int n_mand;
     int argi;
-    VALUE hash;
 };
 
 static void
-rb_scan_args_parse(int kw_flag, int argc, const VALUE *argv, const char *fmt, struct rb_scan_args_t *arg)
+rb_scan_args_parse(int kw_flag, const char *fmt, struct rb_scan_args_t *arg)
 {
     const char *p = fmt;
-    int keyword_given = 0;
-    int last_hash_keyword = 0;
 
     memset(arg, 0, sizeof(*arg));
-    arg->hash = Qnil;
-
-    switch (kw_flag) {
-      case RB_SCAN_ARGS_PASS_CALLED_KEYWORDS:
-        keyword_given = rb_keyword_given_p();
-        break;
-      case RB_SCAN_ARGS_KEYWORDS:
-        keyword_given = 1;
-        break;
-      case RB_SCAN_ARGS_LAST_HASH_KEYWORDS:
-        last_hash_keyword = 1;
-        break;
-    }
+    arg->kw_flag = kw_flag;
 
     if (ISDIGIT(*p)) {
         arg->n_lead = *p - '0';
@@ -2015,42 +1999,49 @@ rb_scan_args_parse(int kw_flag, int argc, const VALUE *argv, const char *fmt, st https://github.com/ruby/ruby/blob/trunk/class.c#L1999
 	rb_fatal("bad scan arg format: %s", fmt);
     }
     arg->n_mand = arg->n_lead + arg->n_trail;
+}
+
+static int
+rb_scan_args_assign(const struct rb_scan_args_t *arg, int argc, const VALUE *const argv, va_list vargs)
+{
+    int i, argi = 0;
+    VALUE *var, hash = Qnil;
 
     if (arg->f_hash && argc > 0) {
         VALUE last = argv[argc - 1];
-
-        if (keyword_given || (last_hash_keyword && RB_TYPE_P(last, T_HASH))) {
-            arg->hash = rb_hash_dup(last);
+        int keyword_given = 0;
+        switch (arg->kw_flag) {
+          case RB_SCAN_ARGS_PASS_CALLED_KEYWORDS:
+            keyword_given = rb_keyword_given_p();
+            break;
+          case RB_SCAN_ARGS_KEYWORDS:
+            keyword_given = 1;
+            break;
+          case RB_SCAN_ARGS_LAST_HASH_KEYWORDS:
+            keyword_given = RB_TYPE_P(last, T_HASH);
+            break;
+        }
+        if (keyword_given) {
+            hash = rb_hash_dup(last);
             argc--;
         }
     }
 
-    arg->argc = argc;
-    arg->argv = argv;
-}
-
-static int
-rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs)
-{
-    int argi = 0;
-    int i;
-    VALUE *var;
-
-    if (arg->argc < arg->n_mand) {
-        return 1;
+    if (argc < arg->n_mand) {
+        goto argc_error;
     }
 
     /* capture leading mandatory arguments */
     for (i = arg->n_lead; i-- > 0; ) {
 	var = va_arg(vargs, VALUE *);
-        if (var) *var = arg->argv[argi];
+        if (var) *var = argv[argi];
 	argi++;
     }
     /* capture optional arguments */
     for (i = arg->n_opt; i-- > 0; ) {
 	var = va_arg(vargs, VALUE *);
-        if (argi < arg->argc - arg->n_trail) {
-            if (var) *var = arg->argv[argi];
+        if (argi < argc - arg->n_trail) {
+            if (var) *var = argv[argi];
 	    argi++;
 	}
 	else {
@@ -2059,11 +2050,11 @@ rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs) https://github.com/ruby/ruby/blob/trunk/class.c#L2050
     }
     /* capture variable length arguments */
     if (arg->f_var) {
-        int n_var = arg->argc - argi - arg->n_trail;
+        int n_var = argc - argi - arg->n_trail;
 
 	var = va_arg(vargs, VALUE *);
 	if (0 < n_var) {
-	    if (var) *var = rb_ary_new4(n_var, &arg->argv[argi]);
+            if (var) *var = rb_ary_new4(n_var, &argv[argi]);
 	    argi += n_var;
 	}
 	else {
@@ -2073,13 +2064,13 @@ rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs) https://github.com/ruby/ruby/blob/trunk/class.c#L2064
     /* capture trailing mandatory arguments */
     for (i = arg->n_trail; i-- > 0; ) {
 	var = va_arg(vargs, VALUE *);
-        if (var) *var = arg->argv[argi];
+        if (var) *var = argv[argi];
 	argi++;
     }
     /* capture an option hash - phase 2: assignment */
     if (arg->f_hash) {
 	var = va_arg(vargs, VALUE *);
-        if (var) *var = arg->hash;
+        if (var) *var = hash;
     }
     /* capture iterator block */
     if (arg->f_block) {
@@ -2092,42 +2083,43 @@ rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs) https://github.com/ruby/ruby/blob/trunk/class.c#L2083
 	}
     }
 
-    if (argi < arg->argc) return 1;
+    if (argi < argc) {
+      argc_error:
+        return -(argc + 1);
+    }
 
-    return 0;
+    return argc;
 }
 
 #undef rb_scan_args
 int
 rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
 {
-    int error;
     va_list vargs;
     struct rb_scan_args_t arg;
-    rb_scan_args_parse(RB_SCAN_ARGS_PASS_CALLED_KEYWORDS, argc, argv, fmt, &arg);
+    rb_scan_args_parse(RB_SCAN_ARGS_PASS_CALLED_KEYWORDS, fmt, &arg);
     va_start(vargs,fmt);
-    error = rb_scan_args_assign(&arg, vargs);
+    argc = rb_scan_args_assign(&arg, argc, argv, vargs);
     va_end(vargs);
-    if (error) {
-        rb_error_arity(arg.argc, arg.n_mand, arg.f_var ? UNLIMITED_ARGUMENTS : arg.n_mand + arg.n_opt);
+    if (argc < 0) {
+        rb_error_arity(-1-argc, arg.n_mand, arg.f_var ? UNLIMITED_ARGUMENTS : arg.n_mand + arg.n_opt);
     }
-    return arg.argc;
+    return argc;
 }
 
 int
 rb_scan_args_kw(int kw_flag, int argc, const VALUE *argv, const char *fmt, ...)
 {
-    int error;
     va_list vargs;
     struct rb_scan_args_t arg;
-    rb_scan_args_parse(kw_flag, argc, argv, fmt, &arg);
+    rb_scan_args_parse(kw_flag, fmt, &arg);
     va_start(vargs,fmt);
-    error = rb_scan_args_assign(&arg, vargs);
+    argc = rb_scan_args_assign(&arg, argc, argv, vargs);
     va_end(vargs);
-    if (error) {
-        rb_error_arity(arg.argc, arg.n_mand, arg.f_var ? UNLIMITED_ARGUMENTS : arg.n_mand + arg.n_opt);
+    if (argc < 0) {
+        rb_error_arity(-1-argc, arg.n_mand, arg.f_var ? UNLIMITED_ARGUMENTS : arg.n_mand + arg.n_opt);
     }
-    return arg.argc;
+    return argc;
 }
 
 int
-- 
cgit v0.10.2


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

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