12 NORETURN(
static void argument_arity_error(
rb_thread_t *th,
const rb_iseq_t *iseq,
const int miss_argc,
const int min_argc,
const int max_argc));
47 args_extend(
struct args_info *args,
const int min_argc)
59 for (i=args->
argc; i<min_argc; i++) {
66 args_reduce(
struct args_info *args,
int over_argc)
71 if (len > over_argc) {
83 args->
argc -= over_argc;
95 else if (args->
argc == 1) {
146 else if (args->
argc > 0) {
153 static inline const VALUE *
179 if (!
NIL_P(*rest_hash_ptr)) {
181 if (!hash) hash =
Qnil;
199 *kw_hash_ptr = args->
argv[args->
argc-1];
201 if (keyword_hash_p(kw_hash_ptr, &rest_hash, th)) {
203 args->
argv[args->
argc-1] = rest_hash;
217 if (keyword_hash_p(kw_hash_ptr, &rest_hash, th)) {
237 args_kw_argv_to_hash(
struct args_info *args)
243 const int kw_start = args->
argc - kw_len;
247 args->
argc = kw_start + 1;
248 for (i=0; i<kw_len; i++) {
258 args_stored_kw_argv_to_hash(
struct args_info *args)
263 const int passed_keyword_len = kw_arg->
keyword_len;
266 for (i=0; i<passed_keyword_len; i++) {
283 if (args->
argc >= argc) {
290 const VALUE *
argv = args_rest_argv(args);
292 for (i=args->
argc, j=0; i<argc; i++, j++) {
301 args_setup_post_parameters(
struct args_info *args,
int argc,
VALUE *locals)
311 args_setup_opt_parameters(
struct args_info *args,
int opt_max,
VALUE *locals)
315 if (args->
argc >= opt_max) {
316 args->
argc -= opt_max;
317 args->
argv += opt_max;
335 for (j=i; j<opt_max; j++) {
347 *locals = args_rest_array(args);
351 make_unknown_kw_hash(
const VALUE *passed_keywords,
int passed_keyword_len,
const VALUE *
kw_argv)
356 for (i=0; i<passed_keyword_len; i++) {
357 if (kw_argv[i] !=
Qundef) {
365 make_rest_kw_hash(
const VALUE *passed_keywords,
int passed_keyword_len,
const VALUE *kw_argv)
370 for (i=0; i<passed_keyword_len; i++) {
371 if (kw_argv[i] !=
Qundef) {
379 args_setup_kw_parameters_lookup(
const ID key,
VALUE *ptr,
const VALUE *
const passed_keywords,
VALUE *passed_values,
const int passed_keyword_len)
384 for (i=0; i<passed_keyword_len; i++) {
385 if (keyname == passed_keywords[i]) {
386 *ptr = passed_values[i];
387 passed_values[i] =
Qundef;
396 args_setup_kw_parameters(
VALUE*
const passed_values,
const int passed_keyword_len,
const VALUE *
const passed_keywords,
404 int i, di, found = 0;
405 int unspecified_bits = 0;
408 for (i=0; i<req_key_num; i++) {
409 ID key = acceptable_keywords[i];
410 if (args_setup_kw_parameters_lookup(key, &locals[i], passed_keywords, passed_values, passed_keyword_len)) {
419 if (missing) argument_kw_error(
GET_THREAD(), iseq,
"missing", missing);
421 for (di=0; i<key_num; i++, di++) {
422 if (args_setup_kw_parameters_lookup(acceptable_keywords[i], &locals[i], passed_keywords, passed_values, passed_keyword_len)) {
426 if (default_values[di] ==
Qundef) {
430 unspecified_bits |= 0x01 << di;
433 if (
NIL_P(unspecified_bits_value)) {
438 for (j=0; j<32; j++) {
439 if (unspecified_bits & (0x01 << j)) {
448 locals[i] = default_values[di];
454 const int rest_hash_index = key_num + 1;
455 locals[rest_hash_index] = make_rest_kw_hash(passed_keywords, passed_keyword_len, passed_values);
458 if (found != passed_keyword_len) {
459 VALUE keys = make_unknown_kw_hash(passed_keywords, passed_keyword_len, passed_values);
460 argument_kw_error(
GET_THREAD(), iseq,
"unknown", keys);
464 if (
NIL_P(unspecified_bits_value)) {
465 unspecified_bits_value =
INT2FIX(unspecified_bits);
467 locals[key_num] = unspecified_bits_value;
471 args_setup_kw_rest_parameter(
VALUE keyword_hash,
VALUE *locals)
484 switch (vm_block_handler_type(block_handler)) {
493 blockval = VM_BH_TO_PROC(block_handler);
545 for (i=calling->
argc; i<iseq->body->param.size; i++) {
552 given_argc = args->
argc = calling->
argc;
562 args->
argc -= kw_len;
563 given_argc -= kw_len;
568 given_argc = args_kw_argv_to_hash(args);
585 switch (arg_setup_type) {
589 if (given_argc == 1 &&
593 args_check_block_arg0(args, th)) {
600 if (given_argc < min_argc) {
601 if (given_argc == min_argc - 1 && args->
kw_argv) {
602 args_stored_kw_argv_to_hash(args);
603 given_argc = args_argc(args);
608 given_argc = min_argc;
609 args_extend(args, min_argc);
612 argument_arity_error(th, iseq, given_argc, min_argc, max_argc);
617 if (given_argc > min_argc &&
622 if (args_pop_keyword_hash(args, &keyword_hash, th)) {
630 args_reduce(args, given_argc - max_argc);
631 given_argc = max_argc;
634 argument_arity_error(th, iseq, given_argc, min_argc, max_argc);
662 else if (!
NIL_P(keyword_hash)) {
671 args_setup_kw_parameters(arg.vals, kw_len, arg.keys, iseq, klocals);
675 args_setup_kw_parameters(
NULL, 0,
NULL, iseq, klocals);
679 args_setup_kw_rest_parameter(keyword_hash, locals + iseq->
body->
param.
keyword->rest_start);
682 argument_kw_error(th, iseq,
"unknown",
rb_hash_keys(keyword_hash));
693 fprintf(stderr,
"local[%d] = %p\n", i, (
void *)locals[i]);
725 argument_arity_error(
rb_thread_t *th,
const rb_iseq_t *iseq,
const int miss_argc,
const int min_argc,
const int max_argc)
727 VALUE exc = rb_arity_error_new(miss_argc, min_argc, max_argc);
730 const ID *keywords = kw->table;
731 int req_key_num = kw->required_num;
732 if (req_key_num > 0) {
733 static const char required[] =
"; required keywords";
736 rb_str_cat(mesg, required,
sizeof(required) - 1 - (req_key_num == 1));
742 }
while (--req_key_num);
746 raise_argument_error(th, iseq, exc);
758 int argc = calling->
argc;
760 VALUE ary = argv[argc-1];
770 for (i = 0; i <
len; i++) {
773 calling->
argc += i - 1;
787 for (i=0; i<kw_len; i++) {
792 cfp->
sp -= kw_len - 1;
793 calling->
argc -= kw_len - 1;
797 vm_to_proc(
VALUE proc)
805 "wrong argument type %s (expected Proc)",
827 mid =
SYM2ID(callback_arg);
830 if (!
NIL_P(blockarg)) {
831 vm_passed_block_handler_set(th, blockarg);
836 return vm_call0(th, obj, mid, argc,
argv, me);
844 VALUE block_code = *(--reg_cfp->
sp);
846 if (
NIL_P(block_code)) {
869 else if (blockiseq !=
NULL) {
884 #define IS_ARGS_SPLAT(ci) ((ci)->flag & VM_CALL_ARGS_SPLAT) 885 #define IS_ARGS_KEYWORD(ci) ((ci)->flag & VM_CALL_KWARG) 887 #define CALLER_SETUP_ARG(cfp, calling, ci) do { \ 888 if (UNLIKELY(IS_ARGS_SPLAT(ci))) vm_caller_setup_arg_splat((cfp), (calling)); \ 889 if (UNLIKELY(IS_ARGS_KEYWORD(ci))) vm_caller_setup_arg_kw((cfp), (calling), (ci)); \ #define VM_CALL_ARGS_BLOCKARG
VALUE rb_ary_unshift(VALUE ary, VALUE item)
VALUE rb_ary_pop(VALUE ary)
VALUE rb_hash_dup(VALUE hash)
VALUE rb_threadptr_backtrace_object(rb_thread_t *th)
VALUE rb_ary_subseq(VALUE ary, long beg, long len)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_str_cat(VALUE, const char *, long)
struct rb_iseq_constant_body::@135::@136 flags
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
VALUE rb_ary_push(VALUE ary, VALUE item)
#define VM_BLOCK_HANDLER_NONE
#define GET_BLOCK_HANDLER()
VALUE rb_ary_tmp_new(long capa)
struct rb_iseq_constant_body * body
struct rb_call_info_kw_arg * kw_arg
#define VM_CALL_ARGS_SPLAT
VALUE rb_hash_lookup(VALUE hash, VALUE key)
RUBY_EXTERN VALUE rb_cProc
VALUE rb_hash_new_with_size(st_index_t size)
const char * rb_obj_classname(VALUE)
VALUE rb_hash_keys(VALUE hash)
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
VALUE rb_vm_make_proc(rb_thread_t *th, const struct rb_captured_block *captured, VALUE klass)
const VALUE * iseq_encoded
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
void rb_hash_foreach(VALUE hash, int(*func)(ANYARGS), VALUE farg)
VALUE rb_extract_keywords(VALUE *orighash)
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
const rb_callable_method_entry_t * rb_callable_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class)
#define ALLOCA_N(type, n)
union rb_captured_block::@141 code
#define MEMCPY(p1, p2, type, n)
VALUE rb_str_resize(VALUE, long)
void rb_vm_pop_frame(rb_thread_t *th)
#define RARRAY_CONST_PTR(a)
NORETURN(static void raise_argument_error(rb_thread_t *th, const rb_iseq_t *iseq, const VALUE exc))
struct rb_iseq_constant_body::@135 param
parameter information
VALUE rb_obj_is_proc(VALUE)
VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt)
VALUE rb_ivar_set(VALUE, ID, VALUE)
VALUE rb_check_hash_type(VALUE hash)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
VALUE rb_sym_to_proc(VALUE sym)
#define RARRAY_LENINT(ary)
const struct rb_iseq_constant_body::@135::rb_iseq_param_keyword * keyword
register unsigned int len
VALUE rb_ary_new_from_values(long n, const VALUE *elts)
VALUE rb_ary_resize(VALUE ary, long len)
expands or shrinks ary to len elements.
#define RARRAY_ASET(a, i, v)
#define UNLIMITED_ARGUMENTS
#define RARRAY_AREF(a, i)
VALUE rb_check_array_type(VALUE ary)
int rb_method_basic_definition_p(VALUE, ID)
VALUE rb_str_cat_cstr(VALUE, const char *)
VALUE rb_ary_dup(VALUE ary)
VALUE rb_func_proc_new(rb_block_call_func_t func, VALUE val)
rb_execution_context_t ec
#define CHECK_VM_STACK_OVERFLOW(cfp, margin)
RUBY_EXTERN VALUE rb_cSymbol
VALUE rb_str_append(VALUE, VALUE)
const struct rb_call_info_kw_arg * kw_arg
VALUE rb_attr_get(VALUE, ID)
VALUE rb_keyword_error_new(const char *error, VALUE keys)