1 /**********************************************************************
3 vm_args.c - process method call arguments.
7 Copyright (C) 2014- Yukihiro Matsumoto
9 **********************************************************************/
11 NORETURN(static void raise_argument_error(rb_execution_context_t
*ec
, const rb_iseq_t
*iseq
, const VALUE exc
));
12 NORETURN(static void argument_arity_error(rb_execution_context_t
*ec
, const rb_iseq_t
*iseq
, const int miss_argc
, const int min_argc
, const int max_argc
));
13 NORETURN(static void argument_kw_error(rb_execution_context_t
*ec
, const rb_iseq_t
*iseq
, const char *error
, const VALUE keys
));
14 VALUE
rb_keyword_error_new(const char *error
, VALUE keys
); /* class.c */
15 static VALUE
method_missing(rb_execution_context_t
*ec
, VALUE obj
, ID id
, int argc
, const VALUE
*argv
,
16 enum method_missing_reason call_status
, int kw_splat
);
17 const rb_callable_method_entry_t
*rb_resolve_refined_method_callable(VALUE refinements
, const rb_callable_method_entry_t
*me
);
24 /* additional args info */
27 const struct rb_callinfo_kwarg
*kw_arg
;
38 arg_rest_dup(struct args_info
*args
)
40 if (!args
->rest_dupped
) {
41 args
->rest
= rb_ary_dup(args
->rest
);
42 args
->rest_dupped
= TRUE
;
47 args_argc(struct args_info
*args
)
49 if (args
->rest
== Qfalse
) {
53 return args
->argc
+ RARRAY_LENINT(args
->rest
) - args
->rest_index
;
58 args_extend(struct args_info
*args
, const int min_argc
)
64 VM_ASSERT(args
->rest_index
== 0);
65 for (i
=args
->argc
+ RARRAY_LENINT(args
->rest
); i
<min_argc
; i
++) {
66 rb_ary_push(args
->rest
, Qnil
);
70 for (i
=args
->argc
; i
<min_argc
; i
++) {
71 args
->argv
[args
->argc
++] = Qnil
;
77 args_reduce(struct args_info
*args
, int over_argc
)
80 const long len
= RARRAY_LEN(args
->rest
);
82 if (len
> over_argc
) {
84 rb_ary_resize(args
->rest
, len
- over_argc
);
93 VM_ASSERT(args
->argc
>= over_argc
);
94 args
->argc
-= over_argc
;
98 args_check_block_arg0(struct args_info
*args
)
102 if (args
->rest
&& RARRAY_LEN(args
->rest
) == 1) {
103 VALUE arg0
= RARRAY_AREF(args
->rest
, 0);
104 ary
= rb_check_array_type(arg0
);
106 else if (args
->argc
== 1) {
107 VALUE arg0
= args
->argv
[0];
108 ary
= rb_check_array_type(arg0
);
109 args
->argv
[0] = arg0
; /* see: https://bugs.ruby-lang.org/issues/8484 */
114 args
->rest_index
= 0;
123 args_copy(struct args_info
*args
)
125 if (args
->rest
!= Qfalse
) {
126 int argc
= args
->argc
;
131 * argv: [m0, m1, m2, m3]
132 * rest: [a0, a1, a2, a3, a4, a5]
139 * rest: [m2, m3, a2, a3, a4, a5]
145 * argv: [] (argc == 0)
146 * rest: [m0, m1, m2, m3, a2, a3, a4, a5]
150 while (args
->rest_index
> 0 && argc
> 0) {
151 RARRAY_ASET(args
->rest
, --args
->rest_index
, args
->argv
[--argc
]);
154 rb_ary_unshift(args
->rest
, args
->argv
[--argc
]);
157 else if (args
->argc
> 0) {
158 args
->rest
= rb_ary_new_from_values(args
->argc
, args
->argv
);
159 args
->rest_index
= 0;
160 args
->rest_dupped
= TRUE
;
165 static inline const VALUE
*
166 args_rest_argv(struct args_info
*args
)
168 return RARRAY_CONST_PTR_TRANSIENT(args
->rest
) + args
->rest_index
;
172 args_rest_array(struct args_info
*args
)
177 ary
= rb_ary_behead(args
->rest
, args
->rest_index
);
178 args
->rest_index
= 0;
188 args_kw_argv_to_hash(struct args_info
*args
)
190 const struct rb_callinfo_kwarg
*kw_arg
= args
->kw_arg
;
191 const VALUE
*const passed_keywords
= kw_arg
->keywords
;
192 const int kw_len
= kw_arg
->keyword_len
;
193 VALUE h
= rb_hash_new_with_size(kw_len
);
194 const int kw_start
= args
->argc
- kw_len
;
195 const VALUE
* const kw_argv
= args
->argv
+ kw_start
;
198 args
->argc
= kw_start
+ 1;
199 for (i
=0; i
<kw_len
; i
++) {
200 rb_hash_aset(h
, passed_keywords
[i
], kw_argv
[i
]);
203 args
->argv
[args
->argc
- 1] = h
;
209 args_setup_lead_parameters(struct args_info
*args
, int argc
, VALUE
*locals
)
211 if (args
->argc
>= argc
) {
218 const VALUE
*argv
= args_rest_argv(args
);
220 for (i
=args
->argc
, j
=0; i
<argc
; i
++, j
++) {
223 args
->rest_index
+= argc
- args
->argc
;
229 args_setup_post_parameters(struct args_info
*args
, int argc
, VALUE
*locals
)
232 len
= RARRAY_LEN(args
->rest
);
233 MEMCPY(locals
, RARRAY_CONST_PTR_TRANSIENT(args
->rest
) + len
- argc
, VALUE
, argc
);
234 rb_ary_resize(args
->rest
, len
- argc
);
238 args_setup_opt_parameters(struct args_info
*args
, int opt_max
, VALUE
*locals
)
242 if (args
->argc
>= opt_max
) {
243 args
->argc
-= opt_max
;
244 args
->argv
+= opt_max
;
253 int len
= RARRAY_LENINT(args
->rest
);
254 const VALUE
*argv
= RARRAY_CONST_PTR_TRANSIENT(args
->rest
);
256 for (; i
<opt_max
&& args
->rest_index
< len
; i
++, args
->rest_index
++) {
257 locals
[i
] = argv
[args
->rest_index
];
261 /* initialize by nil */
262 for (j
=i
; j
<opt_max
; j
++) {
271 args_setup_rest_parameter(struct args_info
*args
, VALUE
*locals
)
273 *locals
= args_rest_array(args
);
277 make_unknown_kw_hash(const VALUE
*passed_keywords
, int passed_keyword_len
, const VALUE
*kw_argv
)
280 VALUE obj
= rb_ary_hidden_new(1);
282 for (i
=0; i
<passed_keyword_len
; i
++) {
283 if (!UNDEF_P(kw_argv
[i
])) {
284 rb_ary_push(obj
, passed_keywords
[i
]);
291 make_rest_kw_hash(const VALUE
*passed_keywords
, int passed_keyword_len
, const VALUE
*kw_argv
)
294 VALUE obj
= rb_hash_new_with_size(passed_keyword_len
);
296 for (i
=0; i
<passed_keyword_len
; i
++) {
297 if (!UNDEF_P(kw_argv
[i
])) {
298 rb_hash_aset(obj
, passed_keywords
[i
], kw_argv
[i
]);
305 args_setup_kw_parameters_lookup(const ID key
, VALUE
*ptr
, const VALUE
*const passed_keywords
, VALUE
*passed_values
, const int passed_keyword_len
)
308 const VALUE keyname
= ID2SYM(key
);
310 for (i
=0; i
<passed_keyword_len
; i
++) {
311 if (keyname
== passed_keywords
[i
]) {
312 *ptr
= passed_values
[i
];
313 passed_values
[i
] = Qundef
;
321 #define KW_SPECIFIED_BITS_MAX (32-1) /* TODO: 32 -> Fixnum's max bits */
324 args_setup_kw_parameters(rb_execution_context_t
*const ec
, const rb_iseq_t
*const iseq
,
325 VALUE
*const passed_values
, const int passed_keyword_len
, const VALUE
*const passed_keywords
,
328 const ID
*acceptable_keywords
= ISEQ_BODY(iseq
)->param
.keyword
->table
;
329 const int req_key_num
= ISEQ_BODY(iseq
)->param
.keyword
->required_num
;
330 const int key_num
= ISEQ_BODY(iseq
)->param
.keyword
->num
;
331 const VALUE
* const default_values
= ISEQ_BODY(iseq
)->param
.keyword
->default_values
;
333 int i
, di
, found
= 0;
334 int unspecified_bits
= 0;
335 VALUE unspecified_bits_value
= Qnil
;
337 for (i
=0; i
<req_key_num
; i
++) {
338 ID key
= acceptable_keywords
[i
];
339 if (args_setup_kw_parameters_lookup(key
, &locals
[i
], passed_keywords
, passed_values
, passed_keyword_len
)) {
343 if (!missing
) missing
= rb_ary_hidden_new(1);
344 rb_ary_push(missing
, ID2SYM(key
));
348 if (missing
) argument_kw_error(ec
, iseq
, "missing", missing
);
350 for (di
=0; i
<key_num
; i
++, di
++) {
351 if (args_setup_kw_parameters_lookup(acceptable_keywords
[i
], &locals
[i
], passed_keywords
, passed_values
, passed_keyword_len
)) {
355 if (UNDEF_P(default_values
[di
])) {
358 if (LIKELY(i
< KW_SPECIFIED_BITS_MAX
)) {
359 unspecified_bits
|= 0x01 << di
;
362 if (NIL_P(unspecified_bits_value
)) {
365 unspecified_bits_value
= rb_hash_new();
367 for (j
=0; j
<KW_SPECIFIED_BITS_MAX
; j
++) {
368 if (unspecified_bits
& (0x01 << j
)) {
369 rb_hash_aset(unspecified_bits_value
, INT2FIX(j
), Qtrue
);
373 rb_hash_aset(unspecified_bits_value
, INT2FIX(di
), Qtrue
);
377 locals
[i
] = default_values
[di
];
382 if (ISEQ_BODY(iseq
)->param
.flags
.has_kwrest
) {
383 const int rest_hash_index
= key_num
+ 1;
384 locals
[rest_hash_index
] = make_rest_kw_hash(passed_keywords
, passed_keyword_len
, passed_values
);
387 if (found
!= passed_keyword_len
) {
388 VALUE keys
= make_unknown_kw_hash(passed_keywords
, passed_keyword_len
, passed_values
);
389 argument_kw_error(ec
, iseq
, "unknown", keys
);
393 if (NIL_P(unspecified_bits_value
)) {
394 unspecified_bits_value
= INT2FIX(unspecified_bits
);
396 locals
[key_num
] = unspecified_bits_value
;
400 args_setup_kw_rest_parameter(VALUE keyword_hash
, VALUE
*locals
, int kw_flag
)
402 if (NIL_P(keyword_hash
)) {
403 keyword_hash
= rb_hash_new();
405 else if (!(kw_flag
& VM_CALL_KW_SPLAT_MUT
)) {
406 keyword_hash
= rb_hash_dup(keyword_hash
);
408 locals
[0] = keyword_hash
;
412 args_setup_block_parameter(const rb_execution_context_t
*ec
, struct rb_calling_info
*calling
, VALUE
*locals
)
414 VALUE block_handler
= calling
->block_handler
;
415 *locals
= rb_vm_bh_to_procval(ec
, block_handler
);
418 struct fill_values_arg
{
425 fill_keys_values(st_data_t key
, st_data_t val
, st_data_t ptr
)
427 struct fill_values_arg
*arg
= (struct fill_values_arg
*)ptr
;
429 arg
->keys
[i
] = (VALUE
)key
;
430 arg
->vals
[i
] = (VALUE
)val
;
435 ignore_keyword_hash_p(VALUE keyword_hash
, const rb_iseq_t
* const iseq
, unsigned int * kw_flag
, VALUE
* converted_keyword_hash
)
437 if (!RB_TYPE_P(keyword_hash
, T_HASH
)) {
438 keyword_hash
= rb_to_hash_type(keyword_hash
);
441 if (!(*kw_flag
& VM_CALL_KW_SPLAT_MUT
) &&
442 (ISEQ_BODY(iseq
)->param
.flags
.has_kwrest
||
443 ISEQ_BODY(iseq
)->param
.flags
.ruby2_keywords
)) {
444 *kw_flag
|= VM_CALL_KW_SPLAT_MUT
;
445 keyword_hash
= rb_hash_dup(keyword_hash
);
447 *converted_keyword_hash
= keyword_hash
;
448 return !(ISEQ_BODY(iseq
)->param
.flags
.has_kw
) &&
449 !(ISEQ_BODY(iseq
)->param
.flags
.has_kwrest
) &&
450 RHASH_EMPTY_P(keyword_hash
);
454 setup_parameters_complex(rb_execution_context_t
* const ec
, const rb_iseq_t
* const iseq
,
455 struct rb_calling_info
*const calling
,
456 const struct rb_callinfo
*ci
,
457 VALUE
* const locals
, const enum arg_setup_type arg_setup_type
)
459 const int min_argc
= ISEQ_BODY(iseq
)->param
.lead_num
+ ISEQ_BODY(iseq
)->param
.post_num
;
460 const int max_argc
= (ISEQ_BODY(iseq
)->param
.flags
.has_rest
== FALSE
) ? min_argc
+ ISEQ_BODY(iseq
)->param
.opt_num
: UNLIMITED_ARGUMENTS
;
462 unsigned int kw_flag
= vm_ci_flag(ci
) & (VM_CALL_KWARG
| VM_CALL_KW_SPLAT
| VM_CALL_KW_SPLAT_MUT
);
463 int opt_pc
= 0, allow_autosplat
= !kw_flag
;
464 struct args_info args_body
, *args
;
465 VALUE keyword_hash
= Qnil
;
466 VALUE
* const orig_sp
= ec
->cfp
->sp
;
468 VALUE flag_keyword_hash
= 0;
469 VALUE splat_flagged_keyword_hash
= 0;
470 VALUE converted_keyword_hash
= 0;
473 vm_check_canary(ec
, orig_sp
);
477 * [pushed values] [uninitialized values]
479 * <- ISEQ_BODY(iseq)->param.size------------>
483 * [pushed values] [initialized values ]
485 * <- ISEQ_BODY(iseq)->param.size------------>
488 for (i
=calling
->argc
; i
<ISEQ_BODY(iseq
)->param
.size
; i
++) {
491 ec
->cfp
->sp
= &locals
[i
];
495 given_argc
= args
->argc
= calling
->argc
;
497 args
->rest_dupped
= FALSE
;
499 if (kw_flag
& VM_CALL_KWARG
) {
500 args
->kw_arg
= vm_ci_kwarg(ci
);
502 if (ISEQ_BODY(iseq
)->param
.flags
.has_kw
) {
503 int kw_len
= args
->kw_arg
->keyword_len
;
505 args
->kw_argv
= ALLOCA_N(VALUE
, kw_len
);
506 args
->argc
-= kw_len
;
507 given_argc
-= kw_len
;
508 MEMCPY(args
->kw_argv
, locals
+ args
->argc
, VALUE
, kw_len
);
511 args
->kw_argv
= NULL
;
512 given_argc
= args_kw_argv_to_hash(args
);
513 kw_flag
|= VM_CALL_KW_SPLAT
| VM_CALL_KW_SPLAT_MUT
;
518 args
->kw_argv
= NULL
;
521 if ((vm_ci_flag(ci
) & VM_CALL_ARGS_SPLAT
) && (vm_ci_flag(ci
) & VM_CALL_KW_SPLAT
)) {
523 args
->rest_index
= 0;
524 keyword_hash
= locals
[--args
->argc
];
525 args
->rest
= locals
[--args
->argc
];
527 if (ignore_keyword_hash_p(keyword_hash
, iseq
, &kw_flag
, &converted_keyword_hash
)) {
530 else if (UNLIKELY(ISEQ_BODY(iseq
)->param
.flags
.ruby2_keywords
)) {
531 flag_keyword_hash
= keyword_hash
;
532 rb_ary_push(args
->rest
, keyword_hash
);
535 else if (!ISEQ_BODY(iseq
)->param
.flags
.has_kwrest
&& !ISEQ_BODY(iseq
)->param
.flags
.has_kw
) {
536 rb_ary_push(args
->rest
, keyword_hash
);
540 int len
= RARRAY_LENINT(args
->rest
);
541 given_argc
+= len
- 2;
543 else if (vm_ci_flag(ci
) & VM_CALL_ARGS_SPLAT
) {
545 args
->rest_index
= 0;
546 args
->rest
= locals
[--args
->argc
];
547 int len
= RARRAY_LENINT(args
->rest
);
548 given_argc
+= len
- 1;
549 rest_last
= RARRAY_AREF(args
->rest
, len
- 1);
551 if (!kw_flag
&& len
> 0) {
552 if (RB_TYPE_P(rest_last
, T_HASH
) &&
553 (((struct RHash
*)rest_last
)->basic
.flags
& RHASH_PASS_AS_KEYWORDS
)) {
554 // def f(**kw); a = [..., kw]; g(*a)
555 splat_flagged_keyword_hash
= rest_last
;
556 rest_last
= rb_hash_dup(rest_last
);
557 kw_flag
|= VM_CALL_KW_SPLAT
| VM_CALL_KW_SPLAT_MUT
;
559 if (ignore_keyword_hash_p(rest_last
, iseq
, &kw_flag
, &converted_keyword_hash
)) {
561 rb_ary_pop(args
->rest
);
563 kw_flag
&= ~(VM_CALL_KW_SPLAT
| VM_CALL_KW_SPLAT_MUT
);
566 if (rest_last
!= converted_keyword_hash
) {
567 rest_last
= converted_keyword_hash
;
569 RARRAY_ASET(args
->rest
, len
- 1, rest_last
);
572 if (ISEQ_BODY(iseq
)->param
.flags
.ruby2_keywords
&& rest_last
) {
573 flag_keyword_hash
= rest_last
;
575 else if (ISEQ_BODY(iseq
)->param
.flags
.has_kw
|| ISEQ_BODY(iseq
)->param
.flags
.has_kwrest
) {
577 rb_ary_pop(args
->rest
);
579 keyword_hash
= rest_last
;
591 if (args
->argc
> 0 && (kw_flag
& VM_CALL_KW_SPLAT
)) {
593 VALUE last_arg
= args
->argv
[args
->argc
-1];
594 if (ignore_keyword_hash_p(last_arg
, iseq
, &kw_flag
, &converted_keyword_hash
)) {
597 kw_flag
&= ~(VM_CALL_KW_SPLAT
| VM_CALL_KW_SPLAT_MUT
);
600 if (last_arg
!= converted_keyword_hash
) {
601 last_arg
= converted_keyword_hash
;
602 args
->argv
[args
->argc
-1] = last_arg
;
605 if (ISEQ_BODY(iseq
)->param
.flags
.ruby2_keywords
) {
606 flag_keyword_hash
= last_arg
;
608 else if (ISEQ_BODY(iseq
)->param
.flags
.has_kw
|| ISEQ_BODY(iseq
)->param
.flags
.has_kwrest
) {
611 keyword_hash
= last_arg
;
617 if (flag_keyword_hash
&& RB_TYPE_P(flag_keyword_hash
, T_HASH
)) {
618 ((struct RHash
*)flag_keyword_hash
)->basic
.flags
|= RHASH_PASS_AS_KEYWORDS
;
621 if (kw_flag
&& ISEQ_BODY(iseq
)->param
.flags
.accepts_no_kwarg
) {
622 rb_raise(rb_eArgError
, "no keywords accepted");
625 switch (arg_setup_type
) {
626 case arg_setup_method
:
627 break; /* do nothing special */
628 case arg_setup_block
:
629 if (given_argc
== (NIL_P(keyword_hash
) ? 1 : 2) &&
631 (min_argc
> 0 || ISEQ_BODY(iseq
)->param
.opt_num
> 1) &&
632 !ISEQ_BODY(iseq
)->param
.flags
.ambiguous_param0
&&
633 !((ISEQ_BODY(iseq
)->param
.flags
.has_kw
||
634 ISEQ_BODY(iseq
)->param
.flags
.has_kwrest
)
636 args_check_block_arg0(args
)) {
637 given_argc
= RARRAY_LENINT(args
->rest
);
643 if (given_argc
< min_argc
) {
644 if (arg_setup_type
== arg_setup_block
) {
645 CHECK_VM_STACK_OVERFLOW(ec
->cfp
, min_argc
);
646 given_argc
= min_argc
;
647 args_extend(args
, min_argc
);
650 argument_arity_error(ec
, iseq
, given_argc
, min_argc
, max_argc
);
654 if (given_argc
> max_argc
&& max_argc
!= UNLIMITED_ARGUMENTS
) {
655 if (arg_setup_type
== arg_setup_block
) {
657 args_reduce(args
, given_argc
- max_argc
);
658 given_argc
= max_argc
;
661 argument_arity_error(ec
, iseq
, given_argc
, min_argc
, max_argc
);
665 if (ISEQ_BODY(iseq
)->param
.flags
.has_lead
) {
666 args_setup_lead_parameters(args
, ISEQ_BODY(iseq
)->param
.lead_num
, locals
+ 0);
669 if (ISEQ_BODY(iseq
)->param
.flags
.has_rest
|| ISEQ_BODY(iseq
)->param
.flags
.has_post
){
673 if (ISEQ_BODY(iseq
)->param
.flags
.has_post
) {
674 args_setup_post_parameters(args
, ISEQ_BODY(iseq
)->param
.post_num
, locals
+ ISEQ_BODY(iseq
)->param
.post_start
);
677 if (ISEQ_BODY(iseq
)->param
.flags
.has_opt
) {
678 int opt
= args_setup_opt_parameters(args
, ISEQ_BODY(iseq
)->param
.opt_num
, locals
+ ISEQ_BODY(iseq
)->param
.lead_num
);
679 opt_pc
= (int)ISEQ_BODY(iseq
)->param
.opt_table
[opt
];
682 if (ISEQ_BODY(iseq
)->param
.flags
.has_rest
) {
683 args_setup_rest_parameter(args
, locals
+ ISEQ_BODY(iseq
)->param
.rest_start
);
684 VALUE ary
= *(locals
+ ISEQ_BODY(iseq
)->param
.rest_start
);
685 VALUE index
= RARRAY_LEN(ary
) - 1;
686 if (splat_flagged_keyword_hash
&&
687 !ISEQ_BODY(iseq
)->param
.flags
.ruby2_keywords
&&
688 !ISEQ_BODY(iseq
)->param
.flags
.has_kw
&&
689 !ISEQ_BODY(iseq
)->param
.flags
.has_kwrest
&&
690 RARRAY_AREF(ary
, index
) == splat_flagged_keyword_hash
) {
691 ((struct RHash
*)rest_last
)->basic
.flags
&= ~RHASH_PASS_AS_KEYWORDS
;
692 RARRAY_ASET(ary
, index
, rest_last
);
696 if (ISEQ_BODY(iseq
)->param
.flags
.has_kw
) {
697 VALUE
* const klocals
= locals
+ ISEQ_BODY(iseq
)->param
.keyword
->bits_start
- ISEQ_BODY(iseq
)->param
.keyword
->num
;
699 if (args
->kw_argv
!= NULL
) {
700 const struct rb_callinfo_kwarg
*kw_arg
= args
->kw_arg
;
701 args_setup_kw_parameters(ec
, iseq
, args
->kw_argv
, kw_arg
->keyword_len
, kw_arg
->keywords
, klocals
);
703 else if (!NIL_P(keyword_hash
)) {
704 int kw_len
= rb_long2int(RHASH_SIZE(keyword_hash
));
705 struct fill_values_arg arg
;
707 arg
.keys
= args
->kw_argv
= ALLOCA_N(VALUE
, kw_len
* 2);
708 arg
.vals
= arg
.keys
+ kw_len
;
710 rb_hash_foreach(keyword_hash
, fill_keys_values
, (VALUE
)&arg
);
711 VM_ASSERT(arg
.argc
== kw_len
);
712 args_setup_kw_parameters(ec
, iseq
, arg
.vals
, kw_len
, arg
.keys
, klocals
);
715 VM_ASSERT(args_argc(args
) == 0);
716 args_setup_kw_parameters(ec
, iseq
, NULL
, 0, NULL
, klocals
);
719 else if (ISEQ_BODY(iseq
)->param
.flags
.has_kwrest
) {
720 args_setup_kw_rest_parameter(keyword_hash
, locals
+ ISEQ_BODY(iseq
)->param
.keyword
->rest_start
, kw_flag
);
722 else if (!NIL_P(keyword_hash
) && RHASH_SIZE(keyword_hash
) > 0 && arg_setup_type
== arg_setup_method
) {
723 argument_kw_error(ec
, iseq
, "unknown", rb_hash_keys(keyword_hash
));
726 if (ISEQ_BODY(iseq
)->param
.flags
.has_block
) {
727 if (ISEQ_BODY(iseq
)->local_iseq
== iseq
) {
731 args_setup_block_parameter(ec
, calling
, locals
+ ISEQ_BODY(iseq
)->param
.block_start
);
738 for (i
=0; i
<ISEQ_BODY(iseq
)->param
.size
; i
++) {
739 ruby_debug_printf("local[%d] = %p\n", i
, (void *)locals
[i
]);
744 ec
->cfp
->sp
= orig_sp
;
749 raise_argument_error(rb_execution_context_t
*ec
, const rb_iseq_t
*iseq
, const VALUE exc
)
754 vm_push_frame(ec
, iseq
, VM_FRAME_MAGIC_DUMMY
| VM_ENV_FLAG_LOCAL
, Qnil
/* self */,
755 VM_BLOCK_HANDLER_NONE
/* specval*/, Qfalse
/* me or cref */,
756 ISEQ_BODY(iseq
)->iseq_encoded
,
757 ec
->cfp
->sp
, 0, 0 /* stack_max */);
758 at
= rb_ec_backtrace_object(ec
);
759 rb_backtrace_use_iseq_first_lineno_for_last_location(at
);
763 at
= rb_ec_backtrace_object(ec
);
766 rb_ivar_set(exc
, idBt_locations
, at
);
767 rb_exc_set_backtrace(exc
, at
);
772 argument_arity_error(rb_execution_context_t
*ec
, const rb_iseq_t
*iseq
, const int miss_argc
, const int min_argc
, const int max_argc
)
774 VALUE exc
= rb_arity_error_new(miss_argc
, min_argc
, max_argc
);
775 if (ISEQ_BODY(iseq
)->param
.flags
.has_kw
) {
776 const struct rb_iseq_param_keyword
*const kw
= ISEQ_BODY(iseq
)->param
.keyword
;
777 const ID
*keywords
= kw
->table
;
778 int req_key_num
= kw
->required_num
;
779 if (req_key_num
> 0) {
780 static const char required
[] = "; required keywords";
781 VALUE mesg
= rb_attr_get(exc
, idMesg
);
782 rb_str_resize(mesg
, RSTRING_LEN(mesg
)-1);
783 rb_str_cat(mesg
, required
, sizeof(required
) - 1 - (req_key_num
== 1));
784 rb_str_cat_cstr(mesg
, ":");
786 rb_str_cat_cstr(mesg
, " ");
787 rb_str_append(mesg
, rb_id2str(*keywords
++));
788 rb_str_cat_cstr(mesg
, ",");
789 } while (--req_key_num
);
790 RSTRING_PTR(mesg
)[RSTRING_LEN(mesg
)-1] = ')';
793 raise_argument_error(ec
, iseq
, exc
);
797 argument_kw_error(rb_execution_context_t
*ec
, const rb_iseq_t
*iseq
, const char *error
, const VALUE keys
)
799 raise_argument_error(ec
, iseq
, rb_keyword_error_new(error
, keys
));
803 vm_to_proc(VALUE proc
)
805 if (UNLIKELY(!rb_obj_is_proc(proc
))) {
807 const rb_callable_method_entry_t
*me
=
808 rb_callable_method_entry_with_refinements(CLASS_OF(proc
), idTo_proc
, NULL
);
811 b
= rb_vm_call0(GET_EC(), proc
, idTo_proc
, 0, NULL
, me
, RB_NO_KEYWORDS
);
814 /* NOTE: calling method_missing */
815 b
= rb_check_convert_type_with_id(proc
, T_DATA
, "Proc", idTo_proc
);
818 if (NIL_P(b
) || !rb_obj_is_proc(b
)) {
819 rb_raise(rb_eTypeError
,
820 "wrong argument type %s (expected Proc)",
821 rb_obj_classname(proc
));
831 refine_sym_proc_call(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg
, callback_arg
))
835 const rb_callable_method_entry_t
*me
= 0; /* for hidden object case */
836 rb_execution_context_t
*ec
;
837 const VALUE symbol
= RARRAY_AREF(callback_arg
, 0);
838 const VALUE refinements
= RARRAY_AREF(callback_arg
, 1);
839 int kw_splat
= RB_PASS_CALLED_KEYWORDS
;
843 rb_raise(rb_eArgError
, "no receiver given");
847 mid
= SYM2ID(symbol
);
848 for (klass
= CLASS_OF(obj
); klass
; klass
= RCLASS_SUPER(klass
)) {
849 me
= rb_callable_method_entry(klass
, mid
);
851 me
= rb_resolve_refined_method_callable(refinements
, me
);
857 if (!NIL_P(blockarg
)) {
858 vm_passed_block_handler_set(ec
, blockarg
);
861 return method_missing(ec
, obj
, mid
, argc
, argv
, MISSING_NOENTRY
, kw_splat
);
863 return rb_vm_call0(ec
, obj
, mid
, argc
, argv
, me
, kw_splat
);
867 vm_caller_setup_arg_block(const rb_execution_context_t
*ec
, rb_control_frame_t
*reg_cfp
,
868 const struct rb_callinfo
*ci
, const rb_iseq_t
*blockiseq
, const int is_super
)
870 if (vm_ci_flag(ci
) & VM_CALL_ARGS_BLOCKARG
) {
871 VALUE block_code
= *(--reg_cfp
->sp
);
873 if (NIL_P(block_code
)) {
874 return VM_BLOCK_HANDLER_NONE
;
876 else if (block_code
== rb_block_param_proxy
) {
877 VM_ASSERT(!VM_CFP_IN_HEAP_P(GET_EC(), reg_cfp
));
878 VALUE handler
= VM_CF_BLOCK_HANDLER(reg_cfp
);
879 reg_cfp
->block_code
= (const void *) handler
;
882 else if (SYMBOL_P(block_code
) && rb_method_basic_definition_p(rb_cSymbol
, idTo_proc
)) {
883 const rb_cref_t
*cref
= vm_env_cref(reg_cfp
->ep
);
884 if (cref
&& !NIL_P(cref
->refinements
)) {
885 VALUE ref
= cref
->refinements
;
886 VALUE func
= rb_hash_lookup(ref
, block_code
);
888 /* TODO: limit cached funcs */
889 VALUE callback_arg
= rb_ary_hidden_new(2);
890 rb_ary_push(callback_arg
, block_code
);
891 rb_ary_push(callback_arg
, ref
);
892 OBJ_FREEZE_RAW(callback_arg
);
893 func
= rb_func_lambda_new(refine_sym_proc_call
, callback_arg
, 1, UNLIMITED_ARGUMENTS
);
894 rb_hash_aset(ref
, block_code
, func
);
901 return vm_to_proc(block_code
);
904 else if (blockiseq
!= NULL
) { /* likely */
905 struct rb_captured_block
*captured
= VM_CFP_TO_CAPTURED_BLOCK(reg_cfp
);
906 captured
->code
.iseq
= blockiseq
;
907 return VM_BH_FROM_ISEQ_BLOCK(captured
);
911 return GET_BLOCK_HANDLER();
914 return VM_BLOCK_HANDLER_NONE
;