1 /**********************************************************************
6 created at: Sat May 24 16:02:32 JST 2008
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
12 **********************************************************************/
14 struct local_var_list
{
18 static inline VALUE
method_missing(rb_execution_context_t
*ec
, VALUE obj
, ID id
, int argc
, const VALUE
*argv
, enum method_missing_reason call_status
, int kw_splat
);
19 static inline VALUE
vm_yield_with_cref(rb_execution_context_t
*ec
, int argc
, const VALUE
*argv
, int kw_splat
, const rb_cref_t
*cref
, int is_lambda
);
20 static inline VALUE
vm_yield(rb_execution_context_t
*ec
, int argc
, const VALUE
*argv
, int kw_splat
);
21 static inline VALUE
vm_yield_with_block(rb_execution_context_t
*ec
, int argc
, const VALUE
*argv
, VALUE block_handler
, int kw_splat
);
22 static inline VALUE
vm_yield_force_blockarg(rb_execution_context_t
*ec
, VALUE args
);
23 VALUE
vm_exec(rb_execution_context_t
*ec
, bool mjit_enable_p
);
24 static void vm_set_eval_stack(rb_execution_context_t
* th
, const rb_iseq_t
*iseq
, const rb_cref_t
*cref
, const struct rb_block
*base_block
);
25 static int vm_collect_local_variables_in_heap(const VALUE
*dfp
, const struct local_var_list
*vars
);
27 static VALUE rb_eUncaughtThrow
;
28 static ID id_result
, id_tag
, id_value
;
29 #define id_mesg idMesg
31 typedef enum call_type
{
40 static VALUE
send_internal(int argc
, const VALUE
*argv
, VALUE recv
, call_type scope
);
41 static VALUE
vm_call0_body(rb_execution_context_t
* ec
, struct rb_calling_info
*calling
, const VALUE
*argv
);
45 MJIT_FUNC_EXPORTED VALUE
46 rb_vm_call0(rb_execution_context_t
*ec
, VALUE recv
, ID id
, int argc
, const VALUE
*argv
, const rb_callable_method_entry_t
*cme
, int kw_splat
)
48 struct rb_calling_info calling
= {
49 .ci
= &VM_CI_ON_STACK(id
, kw_splat
? VM_CALL_KW_SPLAT
: 0, argc
, NULL
),
50 .cc
= &VM_CC_ON_STACK(Qfalse
, vm_call_general
, { 0 }, cme
),
51 .block_handler
= vm_passed_block_handler(ec
),
57 return vm_call0_body(ec
, &calling
, argv
);
60 MJIT_FUNC_EXPORTED VALUE
61 rb_vm_call_with_refinements(rb_execution_context_t
*ec
, VALUE recv
, ID id
, int argc
, const VALUE
*argv
, int kw_splat
)
63 const rb_callable_method_entry_t
*me
=
64 rb_callable_method_entry_with_refinements(CLASS_OF(recv
), id
, NULL
);
66 return rb_vm_call0(ec
, recv
, id
, argc
, argv
, me
, kw_splat
);
69 /* fallback to funcall (e.g. method_missing) */
70 return rb_funcallv(recv
, id
, argc
, argv
);
75 vm_call0_cc(rb_execution_context_t
*ec
, VALUE recv
, ID id
, int argc
, const VALUE
*argv
, const struct rb_callcache
*cc
, int kw_splat
)
77 struct rb_calling_info calling
= {
78 .ci
= &VM_CI_ON_STACK(id
, kw_splat
? VM_CALL_KW_SPLAT
: 0, argc
, NULL
),
80 .block_handler
= vm_passed_block_handler(ec
),
86 return vm_call0_body(ec
, &calling
, argv
);
90 vm_call0_cme(rb_execution_context_t
*ec
, struct rb_calling_info
*calling
, const VALUE
*argv
, const rb_callable_method_entry_t
*cme
)
92 calling
->cc
= &VM_CC_ON_STACK(Qfalse
, vm_call_general
, { 0 }, cme
);
93 return vm_call0_body(ec
, calling
, argv
);
97 vm_call0_super(rb_execution_context_t
*ec
, struct rb_calling_info
*calling
, const VALUE
*argv
, VALUE klass
, enum method_missing_reason ex
)
99 ID mid
= vm_ci_mid(calling
->ci
);
100 klass
= RCLASS_SUPER(klass
);
103 const rb_callable_method_entry_t
*cme
= rb_callable_method_entry(klass
, mid
);
106 RUBY_VM_CHECK_INTS(ec
);
107 return vm_call0_cme(ec
, calling
, argv
, cme
);
111 vm_passed_block_handler_set(ec
, calling
->block_handler
);
112 return method_missing(ec
, calling
->recv
, mid
, calling
->argc
, argv
, ex
, calling
->kw_splat
);
116 vm_call0_cfunc_with_frame(rb_execution_context_t
* ec
, struct rb_calling_info
*calling
, const VALUE
*argv
)
118 const struct rb_callinfo
*ci
= calling
->ci
;
120 const rb_callable_method_entry_t
*me
= vm_cc_cme(calling
->cc
);
121 const rb_method_cfunc_t
*cfunc
= UNALIGNED_MEMBER_PTR(me
->def
, body
.cfunc
);
122 int len
= cfunc
->argc
;
123 VALUE recv
= calling
->recv
;
124 int argc
= calling
->argc
;
125 ID mid
= vm_ci_mid(ci
);
126 VALUE block_handler
= calling
->block_handler
;
127 int frame_flags
= VM_FRAME_MAGIC_CFUNC
| VM_FRAME_FLAG_CFRAME
| VM_ENV_FLAG_LOCAL
;
129 if (calling
->kw_splat
) {
130 if (argc
> 0 && RB_TYPE_P(argv
[argc
-1], T_HASH
) && RHASH_EMPTY_P(argv
[argc
-1])) {
134 frame_flags
|= VM_FRAME_FLAG_CFRAME_KW
;
138 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec
, me
->owner
, me
->def
->original_id
);
139 EXEC_EVENT_HOOK(ec
, RUBY_EVENT_C_CALL
, recv
, me
->def
->original_id
, mid
, me
->owner
, Qnil
);
141 rb_control_frame_t
*reg_cfp
= ec
->cfp
;
143 vm_push_frame(ec
, 0, frame_flags
, recv
,
144 block_handler
, (VALUE
)me
,
145 0, reg_cfp
->sp
, 0, 0);
147 if (len
>= 0) rb_check_arity(argc
, len
, len
);
149 val
= (*cfunc
->invoker
)(recv
, argc
, argv
, cfunc
->func
);
151 CHECK_CFP_CONSISTENCY("vm_call0_cfunc_with_frame");
154 EXEC_EVENT_HOOK(ec
, RUBY_EVENT_C_RETURN
, recv
, me
->def
->original_id
, mid
, me
->owner
, val
);
155 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec
, me
->owner
, me
->def
->original_id
);
161 vm_call0_cfunc(rb_execution_context_t
*ec
, struct rb_calling_info
*calling
, const VALUE
*argv
)
163 return vm_call0_cfunc_with_frame(ec
, calling
, argv
);
167 vm_call_check_arity(struct rb_calling_info
*calling
, int argc
, const VALUE
*argv
)
169 if (calling
->kw_splat
&&
171 RB_TYPE_P(argv
[calling
->argc
-1], T_HASH
) &&
172 RHASH_EMPTY_P(argv
[calling
->argc
-1])) {
176 rb_check_arity(calling
->argc
, argc
, argc
);
179 /* `ci' should point temporal value (on stack value) */
181 vm_call0_body(rb_execution_context_t
*ec
, struct rb_calling_info
*calling
, const VALUE
*argv
)
183 const struct rb_callinfo
*ci
= calling
->ci
;
184 const struct rb_callcache
*cc
= calling
->cc
;
189 switch (vm_cc_cme(cc
)->def
->type
) {
190 case VM_METHOD_TYPE_ISEQ
:
192 rb_control_frame_t
*reg_cfp
= ec
->cfp
;
195 CHECK_VM_STACK_OVERFLOW(reg_cfp
, calling
->argc
+ 1);
196 vm_check_canary(ec
, reg_cfp
->sp
);
198 *reg_cfp
->sp
++ = calling
->recv
;
199 for (i
= 0; i
< calling
->argc
; i
++) {
200 *reg_cfp
->sp
++ = argv
[i
];
203 vm_call_iseq_setup(ec
, reg_cfp
, calling
);
204 VM_ENV_FLAGS_SET(ec
->cfp
->ep
, VM_FRAME_FLAG_FINISH
);
205 return vm_exec(ec
, true); /* CHECK_INTS in this function */
207 case VM_METHOD_TYPE_NOTIMPLEMENTED
:
208 case VM_METHOD_TYPE_CFUNC
:
209 ret
= vm_call0_cfunc(ec
, calling
, argv
);
211 case VM_METHOD_TYPE_ATTRSET
:
212 vm_call_check_arity(calling
, 1, argv
);
213 VM_CALL_METHOD_ATTR(ret
,
214 rb_ivar_set(calling
->recv
, vm_cc_cme(cc
)->def
->body
.attr
.id
, argv
[0]),
217 case VM_METHOD_TYPE_IVAR
:
218 vm_call_check_arity(calling
, 0, argv
);
219 VM_CALL_METHOD_ATTR(ret
,
220 rb_attr_get(calling
->recv
, vm_cc_cme(cc
)->def
->body
.attr
.id
),
223 case VM_METHOD_TYPE_BMETHOD
:
224 ret
= vm_call_bmethod_body(ec
, calling
, argv
);
226 case VM_METHOD_TYPE_ZSUPER
:
228 VALUE klass
= RCLASS_ORIGIN(vm_cc_cme(cc
)->defined_class
);
229 return vm_call0_super(ec
, calling
, argv
, klass
, MISSING_SUPER
);
231 case VM_METHOD_TYPE_REFINED
:
233 const rb_callable_method_entry_t
*cme
= vm_cc_cme(cc
);
235 if (cme
->def
->body
.refined
.orig_me
) {
236 const rb_callable_method_entry_t
*orig_cme
= refined_method_callable_without_refinement(cme
);
237 return vm_call0_cme(ec
, calling
, argv
, orig_cme
);
240 VALUE klass
= cme
->defined_class
;
241 return vm_call0_super(ec
, calling
, argv
, klass
, 0);
243 case VM_METHOD_TYPE_ALIAS
:
245 const rb_callable_method_entry_t
*cme
= vm_cc_cme(cc
);
246 const rb_callable_method_entry_t
*orig_cme
= aliased_callable_method_entry(cme
);
248 if (cme
== orig_cme
) rb_bug("same!!");
250 if (vm_cc_markable(cc
)) {
251 return vm_call0_cme(ec
, calling
, argv
, orig_cme
);
254 *((const rb_callable_method_entry_t
**)&cc
->cme_
) = orig_cme
;
258 case VM_METHOD_TYPE_MISSING
:
260 vm_passed_block_handler_set(ec
, calling
->block_handler
);
261 return method_missing(ec
, calling
->recv
, vm_ci_mid(ci
), calling
->argc
,
262 argv
, MISSING_NOENTRY
, calling
->kw_splat
);
264 case VM_METHOD_TYPE_OPTIMIZED
:
265 switch (vm_cc_cme(cc
)->def
->body
.optimized
.type
) {
266 case OPTIMIZED_METHOD_TYPE_SEND
:
267 ret
= send_internal(calling
->argc
, argv
, calling
->recv
, calling
->kw_splat
? CALL_FCALL_KW
: CALL_FCALL
);
269 case OPTIMIZED_METHOD_TYPE_CALL
:
272 GetProcPtr(calling
->recv
, proc
);
273 ret
= rb_vm_invoke_proc(ec
, proc
, calling
->argc
, argv
, calling
->kw_splat
, calling
->block_handler
);
276 case OPTIMIZED_METHOD_TYPE_STRUCT_AREF
:
277 vm_call_check_arity(calling
, 0, argv
);
278 ret
= vm_call_opt_struct_aref0(ec
, calling
);
280 case OPTIMIZED_METHOD_TYPE_STRUCT_ASET
:
281 vm_call_check_arity(calling
, 1, argv
);
282 ret
= vm_call_opt_struct_aset0(ec
, calling
, argv
[0]);
285 rb_bug("vm_call0: unsupported optimized method type (%d)", vm_cc_cme(cc
)->def
->body
.optimized
.type
);
288 case VM_METHOD_TYPE_UNDEF
:
291 rb_bug("vm_call0: unsupported method type (%d)", vm_cc_cme(cc
)->def
->type
);
295 RUBY_VM_CHECK_INTS(ec
);
299 MJIT_FUNC_EXPORTED VALUE
300 rb_vm_call_kw(rb_execution_context_t
*ec
, VALUE recv
, VALUE id
, int argc
, const VALUE
*argv
, const rb_callable_method_entry_t
*me
, int kw_splat
)
302 return rb_vm_call0(ec
, recv
, id
, argc
, argv
, me
, kw_splat
);
306 vm_call_super(rb_execution_context_t
*ec
, int argc
, const VALUE
*argv
, int kw_splat
)
308 VALUE recv
= ec
->cfp
->self
;
311 rb_control_frame_t
*cfp
= ec
->cfp
;
312 const rb_callable_method_entry_t
*me
= rb_vm_frame_method_entry(cfp
);
314 if (VM_FRAME_RUBYFRAME_P(cfp
)) {
315 rb_bug("vm_call_super: should not be reached");
318 klass
= RCLASS_ORIGIN(me
->defined_class
);
319 klass
= RCLASS_SUPER(klass
);
320 id
= me
->def
->original_id
;
321 me
= rb_callable_method_entry(klass
, id
);
324 return method_missing(ec
, recv
, id
, argc
, argv
, MISSING_SUPER
, kw_splat
);
326 return rb_vm_call_kw(ec
, recv
, id
, argc
, argv
, me
, kw_splat
);
330 rb_call_super_kw(int argc
, const VALUE
*argv
, int kw_splat
)
332 rb_execution_context_t
*ec
= GET_EC();
333 PASS_PASSED_BLOCK_HANDLER_EC(ec
);
334 return vm_call_super(ec
, argc
, argv
, kw_splat
);
338 rb_call_super(int argc
, const VALUE
*argv
)
340 return rb_call_super_kw(argc
, argv
, RB_NO_KEYWORDS
);
344 rb_current_receiver(void)
346 const rb_execution_context_t
*ec
= GET_EC();
347 rb_control_frame_t
*cfp
;
348 if (!ec
|| !(cfp
= ec
->cfp
)) {
349 rb_raise(rb_eRuntimeError
, "no self, no life");
354 #endif /* #ifndef MJIT_HEADER */
357 stack_check(rb_execution_context_t
*ec
)
359 if (!rb_ec_raised_p(ec
, RAISED_STACKOVERFLOW
) &&
360 rb_ec_stack_check(ec
)) {
361 rb_ec_raised_set(ec
, RAISED_STACKOVERFLOW
);
362 rb_ec_stack_overflow(ec
, FALSE
);
369 rb_check_stack_overflow(void)
371 #ifndef RB_THREAD_LOCAL_SPECIFIER
372 if (!ruby_current_ec_key
) return;
374 rb_execution_context_t
*ec
= GET_EC();
375 if (ec
) stack_check(ec
);
378 NORETURN(static void uncallable_object(VALUE recv
, ID mid
));
379 static inline const rb_callable_method_entry_t
*rb_search_method_entry(VALUE recv
, ID mid
);
380 static inline enum method_missing_reason
rb_method_call_status(rb_execution_context_t
*ec
, const rb_callable_method_entry_t
*me
, call_type scope
, VALUE self
);
382 static const struct rb_callcache
*
383 cc_new(VALUE klass
, ID mid
, int argc
, const rb_callable_method_entry_t
*cme
)
385 const struct rb_callcache
*cc
= NULL
;
389 struct rb_class_cc_entries
*ccs
;
390 struct rb_id_table
*cc_tbl
= RCLASS_CC_TBL(klass
);
393 if (rb_id_table_lookup(cc_tbl
, mid
, &ccs_data
)) {
395 ccs
= (struct rb_class_cc_entries
*)ccs_data
;
398 ccs
= vm_ccs_create(klass
, cme
);
399 rb_id_table_insert(cc_tbl
, mid
, (VALUE
)ccs
);
402 for (int i
=0; i
<ccs
->len
; i
++) {
403 cc
= ccs
->entries
[i
].cc
;
404 if (vm_cc_cme(cc
) == cme
) {
411 const struct rb_callinfo
*ci
= vm_ci_new(mid
, 0, argc
, false); // TODO: proper ci
412 cc
= vm_cc_new(klass
, cme
, vm_call_general
);
413 METHOD_ENTRY_CACHED_SET((struct rb_callable_method_entry_struct
*)cme
);
414 vm_ccs_push(klass
, ccs
, ci
, cc
);
423 gccct_hash(VALUE klass
, ID mid
)
425 return (klass
>> 3) ^ (VALUE
)mid
;
428 NOINLINE(static const struct rb_callcache
*gccct_method_search_slowpath(rb_vm_t
*vm
, VALUE klass
, ID mid
, int argc
, unsigned int index
));
430 static const struct rb_callcache
*
431 gccct_method_search_slowpath(rb_vm_t
*vm
, VALUE klass
, ID mid
, int argc
, unsigned int index
)
433 const rb_callable_method_entry_t
*cme
= rb_callable_method_entry(klass
, mid
);
434 const struct rb_callcache
*cc
;
437 cc
= cc_new(klass
, mid
, argc
, cme
);
443 return vm
->global_cc_cache_table
[index
] = cc
;
446 static inline const struct rb_callcache
*
447 gccct_method_search(rb_execution_context_t
*ec
, VALUE recv
, ID mid
, int argc
)
451 if (!SPECIAL_CONST_P(recv
)) {
452 klass
= RBASIC_CLASS(recv
);
453 if (UNLIKELY(!klass
)) uncallable_object(recv
, mid
);
456 klass
= CLASS_OF(recv
);
459 // search global method cache
460 unsigned int index
= (unsigned int)(gccct_hash(klass
, mid
) % VM_GLOBAL_CC_CACHE_TABLE_SIZE
);
461 rb_vm_t
*vm
= rb_ec_vm_ptr(ec
);
462 const struct rb_callcache
*cc
= vm
->global_cc_cache_table
[index
];
465 if (LIKELY(vm_cc_class_check(cc
, klass
))) {
466 const rb_callable_method_entry_t
*cme
= vm_cc_cme(cc
);
467 if (LIKELY(!METHOD_ENTRY_INVALIDATED(cme
) &&
468 cme
->called_id
== mid
)) {
470 VM_ASSERT(vm_cc_check_cme(cc
, rb_callable_method_entry(klass
, mid
)));
471 RB_DEBUG_COUNTER_INC(gccct_hit
);
478 RB_DEBUG_COUNTER_INC(gccct_null
);
481 RB_DEBUG_COUNTER_INC(gccct_miss
);
482 return gccct_method_search_slowpath(vm
, klass
, mid
, argc
, index
);
487 * calls the specified method.
489 * This function is called by functions in rb_call* family.
490 * \param ec current execution context
491 * \param recv receiver of the method
492 * \param mid an ID that represents the name of the method
493 * \param argc the number of method arguments
494 * \param argv a pointer to an array of method arguments
496 * \param self self in the caller. Qundef means no self is considered and
497 * protected methods cannot be called
499 * \note \a self is used in order to controlling access to protected methods.
502 rb_call0(rb_execution_context_t
*ec
,
503 VALUE recv
, ID mid
, int argc
, const VALUE
*argv
,
504 call_type call_scope
, VALUE self
)
506 enum method_missing_reason call_status
;
507 call_type scope
= call_scope
;
508 int kw_splat
= RB_NO_KEYWORDS
;
523 const struct rb_callcache
*cc
= gccct_method_search(ec
, recv
, mid
, argc
);
525 if (scope
== CALL_PUBLIC
) {
526 RB_DEBUG_COUNTER_INC(call0_public
);
528 const rb_callable_method_entry_t
*cc_cme
= cc
? vm_cc_cme(cc
) : NULL
;
529 const rb_callable_method_entry_t
*cme
= callable_method_entry_refeinements0(CLASS_OF(recv
), mid
, NULL
, true, cc_cme
);
530 call_status
= rb_method_call_status(ec
, cme
, scope
, self
);
532 if (UNLIKELY(call_status
!= MISSING_NONE
)) {
533 return method_missing(ec
, recv
, mid
, argc
, argv
, call_status
, kw_splat
);
535 else if (UNLIKELY(cc_cme
!= cme
)) { // refinement is solved
537 return rb_vm_call_kw(ec
, recv
, mid
, argc
, argv
, cme
, kw_splat
);
541 RB_DEBUG_COUNTER_INC(call0_other
);
542 call_status
= rb_method_call_status(ec
, cc
? vm_cc_cme(cc
) : NULL
, scope
, self
);
544 if (UNLIKELY(call_status
!= MISSING_NONE
)) {
545 return method_missing(ec
, recv
, mid
, argc
, argv
, call_status
, kw_splat
);
550 return vm_call0_cc(ec
, recv
, mid
, argc
, argv
, cc
, kw_splat
);
553 struct rescue_funcall_args
{
557 rb_execution_context_t
*ec
;
558 const rb_callable_method_entry_t
*cme
;
559 unsigned int respond
: 1;
560 unsigned int respond_to_missing
: 1;
567 check_funcall_exec(VALUE v
)
569 struct rescue_funcall_args
*args
= (void *)v
;
570 return call_method_entry(args
->ec
, args
->defined_class
,
571 args
->recv
, idMethodMissing
,
572 args
->cme
, args
->argc
, args
->argv
, args
->kw_splat
);
576 check_funcall_failed(VALUE v
, VALUE e
)
578 struct rescue_funcall_args
*args
= (void *)v
;
579 int ret
= args
->respond
;
581 switch (method_boundp(args
->defined_class
, args
->mid
,
582 BOUND_PRIVATE
|BOUND_RESPONDS
)) {
587 ret
= args
->respond_to_missing
;
601 check_funcall_respond_to(rb_execution_context_t
*ec
, VALUE klass
, VALUE recv
, ID mid
)
603 return vm_respond_to(ec
, klass
, recv
, mid
, TRUE
);
607 check_funcall_callable(rb_execution_context_t
*ec
, const rb_callable_method_entry_t
*me
)
609 return rb_method_call_status(ec
, me
, CALL_FCALL
, ec
->cfp
->self
) == MISSING_NONE
;
613 check_funcall_missing(rb_execution_context_t
*ec
, VALUE klass
, VALUE recv
, ID mid
, int argc
, const VALUE
*argv
, int respond
, VALUE def
, int kw_splat
)
615 struct rescue_funcall_args args
;
616 const rb_callable_method_entry_t
*cme
;
619 ret
= basic_obj_respond_to_missing(ec
, klass
, recv
,
621 if (!RTEST(ret
)) return def
;
622 args
.respond
= respond
> 0;
623 args
.respond_to_missing
= (ret
!= Qundef
);
625 cme
= callable_method_entry(klass
, idMethodMissing
, &args
.defined_class
);
627 if (cme
&& !METHOD_ENTRY_BASIC(cme
)) {
628 VALUE argbuf
, *new_args
= ALLOCV_N(VALUE
, argbuf
, argc
+1);
630 new_args
[0] = ID2SYM(mid
);
633 static const VALUE buf
= Qfalse
;
634 VM_ASSERT(argc
== 0);
638 MEMCPY(new_args
+1, argv
, VALUE
, argc
);
639 ec
->method_missing_reason
= MISSING_NOENTRY
;
644 args
.argc
= argc
+ 1;
645 args
.argv
= new_args
;
646 args
.kw_splat
= kw_splat
;
647 ret
= rb_rescue2(check_funcall_exec
, (VALUE
)&args
,
648 check_funcall_failed
, (VALUE
)&args
,
649 rb_eNoMethodError
, (VALUE
)0);
655 static VALUE
rb_check_funcall_default_kw(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
, VALUE def
, int kw_splat
);
658 rb_check_funcall_kw(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
, int kw_splat
)
660 return rb_check_funcall_default_kw(recv
, mid
, argc
, argv
, Qundef
, kw_splat
);
664 rb_check_funcall(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
)
666 return rb_check_funcall_default_kw(recv
, mid
, argc
, argv
, Qundef
, RB_NO_KEYWORDS
);
670 rb_check_funcall_default_kw(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
, VALUE def
, int kw_splat
)
672 VM_ASSERT(ruby_thread_has_gvl_p());
674 VALUE klass
= CLASS_OF(recv
);
675 const rb_callable_method_entry_t
*me
;
676 rb_execution_context_t
*ec
= GET_EC();
677 int respond
= check_funcall_respond_to(ec
, klass
, recv
, mid
);
682 me
= rb_search_method_entry(recv
, mid
);
683 if (!check_funcall_callable(ec
, me
)) {
684 VALUE ret
= check_funcall_missing(ec
, klass
, recv
, mid
, argc
, argv
,
685 respond
, def
, kw_splat
);
686 if (ret
== Qundef
) ret
= def
;
690 return rb_vm_call_kw(ec
, recv
, mid
, argc
, argv
, me
, kw_splat
);
694 rb_check_funcall_default(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
, VALUE def
)
696 return rb_check_funcall_default_kw(recv
, mid
, argc
, argv
, def
, RB_NO_KEYWORDS
);
700 rb_check_funcall_with_hook_kw(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
,
701 rb_check_funcall_hook
*hook
, VALUE arg
, int kw_splat
)
703 VALUE klass
= CLASS_OF(recv
);
704 const rb_callable_method_entry_t
*me
;
705 rb_execution_context_t
*ec
= GET_EC();
706 int respond
= check_funcall_respond_to(ec
, klass
, recv
, mid
);
709 (*hook
)(FALSE
, recv
, mid
, argc
, argv
, arg
);
713 me
= rb_search_method_entry(recv
, mid
);
714 if (!check_funcall_callable(ec
, me
)) {
715 VALUE ret
= check_funcall_missing(ec
, klass
, recv
, mid
, argc
, argv
,
716 respond
, Qundef
, kw_splat
);
717 (*hook
)(ret
!= Qundef
, recv
, mid
, argc
, argv
, arg
);
721 (*hook
)(TRUE
, recv
, mid
, argc
, argv
, arg
);
722 return rb_vm_call_kw(ec
, recv
, mid
, argc
, argv
, me
, kw_splat
);
726 rb_check_funcall_with_hook(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
,
727 rb_check_funcall_hook
*hook
, VALUE arg
)
729 return rb_check_funcall_with_hook_kw(recv
, mid
, argc
, argv
, hook
, arg
, RB_NO_KEYWORDS
);
733 rb_type_str(enum ruby_value_type type
)
735 #define type_case(t) t: return #t
737 case type_case(T_NONE
);
738 case type_case(T_OBJECT
);
739 case type_case(T_CLASS
);
740 case type_case(T_MODULE
);
741 case type_case(T_FLOAT
);
742 case type_case(T_STRING
);
743 case type_case(T_REGEXP
);
744 case type_case(T_ARRAY
);
745 case type_case(T_HASH
);
746 case type_case(T_STRUCT
);
747 case type_case(T_BIGNUM
);
748 case type_case(T_FILE
);
749 case type_case(T_DATA
);
750 case type_case(T_MATCH
);
751 case type_case(T_COMPLEX
);
752 case type_case(T_RATIONAL
);
753 case type_case(T_NIL
);
754 case type_case(T_TRUE
);
755 case type_case(T_FALSE
);
756 case type_case(T_SYMBOL
);
757 case type_case(T_FIXNUM
);
758 case type_case(T_IMEMO
);
759 case type_case(T_UNDEF
);
760 case type_case(T_NODE
);
761 case type_case(T_ICLASS
);
762 case type_case(T_ZOMBIE
);
763 case type_case(T_MOVED
);
771 uncallable_object(VALUE recv
, ID mid
)
776 VALUE mname
= rb_id2str(mid
);
778 if (SPECIAL_CONST_P(recv
)) {
779 rb_raise(rb_eNotImpError
,
780 "method `%"PRIsVALUE
"' called on unexpected immediate object (%p)",
781 mname
, (void *)recv
);
783 else if ((flags
= RBASIC(recv
)->flags
) == 0) {
784 rb_raise(rb_eNotImpError
,
785 "method `%"PRIsVALUE
"' called on terminated object (%p)",
786 mname
, (void *)recv
);
788 else if (!(typestr
= rb_type_str(type
= BUILTIN_TYPE(recv
)))) {
789 rb_raise(rb_eNotImpError
,
790 "method `%"PRIsVALUE
"' called on broken T_?""?""?(0x%02x) object"
791 " (%p flags=0x%"PRIxVALUE
")",
792 mname
, type
, (void *)recv
, flags
);
794 else if (T_OBJECT
<= type
&& type
< T_NIL
) {
795 rb_raise(rb_eNotImpError
,
796 "method `%"PRIsVALUE
"' called on hidden %s object"
797 " (%p flags=0x%"PRIxVALUE
")",
798 mname
, typestr
, (void *)recv
, flags
);
801 rb_raise(rb_eNotImpError
,
802 "method `%"PRIsVALUE
"' called on unexpected %s object"
803 " (%p flags=0x%"PRIxVALUE
")",
804 mname
, typestr
, (void *)recv
, flags
);
808 static inline const rb_callable_method_entry_t
*
809 rb_search_method_entry(VALUE recv
, ID mid
)
811 VALUE klass
= CLASS_OF(recv
);
813 if (!klass
) uncallable_object(recv
, mid
);
814 return rb_callable_method_entry(klass
, mid
);
817 static inline enum method_missing_reason
818 rb_method_call_status(rb_execution_context_t
*ec
, const rb_callable_method_entry_t
*me
, call_type scope
, VALUE self
)
820 if (UNLIKELY(UNDEFINED_METHOD_ENTRY_P(me
))) {
823 else if (UNLIKELY(me
->def
->type
== VM_METHOD_TYPE_REFINED
)) {
824 me
= rb_resolve_refined_method_callable(Qnil
, me
);
825 if (UNDEFINED_METHOD_ENTRY_P(me
)) goto undefined
;
828 rb_method_visibility_t visi
= METHOD_ENTRY_VISI(me
);
830 /* receiver specified form for private method */
831 if (UNLIKELY(visi
!= METHOD_VISI_PUBLIC
)) {
832 if (me
->def
->original_id
== idMethodMissing
) {
835 else if (visi
== METHOD_VISI_PRIVATE
&&
836 scope
== CALL_PUBLIC
) {
837 return MISSING_PRIVATE
;
839 /* self must be kind of a specified form for protected method */
840 else if (visi
== METHOD_VISI_PROTECTED
&&
841 scope
== CALL_PUBLIC
) {
843 VALUE defined_class
= me
->owner
;
844 if (RB_TYPE_P(defined_class
, T_ICLASS
)) {
845 defined_class
= RBASIC(defined_class
)->klass
;
848 if (self
== Qundef
|| !rb_obj_is_kind_of(self
, defined_class
)) {
849 return MISSING_PROTECTED
;
857 return scope
== CALL_VCALL
? MISSING_VCALL
: MISSING_NOENTRY
;
863 * calls the specified method.
865 * This function is called by functions in rb_call* family.
866 * \param recv receiver
867 * \param mid an ID that represents the name of the method
868 * \param argc the number of method arguments
869 * \param argv a pointer to an array of method arguments
873 rb_call(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
, call_type scope
)
875 rb_execution_context_t
*ec
= GET_EC();
876 return rb_call0(ec
, recv
, mid
, argc
, argv
, scope
, ec
->cfp
->self
);
879 NORETURN(static void raise_method_missing(rb_execution_context_t
*ec
, int argc
, const VALUE
*argv
,
880 VALUE obj
, enum method_missing_reason call_status
));
884 * obj.method_missing(symbol [, *args] ) -> result
886 * Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
887 * <i>symbol</i> is the symbol for the method called, and <i>args</i>
888 * are any arguments that were passed to it. By default, the interpreter
889 * raises an error when this method is called. However, it is possible
890 * to override the method to provide more dynamic behavior.
891 * If it is decided that a particular method should not be handled, then
892 * <i>super</i> should be called, so that ancestors can pick up the
894 * The example below creates
895 * a class <code>Roman</code>, which responds to methods with names
896 * consisting of roman numerals, returning the corresponding integer
900 * def roman_to_int(str)
904 * def method_missing(symbol, *args)
905 * str = symbol.id2name
909 * super(symbol, *args)
918 * r.foo #=> NoMethodError
922 rb_method_missing(int argc
, const VALUE
*argv
, VALUE obj
)
924 rb_execution_context_t
*ec
= GET_EC();
925 raise_method_missing(ec
, argc
, argv
, obj
, ec
->method_missing_reason
);
926 UNREACHABLE_RETURN(Qnil
);
929 MJIT_FUNC_EXPORTED VALUE
930 rb_make_no_method_exception(VALUE exc
, VALUE format
, VALUE obj
,
931 int argc
, const VALUE
*argv
, int priv
)
933 VALUE name
= argv
[0];
936 format
= rb_fstring_lit("undefined method `%s' for %s%s%s");
938 if (exc
== rb_eNoMethodError
) {
939 VALUE args
= rb_ary_new4(argc
- 1, argv
+ 1);
940 return rb_nomethod_err_new(format
, obj
, name
, args
, priv
);
943 return rb_name_err_new(format
, obj
, name
);
947 #endif /* #ifndef MJIT_HEADER */
950 raise_method_missing(rb_execution_context_t
*ec
, int argc
, const VALUE
*argv
, VALUE obj
,
951 enum method_missing_reason last_call_status
)
953 VALUE exc
= rb_eNoMethodError
;
956 if (UNLIKELY(argc
== 0)) {
957 rb_raise(rb_eArgError
, "no method name given");
959 else if (UNLIKELY(!SYMBOL_P(argv
[0]))) {
960 const VALUE e
= rb_eArgError
; /* TODO: TypeError? */
961 rb_raise(e
, "method name must be a Symbol but %"PRIsVALUE
" is given",
962 rb_obj_class(argv
[0]));
967 if (last_call_status
& MISSING_PRIVATE
) {
968 format
= rb_fstring_lit("private method `%s' called for %s%s%s");
970 else if (last_call_status
& MISSING_PROTECTED
) {
971 format
= rb_fstring_lit("protected method `%s' called for %s%s%s");
973 else if (last_call_status
& MISSING_VCALL
) {
974 format
= rb_fstring_lit("undefined local variable or method `%s' for %s%s%s");
977 else if (last_call_status
& MISSING_SUPER
) {
978 format
= rb_fstring_lit("super: no superclass method `%s' for %s%s%s");
982 exc
= rb_make_no_method_exception(exc
, format
, obj
, argc
, argv
,
983 last_call_status
& (MISSING_FCALL
|MISSING_VCALL
));
984 if (!(last_call_status
& MISSING_MISSING
)) {
985 rb_vm_pop_cfunc_frame();
992 vm_raise_method_missing(rb_execution_context_t
*ec
, int argc
, const VALUE
*argv
,
993 VALUE obj
, int call_status
)
995 vm_passed_block_handler_set(ec
, VM_BLOCK_HANDLER_NONE
);
996 raise_method_missing(ec
, argc
, argv
, obj
, call_status
| MISSING_MISSING
);
1000 method_missing(rb_execution_context_t
*ec
, VALUE obj
, ID id
, int argc
, const VALUE
*argv
, enum method_missing_reason call_status
, int kw_splat
)
1002 VALUE
*nargv
, result
, work
, klass
;
1003 VALUE block_handler
= vm_passed_block_handler(ec
);
1004 const rb_callable_method_entry_t
*me
;
1006 ec
->method_missing_reason
= call_status
;
1008 if (id
== idMethodMissing
) {
1012 nargv
= ALLOCV_N(VALUE
, work
, argc
+ 1);
1013 nargv
[0] = ID2SYM(id
);
1016 static const VALUE buf
= Qfalse
;
1017 VM_ASSERT(argc
== 0);
1021 MEMCPY(nargv
+ 1, argv
, VALUE
, argc
);
1025 klass
= CLASS_OF(obj
);
1026 if (!klass
) goto missing
;
1027 me
= rb_callable_method_entry(klass
, idMethodMissing
);
1028 if (!me
|| METHOD_ENTRY_BASIC(me
)) goto missing
;
1029 vm_passed_block_handler_set(ec
, block_handler
);
1030 result
= rb_vm_call_kw(ec
, obj
, idMethodMissing
, argc
, argv
, me
, kw_splat
);
1031 if (work
) ALLOCV_END(work
);
1034 raise_method_missing(ec
, argc
, argv
, obj
, call_status
| MISSING_MISSING
);
1035 UNREACHABLE_RETURN(Qundef
);
1041 rb_funcallv_scope(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
, call_type scope
)
1043 rb_execution_context_t
*ec
= GET_EC();
1044 const struct rb_callcache
*cc
= gccct_method_search(ec
, recv
, mid
, argc
);
1045 VALUE self
= ec
->cfp
->self
;
1048 LIKELY(rb_method_call_status(ec
, vm_cc_cme(cc
), scope
, self
) == MISSING_NONE
)) {
1050 return vm_call0_cc(ec
, recv
, mid
, argc
, argv
, cc
, false);
1053 return rb_call0(ec
, recv
, mid
, argc
, argv
, scope
, self
);
1061 rb_funcallv(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
)
1063 VM_ASSERT(ruby_thread_has_gvl_p());
1065 return rb_funcallv_scope(recv
, mid
, argc
, argv
, CALL_FCALL
);
1069 rb_funcallv_kw(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
, int kw_splat
)
1071 VM_ASSERT(ruby_thread_has_gvl_p());
1073 return rb_call(recv
, mid
, argc
, argv
, kw_splat
? CALL_FCALL_KW
: CALL_FCALL
);
1077 rb_apply(VALUE recv
, ID mid
, VALUE args
)
1082 argc
= RARRAY_LENINT(args
);
1083 if (argc
>= 0x100) {
1084 args
= rb_ary_subseq(args
, 0, argc
);
1085 RBASIC_CLEAR_CLASS(args
);
1087 ret
= rb_call(recv
, mid
, argc
, RARRAY_CONST_PTR(args
), CALL_FCALL
);
1091 argv
= ALLOCA_N(VALUE
, argc
);
1092 MEMCPY(argv
, RARRAY_CONST_PTR_TRANSIENT(args
), VALUE
, argc
);
1094 return rb_funcallv(recv
, mid
, argc
, argv
);
1102 rb_funcall(VALUE recv
, ID mid
, int n
, ...)
1112 argv
= ALLOCA_N(VALUE
, n
);
1114 for (i
= 0; i
< n
; i
++) {
1115 argv
[i
] = va_arg(ar
, VALUE
);
1122 return rb_funcallv(recv
, mid
, n
, argv
);
1126 * Calls a method only if it is the basic method of `ancestor`
1127 * otherwise returns Qundef;
1128 * \param recv receiver of the method
1129 * \param mid an ID that represents the name of the method
1130 * \param ancestor the Class that defined the basic method
1131 * \param argc the number of arguments
1132 * \param argv pointer to an array of method arguments
1133 * \param kw_splat bool
1136 rb_check_funcall_basic_kw(VALUE recv
, ID mid
, VALUE ancestor
, int argc
, const VALUE
*argv
, int kw_splat
)
1138 const rb_callable_method_entry_t
*cme
;
1139 rb_execution_context_t
*ec
;
1140 VALUE klass
= CLASS_OF(recv
);
1141 if (!klass
) return Qundef
; /* hidden object */
1143 cme
= rb_callable_method_entry(klass
, mid
);
1144 if (cme
&& METHOD_ENTRY_BASIC(cme
) && RBASIC_CLASS(cme
->defined_class
) == ancestor
) {
1146 return rb_vm_call0(ec
, recv
, mid
, argc
, argv
, cme
, kw_splat
);
1153 rb_funcallv_public(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
)
1155 return rb_funcallv_scope(recv
, mid
, argc
, argv
, CALL_PUBLIC
);
1159 rb_funcallv_public_kw(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
, int kw_splat
)
1161 return rb_call(recv
, mid
, argc
, argv
, kw_splat
? CALL_PUBLIC_KW
: CALL_PUBLIC
);
1165 rb_funcall_passing_block(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
)
1167 PASS_PASSED_BLOCK_HANDLER();
1168 return rb_funcallv_public(recv
, mid
, argc
, argv
);
1172 rb_funcall_passing_block_kw(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
, int kw_splat
)
1174 PASS_PASSED_BLOCK_HANDLER();
1175 return rb_call(recv
, mid
, argc
, argv
, kw_splat
? CALL_PUBLIC_KW
: CALL_PUBLIC
);
1179 rb_funcall_with_block(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
, VALUE passed_procval
)
1181 if (!NIL_P(passed_procval
)) {
1182 vm_passed_block_handler_set(GET_EC(), passed_procval
);
1185 return rb_funcallv_public(recv
, mid
, argc
, argv
);
1189 rb_funcall_with_block_kw(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
, VALUE passed_procval
, int kw_splat
)
1191 if (!NIL_P(passed_procval
)) {
1192 vm_passed_block_handler_set(GET_EC(), passed_procval
);
1195 return rb_call(recv
, mid
, argc
, argv
, kw_splat
? CALL_PUBLIC_KW
: CALL_PUBLIC
);
1199 current_vm_stack_arg(const rb_execution_context_t
*ec
, const VALUE
*argv
)
1201 rb_control_frame_t
*prev_cfp
= RUBY_VM_PREVIOUS_CONTROL_FRAME(ec
->cfp
);
1202 if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec
, prev_cfp
)) return NULL
;
1203 if (prev_cfp
->sp
+ 1 != argv
) return NULL
;
1204 return prev_cfp
->sp
+ 1;
1208 send_internal(int argc
, const VALUE
*argv
, VALUE recv
, call_type scope
)
1213 VALUE ret
, vargv
= 0;
1214 rb_execution_context_t
*ec
= GET_EC();
1215 int public = scope
== CALL_PUBLIC
|| scope
== CALL_PUBLIC_KW
;
1221 self
= RUBY_VM_PREVIOUS_CONTROL_FRAME(ec
->cfp
)->self
;
1225 rb_raise(rb_eArgError
, "no method name given");
1230 id
= rb_check_id(&vid
);
1232 if (rb_method_basic_definition_p(CLASS_OF(recv
), idMethodMissing
)) {
1233 VALUE exc
= rb_make_no_method_exception(rb_eNoMethodError
, 0,
1238 if (!SYMBOL_P(*argv
)) {
1239 VALUE
*tmp_argv
= current_vm_stack_arg(ec
, argv
);
1240 vid
= rb_str_intern(vid
);
1244 else if (argc
> 1) {
1245 tmp_argv
= ALLOCV_N(VALUE
, vargv
, argc
);
1247 MEMCPY(tmp_argv
+1, argv
+1, VALUE
, argc
-1);
1254 id
= idMethodMissing
;
1255 ec
->method_missing_reason
= MISSING_NOENTRY
;
1260 PASS_PASSED_BLOCK_HANDLER_EC(ec
);
1261 ret
= rb_call0(ec
, recv
, id
, argc
, argv
, scope
, self
);
1267 send_internal_kw(int argc
, const VALUE
*argv
, VALUE recv
, call_type scope
)
1269 if (rb_keyword_given_p()) {
1272 scope
= CALL_PUBLIC_KW
;
1275 scope
= CALL_FCALL_KW
;
1281 return send_internal(argc
, argv
, recv
, scope
);
1286 * foo.send(symbol [, args...]) -> obj
1287 * foo.__send__(symbol [, args...]) -> obj
1288 * foo.send(string [, args...]) -> obj
1289 * foo.__send__(string [, args...]) -> obj
1291 * Invokes the method identified by _symbol_, passing it any
1292 * arguments specified.
1293 * When the method is identified by a string, the string is converted
1296 * BasicObject implements +__send__+, Kernel implements +send+.
1297 * <code>__send__</code> is safer than +send+
1298 * when _obj_ has the same method name like <code>Socket</code>.
1299 * See also <code>public_send</code>.
1303 * "Hello " + args.join(' ')
1307 * k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
1311 rb_f_send(int argc
, VALUE
*argv
, VALUE recv
)
1313 return send_internal_kw(argc
, argv
, recv
, CALL_FCALL
);
1318 * obj.public_send(symbol [, args...]) -> obj
1319 * obj.public_send(string [, args...]) -> obj
1321 * Invokes the method identified by _symbol_, passing it any
1322 * arguments specified. Unlike send, public_send calls public
1324 * When the method is identified by a string, the string is converted
1327 * 1.public_send(:puts, "hello") # causes NoMethodError
1331 rb_f_public_send(int argc
, VALUE
*argv
, VALUE recv
)
1333 return send_internal_kw(argc
, argv
, recv
, CALL_PUBLIC
);
1339 rb_yield_0_kw(int argc
, const VALUE
* argv
, int kw_splat
)
1341 return vm_yield(GET_EC(), argc
, argv
, kw_splat
);
1345 rb_yield_0(int argc
, const VALUE
* argv
)
1347 return vm_yield(GET_EC(), argc
, argv
, RB_NO_KEYWORDS
);
1351 rb_yield_1(VALUE val
)
1353 return rb_yield_0(1, &val
);
1359 if (val
== Qundef
) {
1360 return rb_yield_0(0, NULL
);
1363 return rb_yield_0(1, &val
);
1367 #undef rb_yield_values
1369 rb_yield_values(int n
, ...)
1372 return rb_yield_0(0, 0);
1378 argv
= ALLOCA_N(VALUE
, n
);
1381 for (i
=0; i
<n
; i
++) {
1382 argv
[i
] = va_arg(args
, VALUE
);
1386 return rb_yield_0(n
, argv
);
1391 rb_yield_values2(int argc
, const VALUE
*argv
)
1393 return rb_yield_0(argc
, argv
);
1397 rb_yield_values_kw(int argc
, const VALUE
*argv
, int kw_splat
)
1399 return rb_yield_0_kw(argc
, argv
, kw_splat
);
1403 rb_yield_splat(VALUE values
)
1405 VALUE tmp
= rb_check_array_type(values
);
1408 rb_raise(rb_eArgError
, "not an array");
1410 v
= rb_yield_0(RARRAY_LENINT(tmp
), RARRAY_CONST_PTR(tmp
));
1416 rb_yield_splat_kw(VALUE values
, int kw_splat
)
1418 VALUE tmp
= rb_check_array_type(values
);
1421 rb_raise(rb_eArgError
, "not an array");
1423 v
= rb_yield_0_kw(RARRAY_LENINT(tmp
), RARRAY_CONST_PTR(tmp
), kw_splat
);
1429 rb_yield_force_blockarg(VALUE values
)
1431 return vm_yield_force_blockarg(GET_EC(), values
);
1435 rb_yield_block(RB_BLOCK_CALL_FUNC_ARGLIST(val
, arg
))
1437 return vm_yield_with_block(GET_EC(), argc
, argv
,
1438 NIL_P(blockarg
) ? VM_BLOCK_HANDLER_NONE
: blockarg
,
1439 rb_keyword_given_p());
1452 loop_stop(VALUE dummy
, VALUE exc
)
1454 return rb_attr_get(exc
, id_result
);
1458 rb_f_loop_size(VALUE self
, VALUE args
, VALUE eobj
)
1460 return DBL2NUM(HUGE_VAL
);
1466 * loop -> an_enumerator
1468 * Repeatedly executes the block.
1470 * If no block is given, an enumerator is returned instead.
1475 * break if !line or line =~ /^qQ/
1479 * StopIteration raised in the block breaks the loop. In this case,
1480 * loop returns the "result" value stored in the exception.
1482 * enum = Enumerator.new { |y|
1494 rb_f_loop(VALUE self
)
1496 RETURN_SIZED_ENUMERATOR(self
, 0, 0, rb_f_loop_size
);
1497 return rb_rescue2(loop_i
, (VALUE
)0, loop_stop
, (VALUE
)0, rb_eStopIteration
, (VALUE
)0);
1502 vm_frametype_name(const rb_control_frame_t
*cfp
);
1506 rb_iterate0(VALUE (* it_proc
) (VALUE
), VALUE data1
,
1507 const struct vm_ifunc
*const ifunc
,
1508 rb_execution_context_t
*ec
)
1510 enum ruby_tag_type state
;
1511 volatile VALUE retval
= Qnil
;
1512 rb_control_frame_t
*const cfp
= ec
->cfp
;
1515 state
= EC_EXEC_TAG();
1519 VALUE block_handler
;
1522 struct rb_captured_block
*captured
= VM_CFP_TO_CAPTURED_BLOCK(cfp
);
1523 captured
->code
.ifunc
= ifunc
;
1524 block_handler
= VM_BH_FROM_IFUNC_BLOCK(captured
);
1527 block_handler
= VM_CF_BLOCK_HANDLER(cfp
);
1529 vm_passed_block_handler_set(ec
, block_handler
);
1531 retval
= (*it_proc
) (data1
);
1533 else if (state
== TAG_BREAK
|| state
== TAG_RETRY
) {
1534 const struct vm_throw_data
*const err
= (struct vm_throw_data
*)ec
->errinfo
;
1535 const rb_control_frame_t
*const escape_cfp
= THROW_DATA_CATCH_FRAME(err
);
1537 if (cfp
== escape_cfp
) {
1538 rb_vm_rewind_cfp(ec
, cfp
);
1541 ec
->tag
->state
= TAG_NONE
;
1544 if (state
== TAG_RETRY
) goto iter_retry
;
1545 retval
= THROW_DATA_VAL(err
);
1548 SDR(); fprintf(stderr
, "%p, %p\n", (void *)cfp
, (void *)escape_cfp
);
1554 EC_JUMP_TAG(ec
, state
);
1560 rb_iterate_internal(VALUE (* it_proc
)(VALUE
), VALUE data1
,
1561 rb_block_call_func_t bl_proc
, VALUE data2
)
1563 return rb_iterate0(it_proc
, data1
,
1564 bl_proc
? rb_vm_ifunc_proc_new(bl_proc
, (void *)data2
) : 0,
1569 rb_iterate(VALUE (* it_proc
)(VALUE
), VALUE data1
,
1570 rb_block_call_func_t bl_proc
, VALUE data2
)
1572 return rb_iterate_internal(it_proc
, data1
, bl_proc
, data2
);
1575 struct iter_method_arg
{
1584 iterate_method(VALUE obj
)
1586 const struct iter_method_arg
* arg
=
1587 (struct iter_method_arg
*) obj
;
1589 return rb_call(arg
->obj
, arg
->mid
, arg
->argc
, arg
->argv
, arg
->kw_splat
? CALL_FCALL_KW
: CALL_FCALL
);
1592 VALUE
rb_block_call_kw(VALUE obj
, ID mid
, int argc
, const VALUE
* argv
, rb_block_call_func_t bl_proc
, VALUE data2
, int kw_splat
);
1595 rb_block_call(VALUE obj
, ID mid
, int argc
, const VALUE
* argv
,
1596 rb_block_call_func_t bl_proc
, VALUE data2
)
1598 return rb_block_call_kw(obj
, mid
, argc
, argv
, bl_proc
, data2
, RB_NO_KEYWORDS
);
1602 rb_block_call_kw(VALUE obj
, ID mid
, int argc
, const VALUE
* argv
,
1603 rb_block_call_func_t bl_proc
, VALUE data2
, int kw_splat
)
1605 struct iter_method_arg arg
;
1611 arg
.kw_splat
= kw_splat
;
1612 return rb_iterate_internal(iterate_method
, (VALUE
)&arg
, bl_proc
, data2
);
1616 rb_lambda_call(VALUE obj
, ID mid
, int argc
, const VALUE
*argv
,
1617 rb_block_call_func_t bl_proc
, int min_argc
, int max_argc
,
1620 struct iter_method_arg arg
;
1621 struct vm_ifunc
*block
;
1623 if (!bl_proc
) rb_raise(rb_eArgError
, "NULL lambda function");
1629 block
= rb_vm_ifunc_new(bl_proc
, (void *)data2
, min_argc
, max_argc
);
1630 return rb_iterate0(iterate_method
, (VALUE
)&arg
, block
, GET_EC());
1634 iterate_check_method(VALUE obj
)
1636 const struct iter_method_arg
* arg
=
1637 (struct iter_method_arg
*) obj
;
1639 return rb_check_funcall(arg
->obj
, arg
->mid
, arg
->argc
, arg
->argv
);
1643 rb_check_block_call(VALUE obj
, ID mid
, int argc
, const VALUE
*argv
,
1644 rb_block_call_func_t bl_proc
, VALUE data2
)
1646 struct iter_method_arg arg
;
1653 return rb_iterate_internal(iterate_check_method
, (VALUE
)&arg
, bl_proc
, data2
);
1659 return rb_call(obj
, idEach
, 0, 0, CALL_FCALL
);
1662 void rb_parser_warn_location(VALUE
, int);
1664 static VALUE eval_default_path
;
1666 static const rb_iseq_t
*
1667 eval_make_iseq(VALUE src
, VALUE fname
, int line
, const rb_binding_t
*bind
,
1668 const struct rb_block
*base_block
)
1670 const VALUE parser
= rb_parser_new();
1671 const rb_iseq_t
*const parent
= vm_block_iseq(base_block
);
1672 rb_iseq_t
*iseq
= NULL
;
1674 int isolated_depth
= 0;
1677 const VALUE
*ep
= vm_block_ep(base_block
);
1680 if (VM_ENV_FLAGS(ep
, VM_ENV_FLAG_ISOLATED
)) {
1681 isolated_depth
= depth
;
1684 else if (VM_ENV_LOCAL_P(ep
)) {
1687 ep
= VM_ENV_PREV_EP(ep
);
1693 fname
= rb_source_location(&line
);
1696 if (fname
!= Qundef
) {
1697 if (!NIL_P(fname
)) fname
= rb_fstring(fname
);
1700 fname
= rb_fstring_lit("(eval)");
1701 if (!eval_default_path
) {
1702 eval_default_path
= rb_fstring_lit("(eval)");
1703 rb_gc_register_mark_object(eval_default_path
);
1705 fname
= eval_default_path
;
1708 rb_parser_set_context(parser
, parent
, FALSE
);
1709 ast
= rb_parser_compile_string_path(parser
, fname
, src
, line
);
1710 if (ast
->body
.root
) {
1711 iseq
= rb_iseq_new_eval(&ast
->body
,
1712 parent
->body
->location
.label
,
1713 fname
, Qnil
, INT2FIX(line
),
1714 parent
, isolated_depth
);
1716 rb_ast_dispose(ast
);
1719 if (0 && iseq
) { /* for debug */
1720 VALUE disasm
= rb_iseq_disasm(iseq
);
1721 printf("%s\n", StringValuePtr(disasm
));
1724 rb_exec_event_hook_script_compiled(GET_EC(), iseq
, src
);
1731 eval_string_with_cref(VALUE self
, VALUE src
, rb_cref_t
*cref
, VALUE file
, int line
)
1733 rb_execution_context_t
*ec
= GET_EC();
1734 struct rb_block block
;
1735 const rb_iseq_t
*iseq
;
1736 rb_control_frame_t
*cfp
= rb_vm_get_ruby_level_next_cfp(ec
, ec
->cfp
);
1738 rb_raise(rb_eRuntimeError
, "Can't eval on top of Fiber or Thread");
1741 block
.as
.captured
= *VM_CFP_TO_CAPTURED_BLOCK(cfp
);
1742 block
.as
.captured
.self
= self
;
1743 block
.as
.captured
.code
.iseq
= cfp
->iseq
;
1744 block
.type
= block_type_iseq
;
1746 iseq
= eval_make_iseq(src
, file
, line
, NULL
, &block
);
1748 rb_exc_raise(ec
->errinfo
);
1751 /* TODO: what the code checking? */
1752 if (!cref
&& block
.as
.captured
.code
.val
) {
1753 rb_cref_t
*orig_cref
= vm_get_cref(vm_block_ep(&block
));
1754 cref
= vm_cref_dup(orig_cref
);
1756 vm_set_eval_stack(ec
, iseq
, cref
, &block
);
1759 return vm_exec(ec
, true);
1763 eval_string_with_scope(VALUE scope
, VALUE src
, VALUE file
, int line
)
1765 rb_execution_context_t
*ec
= GET_EC();
1766 rb_binding_t
*bind
= Check_TypedStruct(scope
, &ruby_binding_data_type
);
1767 const rb_iseq_t
*iseq
= eval_make_iseq(src
, file
, line
, bind
, &bind
->block
);
1769 rb_exc_raise(ec
->errinfo
);
1772 vm_set_eval_stack(ec
, iseq
, NULL
, &bind
->block
);
1775 if (iseq
->body
->local_table_size
> 0) {
1776 vm_bind_update_env(scope
, bind
, vm_make_env_object(ec
, ec
->cfp
));
1780 return vm_exec(ec
, true);
1785 * eval(string [, binding [, filename [,lineno]]]) -> obj
1787 * Evaluates the Ruby expression(s) in <em>string</em>. If
1788 * <em>binding</em> is given, which must be a Binding object, the
1789 * evaluation is performed in its context. If the optional
1790 * <em>filename</em> and <em>lineno</em> parameters are present, they
1791 * will be used when reporting syntax errors.
1793 * def get_binding(str)
1797 * eval "str + ' Fred'" #=> "hello Fred"
1798 * eval "str + ' Fred'", get_binding("bye") #=> "bye Fred"
1802 rb_f_eval(int argc
, const VALUE
*argv
, VALUE self
)
1804 VALUE src
, scope
, vfile
, vline
;
1805 VALUE file
= Qundef
;
1808 rb_scan_args(argc
, argv
, "13", &src
, &scope
, &vfile
, &vline
);
1809 SafeStringValue(src
);
1814 line
= NUM2INT(vline
);
1821 return eval_string_with_cref(self
, src
, NULL
, file
, line
);
1823 return eval_string_with_scope(scope
, src
, file
, line
);
1826 /** @note This function name is not stable. */
1828 ruby_eval_string_from_file(const char *str
, const char *filename
)
1830 VALUE file
= filename
? rb_str_new_cstr(filename
) : 0;
1831 return eval_string_with_cref(rb_vm_top_self(), rb_str_new2(str
), NULL
, file
, 1);
1835 rb_eval_string(const char *str
)
1837 return ruby_eval_string_from_file(str
, "eval");
1841 eval_string_protect(VALUE str
)
1843 return rb_eval_string((char *)str
);
1847 rb_eval_string_protect(const char *str
, int *pstate
)
1849 return rb_protect(eval_string_protect
, (VALUE
)str
, pstate
);
1852 struct eval_string_wrap_arg
{
1859 eval_string_wrap_protect(VALUE data
)
1861 const struct eval_string_wrap_arg
*const arg
= (struct eval_string_wrap_arg
*)data
;
1862 rb_cref_t
*cref
= rb_vm_cref_new_toplevel();
1863 cref
->klass_or_self
= arg
->klass
;
1864 return eval_string_with_cref(arg
->top_self
, rb_str_new_cstr(arg
->str
), cref
, rb_str_new_cstr("eval"), 1);
1868 rb_eval_string_wrap(const char *str
, int *pstate
)
1871 rb_thread_t
*th
= GET_THREAD();
1872 VALUE self
= th
->top_self
;
1873 VALUE wrapper
= th
->top_wrapper
;
1875 struct eval_string_wrap_arg data
;
1877 th
->top_wrapper
= rb_module_new();
1878 th
->top_self
= rb_obj_clone(rb_vm_top_self());
1879 rb_extend_object(th
->top_self
, th
->top_wrapper
);
1881 data
.top_self
= th
->top_self
;
1882 data
.klass
= th
->top_wrapper
;
1885 val
= rb_protect(eval_string_wrap_protect
, (VALUE
)&data
, &state
);
1887 th
->top_self
= self
;
1888 th
->top_wrapper
= wrapper
;
1893 else if (state
!= TAG_NONE
) {
1894 EC_JUMP_TAG(th
->ec
, state
);
1900 rb_eval_cmd_kw(VALUE cmd
, VALUE arg
, int kw_splat
)
1902 enum ruby_tag_type state
;
1903 volatile VALUE val
= Qnil
; /* OK */
1904 rb_execution_context_t
* volatile ec
= GET_EC();
1907 if ((state
= EC_EXEC_TAG()) == TAG_NONE
) {
1908 if (!RB_TYPE_P(cmd
, T_STRING
)) {
1909 val
= rb_funcallv_kw(cmd
, idCall
, RARRAY_LENINT(arg
),
1910 RARRAY_CONST_PTR(arg
), kw_splat
);
1913 val
= eval_string_with_cref(rb_vm_top_self(), cmd
, NULL
, 0, 0);
1918 if (state
) EC_JUMP_TAG(ec
, state
);
1922 /* block eval under the class/module context */
1925 yield_under(VALUE self
, int singleton
, int argc
, const VALUE
*argv
, int kw_splat
)
1927 rb_execution_context_t
*ec
= GET_EC();
1928 rb_control_frame_t
*cfp
= ec
->cfp
;
1929 VALUE block_handler
= VM_CF_BLOCK_HANDLER(cfp
);
1930 VALUE new_block_handler
= 0;
1931 const struct rb_captured_block
*captured
= NULL
;
1932 struct rb_captured_block new_captured
;
1933 const VALUE
*ep
= NULL
;
1935 int is_lambda
= FALSE
;
1937 if (block_handler
!= VM_BLOCK_HANDLER_NONE
) {
1939 switch (vm_block_handler_type(block_handler
)) {
1940 case block_handler_type_iseq
:
1941 captured
= VM_BH_TO_CAPT_BLOCK(block_handler
);
1942 new_captured
= *captured
;
1943 new_block_handler
= VM_BH_FROM_ISEQ_BLOCK(&new_captured
);
1945 case block_handler_type_ifunc
:
1946 captured
= VM_BH_TO_CAPT_BLOCK(block_handler
);
1947 new_captured
= *captured
;
1948 new_block_handler
= VM_BH_FROM_IFUNC_BLOCK(&new_captured
);
1950 case block_handler_type_proc
:
1951 is_lambda
= rb_proc_lambda_p(block_handler
) != Qfalse
;
1952 block_handler
= vm_proc_to_block_handler(VM_BH_TO_PROC(block_handler
));
1954 case block_handler_type_symbol
:
1955 return rb_sym_proc_call(SYM2ID(VM_BH_TO_SYMBOL(block_handler
)),
1956 argc
, argv
, kw_splat
,
1957 VM_BLOCK_HANDLER_NONE
);
1960 new_captured
.self
= self
;
1963 VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(ec
->cfp
)[VM_ENV_DATA_INDEX_SPECVAL
], new_block_handler
);
1966 VM_ASSERT(singleton
|| RB_TYPE_P(self
, T_MODULE
) || RB_TYPE_P(self
, T_CLASS
));
1967 cref
= vm_cref_push(ec
, self
, ep
, TRUE
, singleton
);
1969 return vm_yield_with_cref(ec
, argc
, argv
, kw_splat
, cref
, is_lambda
);
1973 rb_yield_refine_block(VALUE refinement
, VALUE refinements
)
1975 rb_execution_context_t
*ec
= GET_EC();
1976 VALUE block_handler
= VM_CF_BLOCK_HANDLER(ec
->cfp
);
1978 if (vm_block_handler_type(block_handler
) != block_handler_type_iseq
) {
1979 rb_bug("rb_yield_refine_block: an iseq block is required");
1982 const struct rb_captured_block
*captured
= VM_BH_TO_ISEQ_BLOCK(block_handler
);
1983 struct rb_captured_block new_captured
= *captured
;
1984 VALUE new_block_handler
= VM_BH_FROM_ISEQ_BLOCK(&new_captured
);
1985 const VALUE
*ep
= captured
->ep
;
1986 rb_cref_t
*cref
= vm_cref_push(ec
, refinement
, ep
, TRUE
, FALSE
);
1987 CREF_REFINEMENTS_SET(cref
, refinements
);
1988 VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(ec
->cfp
)[VM_ENV_DATA_INDEX_SPECVAL
], new_block_handler
);
1989 new_captured
.self
= refinement
;
1990 return vm_yield_with_cref(ec
, 0, NULL
, RB_NO_KEYWORDS
, cref
, FALSE
);
1994 /* string eval under the class/module context */
1996 eval_under(VALUE self
, int singleton
, VALUE src
, VALUE file
, int line
)
1998 rb_cref_t
*cref
= vm_cref_push(GET_EC(), self
, NULL
, FALSE
, singleton
);
1999 SafeStringValue(src
);
2001 return eval_string_with_cref(self
, src
, cref
, file
, line
);
2005 specific_eval(int argc
, const VALUE
*argv
, VALUE self
, int singleton
, int kw_splat
)
2007 if (rb_block_given_p()) {
2008 rb_check_arity(argc
, 0, 0);
2009 return yield_under(self
, singleton
, 1, &self
, kw_splat
);
2012 VALUE file
= Qundef
;
2016 rb_check_arity(argc
, 1, 3);
2018 SafeStringValue(code
);
2020 line
= NUM2INT(argv
[2]);
2023 if (!NIL_P(file
)) StringValue(file
);
2025 return eval_under(self
, singleton
, code
, file
, line
);
2031 * obj.instance_eval(string [, filename [, lineno]] ) -> obj
2032 * obj.instance_eval {|obj| block } -> obj
2034 * Evaluates a string containing Ruby source code, or the given block,
2035 * within the context of the receiver (_obj_). In order to set the
2036 * context, the variable +self+ is set to _obj_ while
2037 * the code is executing, giving the code access to _obj_'s
2038 * instance variables and private methods.
2040 * When <code>instance_eval</code> is given a block, _obj_ is also
2041 * passed in as the block's only argument.
2043 * When <code>instance_eval</code> is given a +String+, the optional
2044 * second and third parameters supply a filename and starting line number
2045 * that are used when reporting compilation errors.
2047 * class KlassWithSecret
2053 * "Ssssh! The secret is #{@secret}."
2056 * k = KlassWithSecret.new
2057 * k.instance_eval { @secret } #=> 99
2058 * k.instance_eval { the_secret } #=> "Ssssh! The secret is 99."
2059 * k.instance_eval {|obj| obj == self } #=> true
2063 rb_obj_instance_eval_internal(int argc
, const VALUE
*argv
, VALUE self
)
2065 return specific_eval(argc
, argv
, self
, TRUE
, RB_PASS_CALLED_KEYWORDS
);
2069 rb_obj_instance_eval(int argc
, const VALUE
*argv
, VALUE self
)
2071 return specific_eval(argc
, argv
, self
, TRUE
, RB_NO_KEYWORDS
);
2076 * obj.instance_exec(arg...) {|var...| block } -> obj
2078 * Executes the given block within the context of the receiver
2079 * (_obj_). In order to set the context, the variable +self+ is set
2080 * to _obj_ while the code is executing, giving the code access to
2081 * _obj_'s instance variables. Arguments are passed as block parameters.
2083 * class KlassWithSecret
2088 * k = KlassWithSecret.new
2089 * k.instance_exec(5) {|x| @secret+x } #=> 104
2093 rb_obj_instance_exec_internal(int argc
, const VALUE
*argv
, VALUE self
)
2095 return yield_under(self
, TRUE
, argc
, argv
, RB_PASS_CALLED_KEYWORDS
);
2099 rb_obj_instance_exec(int argc
, const VALUE
*argv
, VALUE self
)
2101 return yield_under(self
, TRUE
, argc
, argv
, RB_NO_KEYWORDS
);
2106 * mod.class_eval(string [, filename [, lineno]]) -> obj
2107 * mod.class_eval {|mod| block } -> obj
2108 * mod.module_eval(string [, filename [, lineno]]) -> obj
2109 * mod.module_eval {|mod| block } -> obj
2111 * Evaluates the string or block in the context of _mod_, except that when
2112 * a block is given, constant/class variable lookup is not affected. This
2113 * can be used to add methods to a class. <code>module_eval</code> returns
2114 * the result of evaluating its argument. The optional _filename_ and
2115 * _lineno_ parameters set the text for error messages.
2119 * a = %q{def hello() "Hello there!" end}
2120 * Thing.module_eval(a)
2121 * puts Thing.new.hello()
2122 * Thing.module_eval("invalid code", "dummy", 123)
2124 * <em>produces:</em>
2127 * dummy:123:in `module_eval': undefined local variable
2128 * or method `code' for Thing:Class
2132 rb_mod_module_eval_internal(int argc
, const VALUE
*argv
, VALUE mod
)
2134 return specific_eval(argc
, argv
, mod
, FALSE
, RB_PASS_CALLED_KEYWORDS
);
2138 rb_mod_module_eval(int argc
, const VALUE
*argv
, VALUE mod
)
2140 return specific_eval(argc
, argv
, mod
, FALSE
, RB_NO_KEYWORDS
);
2145 * mod.module_exec(arg...) {|var...| block } -> obj
2146 * mod.class_exec(arg...) {|var...| block } -> obj
2148 * Evaluates the given block in the context of the class/module.
2149 * The method defined in the block will belong to the receiver.
2150 * Any arguments passed to the method will be passed to the block.
2151 * This can be used if the block needs to access instance variables.
2156 * def hello() "Hello there!" end
2158 * puts Thing.new.hello()
2160 * <em>produces:</em>
2166 rb_mod_module_exec_internal(int argc
, const VALUE
*argv
, VALUE mod
)
2168 return yield_under(mod
, FALSE
, argc
, argv
, RB_PASS_CALLED_KEYWORDS
);
2172 rb_mod_module_exec(int argc
, const VALUE
*argv
, VALUE mod
)
2174 return yield_under(mod
, FALSE
, argc
, argv
, RB_NO_KEYWORDS
);
2178 * Document-class: UncaughtThrowError
2180 * Raised when +throw+ is called with a _tag_ which does not have
2181 * corresponding +catch+ block.
2183 * throw "foo", "bar"
2185 * <em>raises the exception:</em>
2187 * UncaughtThrowError: uncaught throw "foo"
2191 uncaught_throw_init(int argc
, const VALUE
*argv
, VALUE exc
)
2193 rb_check_arity(argc
, 2, UNLIMITED_ARGUMENTS
);
2194 rb_call_super(argc
- 2, argv
+ 2);
2195 rb_ivar_set(exc
, id_tag
, argv
[0]);
2196 rb_ivar_set(exc
, id_value
, argv
[1]);
2202 * uncaught_throw.tag -> obj
2204 * Return the tag object which was called for.
2208 uncaught_throw_tag(VALUE exc
)
2210 return rb_ivar_get(exc
, id_tag
);
2215 * uncaught_throw.value -> obj
2217 * Return the return value which was called for.
2221 uncaught_throw_value(VALUE exc
)
2223 return rb_ivar_get(exc
, id_value
);
2228 * uncaught_throw.to_s -> string
2230 * Returns formatted message with the inspected tag.
2234 uncaught_throw_to_s(VALUE exc
)
2236 VALUE mesg
= rb_attr_get(exc
, id_mesg
);
2237 VALUE tag
= uncaught_throw_tag(exc
);
2238 return rb_str_format(1, &tag
, mesg
);
2243 * throw(tag [, obj])
2245 * Transfers control to the end of the active +catch+ block
2246 * waiting for _tag_. Raises +UncaughtThrowError+ if there
2247 * is no +catch+ block for the _tag_. The optional second
2248 * parameter supplies a return value for the +catch+ block,
2249 * which otherwise defaults to +nil+. For examples, see
2254 rb_f_throw(int argc
, VALUE
*argv
, VALUE _
)
2258 rb_scan_args(argc
, argv
, "11", &tag
, &value
);
2259 rb_throw_obj(tag
, value
);
2260 UNREACHABLE_RETURN(Qnil
);
2264 rb_throw_obj(VALUE tag
, VALUE value
)
2266 rb_execution_context_t
*ec
= GET_EC();
2267 struct rb_vm_tag
*tt
= ec
->tag
;
2270 if (tt
->tag
== tag
) {
2280 desc
[2] = rb_str_new_cstr("uncaught throw %p");
2281 rb_exc_raise(rb_class_new_instance(numberof(desc
), desc
, rb_eUncaughtThrow
));
2284 ec
->errinfo
= (VALUE
)THROW_DATA_NEW(tag
, NULL
, TAG_THROW
);
2285 EC_JUMP_TAG(ec
, TAG_THROW
);
2289 rb_throw(const char *tag
, VALUE val
)
2291 rb_throw_obj(rb_sym_intern_ascii_cstr(tag
), val
);
2295 catch_i(RB_BLOCK_CALL_FUNC_ARGLIST(tag
, _
))
2297 return rb_yield_0(1, &tag
);
2302 * catch([tag]) {|tag| block } -> obj
2304 * +catch+ executes its block. If +throw+ is not called, the block executes
2305 * normally, and +catch+ returns the value of the last expression evaluated.
2307 * catch(1) { 123 } # => 123
2309 * If <code>throw(tag2, val)</code> is called, Ruby searches up its stack for
2310 * a +catch+ block whose +tag+ has the same +object_id+ as _tag2_. When found,
2311 * the block stops executing and returns _val_ (or +nil+ if no second argument
2312 * was given to +throw+).
2314 * catch(1) { throw(1, 456) } # => 456
2315 * catch(1) { throw(1) } # => nil
2317 * When +tag+ is passed as the first argument, +catch+ yields it as the
2318 * parameter of the block.
2320 * catch(1) {|x| x + 2 } # => 3
2322 * When no +tag+ is given, +catch+ yields a new unique object (as from
2323 * +Object.new+) as the block parameter. This object can then be used as the
2324 * argument to +throw+, and will match the correct +catch+ block.
2329 * puts "This puts is not reached"
2332 * puts "This puts is displayed"
2341 * puts "This puts is still not reached"
2344 * puts "Now this puts is also not reached"
2352 rb_f_catch(int argc
, VALUE
*argv
, VALUE self
)
2354 VALUE tag
= rb_check_arity(argc
, 0, 1) ? argv
[0] : rb_obj_alloc(rb_cObject
);
2355 return rb_catch_obj(tag
, catch_i
, 0);
2359 rb_catch(const char *tag
, rb_block_call_func_t func
, VALUE data
)
2361 VALUE vtag
= tag
? rb_sym_intern_ascii_cstr(tag
) : rb_obj_alloc(rb_cObject
);
2362 return rb_catch_obj(vtag
, func
, data
);
2366 vm_catch_protect(VALUE tag
, rb_block_call_func
*func
, VALUE data
,
2367 enum ruby_tag_type
*stateptr
, rb_execution_context_t
*volatile ec
)
2369 enum ruby_tag_type state
;
2370 VALUE val
= Qnil
; /* OK */
2371 rb_control_frame_t
*volatile saved_cfp
= ec
->cfp
;
2377 if ((state
= EC_EXEC_TAG()) == TAG_NONE
) {
2378 /* call with argc=1, argv = [tag], block = Qnil to insure compatibility */
2379 val
= (*func
)(tag
, data
, 1, (const VALUE
*)&tag
, Qnil
);
2381 else if (state
== TAG_THROW
&& THROW_DATA_VAL((struct vm_throw_data
*)ec
->errinfo
) == tag
) {
2382 rb_vm_rewind_cfp(ec
, saved_cfp
);
2383 val
= ec
->tag
->retval
;
2395 rb_catch_protect(VALUE t
, rb_block_call_func
*func
, VALUE data
, enum ruby_tag_type
*stateptr
)
2397 return vm_catch_protect(t
, func
, data
, stateptr
, GET_EC());
2401 rb_catch_obj(VALUE t
, rb_block_call_func_t func
, VALUE data
)
2403 enum ruby_tag_type state
;
2404 rb_execution_context_t
*ec
= GET_EC();
2405 VALUE val
= vm_catch_protect(t
, (rb_block_call_func
*)func
, data
, &state
, ec
);
2406 if (state
) EC_JUMP_TAG(ec
, state
);
2411 local_var_list_init(struct local_var_list
*vars
)
2413 vars
->tbl
= rb_ident_hash_new();
2414 RBASIC_CLEAR_CLASS(vars
->tbl
);
2418 local_var_list_finish(struct local_var_list
*vars
)
2420 /* TODO: not to depend on the order of st_table */
2421 VALUE ary
= rb_hash_keys(vars
->tbl
);
2422 rb_hash_clear(vars
->tbl
);
2428 local_var_list_update(st_data_t
*key
, st_data_t
*value
, st_data_t arg
, int existing
)
2430 if (existing
) return ST_STOP
;
2431 *value
= (st_data_t
)Qtrue
; /* INT2FIX(arg) */
2436 local_var_list_add(const struct local_var_list
*vars
, ID lid
)
2438 if (lid
&& rb_is_local_id(lid
)) {
2439 /* should skip temporary variable */
2440 st_data_t idx
= 0; /* tbl->num_entries */
2441 rb_hash_stlike_update(vars
->tbl
, ID2SYM(lid
), local_var_list_update
, idx
);
2447 * local_variables -> array
2449 * Returns the names of the current local variables.
2455 * local_variables #=> [:fred, :i]
2459 rb_f_local_variables(VALUE _
)
2461 struct local_var_list vars
;
2462 rb_execution_context_t
*ec
= GET_EC();
2463 rb_control_frame_t
*cfp
= vm_get_ruby_level_caller_cfp(ec
, RUBY_VM_PREVIOUS_CONTROL_FRAME(ec
->cfp
));
2466 local_var_list_init(&vars
);
2469 for (i
= 0; i
< cfp
->iseq
->body
->local_table_size
; i
++) {
2470 local_var_list_add(&vars
, cfp
->iseq
->body
->local_table
[i
]);
2473 if (!VM_ENV_LOCAL_P(cfp
->ep
)) {
2475 const VALUE
*ep
= VM_CF_PREV_EP(cfp
);
2477 if (vm_collect_local_variables_in_heap(ep
, &vars
)) {
2481 while (cfp
->ep
!= ep
) {
2482 cfp
= RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp
);
2490 return local_var_list_finish(&vars
);
2495 * block_given? -> true or false
2497 * Returns <code>true</code> if <code>yield</code> would execute a
2498 * block in the current context. The <code>iterator?</code> form
2499 * is mildly deprecated.
2508 * try #=> "no block"
2509 * try { "hello" } #=> "hello"
2510 * try do "hello" end #=> "hello"
2514 rb_f_block_given_p(VALUE _
)
2516 rb_execution_context_t
*ec
= GET_EC();
2517 rb_control_frame_t
*cfp
= ec
->cfp
;
2518 cfp
= vm_get_ruby_level_caller_cfp(ec
, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp
));
2520 return RBOOL(cfp
!= NULL
&& VM_CF_BLOCK_HANDLER(cfp
) != VM_BLOCK_HANDLER_NONE
);
2525 * iterator? -> true or false
2527 * Deprecated. Use block_given? instead.
2531 rb_f_iterator_p(VALUE self
)
2533 rb_warn_deprecated("iterator?", "block_given?");
2534 return rb_f_block_given_p(self
);
2538 rb_current_realfilepath(void)
2540 const rb_execution_context_t
*ec
= GET_EC();
2541 rb_control_frame_t
*cfp
= ec
->cfp
;
2542 cfp
= vm_get_ruby_level_caller_cfp(ec
, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp
));
2544 VALUE path
= rb_iseq_realpath(cfp
->iseq
);
2545 if (RTEST(path
)) return path
;
2547 path
= rb_iseq_path(cfp
->iseq
);
2548 if (path
== eval_default_path
) {
2561 rb_define_global_function("eval", rb_f_eval
, -1);
2562 rb_define_global_function("local_variables", rb_f_local_variables
, 0);
2563 rb_define_global_function("iterator?", rb_f_iterator_p
, 0);
2564 rb_define_global_function("block_given?", rb_f_block_given_p
, 0);
2566 rb_define_global_function("catch", rb_f_catch
, -1);
2567 rb_define_global_function("throw", rb_f_throw
, -1);
2569 rb_define_global_function("loop", rb_f_loop
, 0);
2571 rb_define_method(rb_cBasicObject
, "instance_eval", rb_obj_instance_eval_internal
, -1);
2572 rb_define_method(rb_cBasicObject
, "instance_exec", rb_obj_instance_exec_internal
, -1);
2573 rb_define_private_method(rb_cBasicObject
, "method_missing", rb_method_missing
, -1);
2576 rb_add_method(rb_cBasicObject
, id__send__
,
2577 VM_METHOD_TYPE_OPTIMIZED
, (void *)OPTIMIZED_METHOD_TYPE_SEND
, METHOD_VISI_PUBLIC
);
2578 rb_add_method(rb_mKernel
, idSend
,
2579 VM_METHOD_TYPE_OPTIMIZED
, (void *)OPTIMIZED_METHOD_TYPE_SEND
, METHOD_VISI_PUBLIC
);
2581 rb_define_method(rb_cBasicObject
, "__send__", rb_f_send
, -1);
2582 rb_define_method(rb_mKernel
, "send", rb_f_send
, -1);
2584 rb_define_method(rb_mKernel
, "public_send", rb_f_public_send
, -1);
2586 rb_define_method(rb_cModule
, "module_exec", rb_mod_module_exec_internal
, -1);
2587 rb_define_method(rb_cModule
, "class_exec", rb_mod_module_exec_internal
, -1);
2588 rb_define_method(rb_cModule
, "module_eval", rb_mod_module_eval_internal
, -1);
2589 rb_define_method(rb_cModule
, "class_eval", rb_mod_module_eval_internal
, -1);
2591 rb_eUncaughtThrow
= rb_define_class("UncaughtThrowError", rb_eArgError
);
2592 rb_define_method(rb_eUncaughtThrow
, "initialize", uncaught_throw_init
, -1);
2593 rb_define_method(rb_eUncaughtThrow
, "tag", uncaught_throw_tag
, 0);
2594 rb_define_method(rb_eUncaughtThrow
, "value", uncaught_throw_value
, 0);
2595 rb_define_method(rb_eUncaughtThrow
, "to_s", uncaught_throw_to_s
, 0);
2597 id_result
= rb_intern_const("result");
2598 id_tag
= rb_intern_const("tag");
2599 id_value
= rb_intern_const("value");
2602 #endif /* #ifndef MJIT_HEADER */