Make rb_scan_args implementations same

between rb_scan_args_set and rb_scan_args_assign +
rb_scan_args_result.
This commit is contained in:
Nobuyoshi Nakada 2020-04-12 23:29:22 +09:00
parent a07cbacd23
commit 4c8e3f1241
No known key found for this signature in database
GPG Key ID: 7CD2805BFA3770C6
2 changed files with 51 additions and 35 deletions

64
class.c
View File

@ -2000,14 +2000,12 @@ rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, V
struct rb_scan_args_t { struct rb_scan_args_t {
int kw_flag; int kw_flag;
int f_var;
int f_hash;
int f_block;
int n_lead; int n_lead;
int n_opt; int n_opt;
int n_trail; int n_trail;
int n_mand; bool f_var;
int argi; bool f_hash;
bool f_block;
}; };
static void static void
@ -2045,7 +2043,6 @@ rb_scan_args_parse(int kw_flag, const char *fmt, struct rb_scan_args_t *arg)
if (*p != '\0') { if (*p != '\0') {
rb_fatal("bad scan arg format: %s", fmt); rb_fatal("bad scan arg format: %s", fmt);
} }
arg->n_mand = arg->n_lead + arg->n_trail;
} }
static int static int
@ -2053,29 +2050,38 @@ rb_scan_args_assign(const struct rb_scan_args_t *arg, int argc, const VALUE *con
{ {
int i, argi = 0; int i, argi = 0;
VALUE *var, hash = Qnil; VALUE *var, hash = Qnil;
#define rb_scan_args_next_param() va_arg(vargs, VALUE *)
const int kw_flag = arg->kw_flag;
const int n_lead = arg->n_lead;
const int n_opt = arg->n_opt;
const int n_trail = arg->n_trail;
const int n_mand = n_lead + n_trail;
const bool f_var = arg->f_var;
const bool f_hash = arg->f_hash;
const bool f_block = arg->f_block;
if (arg->f_hash && argc > 0) { if (f_hash && argc > 0) {
VALUE last = argv[argc - 1]; VALUE last = argv[argc - 1];
if (rb_scan_args_keyword_p(arg->kw_flag, last)) { if (rb_scan_args_keyword_p(kw_flag, last)) {
hash = rb_hash_dup(last); hash = rb_hash_dup(last);
argc--; argc--;
} }
} }
if (argc < arg->n_mand) { if (argc < n_mand) {
goto argc_error; goto argc_error;
} }
/* capture leading mandatory arguments */ /* capture leading mandatory arguments */
for (i = arg->n_lead; i-- > 0; ) { for (i = n_lead; i-- > 0; ) {
var = va_arg(vargs, VALUE *); var = rb_scan_args_next_param();
if (var) *var = argv[argi]; if (var) *var = argv[argi];
argi++; argi++;
} }
/* capture optional arguments */ /* capture optional arguments */
for (i = arg->n_opt; i-- > 0; ) { for (i = n_opt; i-- > 0; ) {
var = va_arg(vargs, VALUE *); var = rb_scan_args_next_param();
if (argi < argc - arg->n_trail) { if (argi < argc - n_trail) {
if (var) *var = argv[argi]; if (var) *var = argv[argi];
argi++; argi++;
} }
@ -2084,12 +2090,12 @@ rb_scan_args_assign(const struct rb_scan_args_t *arg, int argc, const VALUE *con
} }
} }
/* capture variable length arguments */ /* capture variable length arguments */
if (arg->f_var) { if (f_var) {
int n_var = argc - argi - arg->n_trail; int n_var = argc - argi - n_trail;
var = va_arg(vargs, VALUE *); var = rb_scan_args_next_param();
if (0 < n_var) { if (0 < n_var) {
if (var) *var = rb_ary_new4(n_var, &argv[argi]); if (var) *var = rb_ary_new_from_values(n_var, &argv[argi]);
argi += n_var; argi += n_var;
} }
else { else {
@ -2097,19 +2103,19 @@ rb_scan_args_assign(const struct rb_scan_args_t *arg, int argc, const VALUE *con
} }
} }
/* capture trailing mandatory arguments */ /* capture trailing mandatory arguments */
for (i = arg->n_trail; i-- > 0; ) { for (i = n_trail; i-- > 0; ) {
var = va_arg(vargs, VALUE *); var = rb_scan_args_next_param();
if (var) *var = argv[argi]; if (var) *var = argv[argi];
argi++; argi++;
} }
/* capture an option hash - phase 2: assignment */ /* capture an option hash - phase 2: assignment */
if (arg->f_hash) { if (f_hash) {
var = va_arg(vargs, VALUE *); var = rb_scan_args_next_param();
if (var) *var = hash; if (var) *var = hash;
} }
/* capture iterator block */ /* capture iterator block */
if (arg->f_block) { if (f_block) {
var = va_arg(vargs, VALUE *); var = rb_scan_args_next_param();
if (rb_block_given_p()) { if (rb_block_given_p()) {
*var = rb_block_proc(); *var = rb_block_proc();
} }
@ -2124,14 +2130,22 @@ rb_scan_args_assign(const struct rb_scan_args_t *arg, int argc, const VALUE *con
} }
return argc; return argc;
#undef rb_scan_args_next_param
} }
static int static int
rb_scan_args_result(const struct rb_scan_args_t *const arg, int argc) rb_scan_args_result(const struct rb_scan_args_t *const arg, int argc)
{ {
if (argc < 0) { if (argc < 0) {
rb_error_arity(-1-argc, arg->n_mand, arg->f_var ? UNLIMITED_ARGUMENTS : arg->n_mand + arg->n_opt); const int n_lead = arg->n_lead;
const int n_opt = arg->n_opt;
const int n_trail = arg->n_trail;
const int n_mand = n_lead + n_trail;
const bool f_var = arg->f_var;
argc = -argc - 1;
rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt);
} }
return argc; return argc;
} }

View File

@ -266,6 +266,7 @@ rb_scan_args_set(int kw_flag, int argc, const VALUE *argv,
{ {
int i, argi = 0, vari = 0; int i, argi = 0, vari = 0;
VALUE *var, hash = Qnil; VALUE *var, hash = Qnil;
#define rb_scan_args_next_param() vars[vari++]
const int n_mand = n_lead + n_trail; const int n_mand = n_lead + n_trail;
if (f_hash && argc > 0) { if (f_hash && argc > 0) {
@ -282,13 +283,13 @@ rb_scan_args_set(int kw_flag, int argc, const VALUE *argv,
/* capture leading mandatory arguments */ /* capture leading mandatory arguments */
for (i = n_lead; i-- > 0; ) { for (i = n_lead; i-- > 0; ) {
var = vars[vari++]; var = rb_scan_args_next_param();
if (var) *var = argv[argi]; if (var) *var = argv[argi];
argi++; argi++;
} }
/* capture optional arguments */ /* capture optional arguments */
for (i = n_opt; i-- > 0; ) { for (i = n_opt; i-- > 0; ) {
var = vars[vari++]; var = rb_scan_args_next_param();
if (argi < argc - n_trail) { if (argi < argc - n_trail) {
if (var) *var = argv[argi]; if (var) *var = argv[argi];
argi++; argi++;
@ -301,7 +302,7 @@ rb_scan_args_set(int kw_flag, int argc, const VALUE *argv,
if (f_var) { if (f_var) {
int n_var = argc - argi - n_trail; int n_var = argc - argi - n_trail;
var = vars[vari++]; var = rb_scan_args_next_param();
if (0 < n_var) { if (0 < n_var) {
if (var) *var = rb_ary_new_from_values(n_var, &argv[argi]); if (var) *var = rb_ary_new_from_values(n_var, &argv[argi]);
argi += n_var; argi += n_var;
@ -312,18 +313,18 @@ rb_scan_args_set(int kw_flag, int argc, const VALUE *argv,
} }
/* capture trailing mandatory arguments */ /* capture trailing mandatory arguments */
for (i = n_trail; i-- > 0; ) { for (i = n_trail; i-- > 0; ) {
var = vars[vari++]; var = rb_scan_args_next_param();
if (var) *var = argv[argi]; if (var) *var = argv[argi];
argi++; argi++;
} }
/* capture an option hash - phase 2: assignment */ /* capture an option hash - phase 2: assignment */
if (f_hash) { if (f_hash) {
var = vars[vari++]; var = rb_scan_args_next_param();
if (var) *var = hash; if (var) *var = hash;
} }
/* capture iterator block */ /* capture iterator block */
if (f_block) { if (f_block) {
var = vars[vari++]; var = rb_scan_args_next_param();
if (rb_block_given_p()) { if (rb_block_given_p()) {
*var = rb_block_proc(); *var = rb_block_proc();
} }
@ -332,14 +333,15 @@ rb_scan_args_set(int kw_flag, int argc, const VALUE *argv,
} }
} }
if (argi >= argc) { if (argi < argc) {
return argc;
}
argc_error: argc_error:
rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt); rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt);
} }
return argc;
#undef rb_scan_args_next_param
}
#if ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) #if ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P)
# /* skip */ # /* skip */