Project

General

Profile

Feature #16891 ยป keyword-hash-integration.diff

jeremyevans0 (Jeremy Evans), 05/14/2020 08:11 PM

View differences:

vm_args.c
return ary;
}
static int
keyword_hash_has_symbol_p_iter(st_data_t key, st_data_t val, st_data_t arg)
{
if (SYMBOL_P((VALUE)key)) {
*(int*)arg |= 1;
return ST_STOP;
}
return ST_CONTINUE;
}
static int
keyword_hash_has_symbol_p(VALUE kw_hash) {
int has_symbol = 0;
rb_hash_stlike_foreach(kw_hash, keyword_hash_has_symbol_p_iter, (st_data_t)(&has_symbol));
return has_symbol;
}
static int
keyword_hash_p(VALUE *kw_hash_ptr, int check_symbol)
{
*kw_hash_ptr = rb_check_hash_type(*kw_hash_ptr);
if (NIL_P(*kw_hash_ptr)) {
return FALSE;
}
if (!check_symbol || RHASH_EMPTY_P(*kw_hash_ptr) ||
keyword_hash_has_symbol_p(*kw_hash_ptr)) {
return TRUE;
}
*kw_hash_ptr = Qnil;
return FALSE;
}
static VALUE
args_pop_keyword_hash(struct args_info *args, VALUE *kw_hash_ptr, int check_symbol)
{
if (args->rest == Qfalse) {
from_argv:
VM_ASSERT(args->argc > 0);
*kw_hash_ptr = args->argv[args->argc-1];
if (keyword_hash_p(kw_hash_ptr, check_symbol)) {
args->argc--;
return TRUE;
}
}
else {
long len = RARRAY_LEN(args->rest);
if (len > 0) {
*kw_hash_ptr = RARRAY_AREF(args->rest, len - 1);
if (keyword_hash_p(kw_hash_ptr, check_symbol)) {
arg_rest_dup(args);
rb_ary_pop(args->rest);
return TRUE;
}
}
else {
goto from_argv;
}
}
return FALSE;
}
static int
args_kw_argv_to_hash(struct args_info *args)
{
......
RHASH_EMPTY_P(keyword_hash);
}
VALUE rb_iseq_location(const rb_iseq_t *iseq);
static st_table *caller_to_callees = 0;
static VALUE
rb_warn_check(const rb_execution_context_t * const ec, const rb_iseq_t *const iseq)
{
if (!rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) return 1;
if (!iseq) return 0;
const st_data_t callee = (st_data_t)(iseq->body->iseq_unique_id * 2);
const rb_control_frame_t * const cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
if (!cfp) return 0;
const st_data_t caller = (st_data_t)cfp->pc;
if (!caller_to_callees) {
caller_to_callees = st_init_numtable();
}
st_data_t val;
if (st_lookup(caller_to_callees, caller, &val)) {
st_table *callees;
if (val & 1) {
val &= ~(st_data_t)1;
if (val == callee) return 1; /* already warned */
callees = st_init_numtable();
st_insert(callees, val, 1);
}
else {
callees = (st_table *) val;
if (st_is_member(callees, callee)) return 1; /* already warned */
}
st_insert(callees, callee, 1);
st_insert(caller_to_callees, caller, (st_data_t) callees);
}
else {
st_insert(caller_to_callees, caller, callee | 1);
}
return 0; /* not warned yet for the pair of caller and callee */
}
static inline void
rb_warn_last_hash_to_keyword(rb_execution_context_t * const ec,
struct rb_calling_info * const calling,
const struct rb_callinfo *ci,
const rb_iseq_t * const iseq)
{
if (rb_warn_check(ec, iseq)) return;
VALUE name, loc;
name = rb_id2str(vm_ci_mid(ci));
loc = rb_iseq_location(iseq);
if (NIL_P(loc)) {
rb_warning("Using the last argument for `%"PRIsVALUE"' as keyword parameters is deprecated; maybe ** should be added to the call",
name);
}
else {
rb_warning("Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call");
if (calling->recv != Qundef) {
rb_compile_warning(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)),
"The called method `%"PRIsVALUE"' is defined here", name);
}
else {
rb_compile_warning(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)),
"The called method is defined here");
}
}
}
static int
setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * const iseq,
struct rb_calling_info *const calling,
......
}
}
if (!kw_flag && args->kw_argv == NULL &&
(iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) &&
given_argc > min_argc &&
args_pop_keyword_hash(args, &keyword_hash, !iseq->body->param.flags.has_kwrest)) {
rb_warn_last_hash_to_keyword(ec, calling, ci, iseq);
given_argc--;
}
if (given_argc > max_argc && max_argc != UNLIMITED_ARGUMENTS) {
if (arg_setup_type == arg_setup_block) {
/* truncate */
    (1-1/1)