Ruby: vm_eval.c Source File

Ruby 3.2.5p208 (2024-07-26 revision 31d0f1a2e7dbfb60731d1f05b868e1d578cda493)

vm_eval.c
1/**********************************************************************
2
3 vm_eval.c -
4
5 $Author$
6 created at: Sat May 24 16:02:32 JST 2008
7
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
11
12**********************************************************************/
13
14#include "internal/thread.h"
15 struct local_var_list {
16 VALUE tbl;
17};
18
19static 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);
20static 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);
21static inline VALUE vm_yield(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_splat);
22static inline VALUE vm_yield_with_block(rb_execution_context_t *ec, int argc, const VALUE *argv, VALUE block_handler, int kw_splat);
23static inline VALUE vm_yield_force_blockarg(rb_execution_context_t *ec, VALUE args);
24 VALUE vm_exec(rb_execution_context_t *ec, bool jit_enable_p);
25static 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);
26static int vm_collect_local_variables_in_heap(const VALUE *dfp, const struct local_var_list *vars);
27
28static VALUE rb_eUncaughtThrow;
29static ID id_result, id_tag, id_value;
30#define id_mesg idMesg
31
32typedef enum call_type {
33 CALL_PUBLIC,
34 CALL_FCALL,
35 CALL_VCALL,
36 CALL_PUBLIC_KW,
37 CALL_FCALL_KW,
38 CALL_TYPE_MAX
39} call_type;
40
41static VALUE send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope);
42static VALUE vm_call0_body(rb_execution_context_t* ec, struct rb_calling_info *calling, const VALUE *argv);
43
44#ifndef MJIT_HEADER
45
46MJIT_FUNC_EXPORTED VALUE
47rb_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{
49 struct rb_calling_info calling = {
50 .ci = &VM_CI_ON_STACK(id, kw_splat ? VM_CALL_KW_SPLAT : 0, argc, NULL),
51 .cc = &VM_CC_ON_STACK(Qfalse, vm_call_general, {{ 0 }}, cme),
52 .block_handler = vm_passed_block_handler(ec),
53 .recv = recv,
54 .argc = argc,
55 .kw_splat = kw_splat,
56 };
57
58 return vm_call0_body(ec, &calling, argv);
59}
60
61MJIT_FUNC_EXPORTED VALUE
62rb_vm_call_with_refinements(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE *argv, int kw_splat)
63{
64 const rb_callable_method_entry_t *me =
65 rb_callable_method_entry_with_refinements(CLASS_OF(recv), id, NULL);
66 if (me) {
67 return rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat);
68 }
69 else {
70 /* fallback to funcall (e.g. method_missing) */
71 return rb_funcallv(recv, id, argc, argv);
72 }
73}
74
75static inline VALUE
76vm_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{
78 struct rb_calling_info calling = {
79 .ci = &VM_CI_ON_STACK(id, kw_splat ? VM_CALL_KW_SPLAT : 0, argc, NULL),
80 .cc = cc,
81 .block_handler = vm_passed_block_handler(ec),
82 .recv = recv,
83 .argc = argc,
84 .kw_splat = kw_splat,
85 };
86
87 return vm_call0_body(ec, &calling, argv);
88}
89
90static VALUE
91vm_call0_cme(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv, const rb_callable_method_entry_t *cme)
92{
93 calling->cc = &VM_CC_ON_STACK(Qfalse, vm_call_general, {{ 0 }}, cme);
94 return vm_call0_body(ec, calling, argv);
95}
96
97static VALUE
98vm_call0_super(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv, VALUE klass, enum method_missing_reason ex)
99{
100 ID mid = vm_ci_mid(calling->ci);
101 klass = RCLASS_SUPER(klass);
102
103 if (klass) {
104 const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
105
106 if (cme) {
107 RUBY_VM_CHECK_INTS(ec);
108 return vm_call0_cme(ec, calling, argv, cme);
109 }
110 }
111
112 vm_passed_block_handler_set(ec, calling->block_handler);
113 return method_missing(ec, calling->recv, mid, calling->argc, argv, ex, calling->kw_splat);
114}
115
116static VALUE
117vm_call0_cfunc_with_frame(rb_execution_context_t* ec, struct rb_calling_info *calling, const VALUE *argv)
118{
119 const struct rb_callinfo *ci = calling->ci;
120 VALUE val;
121 const rb_callable_method_entry_t *me = vm_cc_cme(calling->cc);
122 const rb_method_cfunc_t *cfunc = UNALIGNED_MEMBER_PTR(me->def, body.cfunc);
123 int len = cfunc->argc;
124 VALUE recv = calling->recv;
125 int argc = calling->argc;
126 ID mid = vm_ci_mid(ci);
127 VALUE block_handler = calling->block_handler;
128 int frame_flags = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
129
130 if (calling->kw_splat) {
131 if (argc > 0 && RB_TYPE_P(argv[argc-1], T_HASH) && RHASH_EMPTY_P(argv[argc-1])) {
132 argc--;
133 }
134 else {
135 frame_flags |= VM_FRAME_FLAG_CFRAME_KW;
136 }
137 }
138
139 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id);
140 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, recv, me->def->original_id, mid, me->owner, Qnil);
141 {
142 rb_control_frame_t *reg_cfp = ec->cfp;
143
144 vm_push_frame(ec, 0, frame_flags, recv,
145 block_handler, (VALUE)me,
146 0, reg_cfp->sp, 0, 0);
147
148 if (len >= 0) rb_check_arity(argc, len, len);
149
150 val = (*cfunc->invoker)(recv, argc, argv, cfunc->func);
151
152 CHECK_CFP_CONSISTENCY("vm_call0_cfunc_with_frame");
153 rb_vm_pop_frame(ec);
154 }
155 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, recv, me->def->original_id, mid, me->owner, val);
156 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, me->owner, me->def->original_id);
157
158 return val;
159}
160
161static VALUE
162vm_call0_cfunc(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv)
163{
164 return vm_call0_cfunc_with_frame(ec, calling, argv);
165}
166
167static void
168vm_call_check_arity(struct rb_calling_info *calling, int argc, const VALUE *argv)
169{
170 if (calling->kw_splat &&
171 calling->argc > 0 &&
172 RB_TYPE_P(argv[calling->argc-1], T_HASH) &&
173 RHASH_EMPTY_P(argv[calling->argc-1])) {
174 calling->argc--;
175 }
176
177 rb_check_arity(calling->argc, argc, argc);
178}
179
180/* `ci' should point temporal value (on stack value) */
181static VALUE
182vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv)
183{
184 const struct rb_callinfo *ci = calling->ci;
185 const struct rb_callcache *cc = calling->cc;
186 VALUE ret;
187
188 retry:
189
190 switch (vm_cc_cme(cc)->def->type) {
191 case VM_METHOD_TYPE_ISEQ:
192 {
193 rb_control_frame_t *reg_cfp = ec->cfp;
194 int i;
195
196 CHECK_VM_STACK_OVERFLOW(reg_cfp, calling->argc + 1);
197 vm_check_canary(ec, reg_cfp->sp);
198
199 *reg_cfp->sp++ = calling->recv;
200 for (i = 0; i < calling->argc; i++) {
201 *reg_cfp->sp++ = argv[i];
202 }
203
204 vm_call_iseq_setup(ec, reg_cfp, calling);
205 VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);
206 return vm_exec(ec, true); /* CHECK_INTS in this function */
207 }
208 case VM_METHOD_TYPE_NOTIMPLEMENTED:
209 case VM_METHOD_TYPE_CFUNC:
210 ret = vm_call0_cfunc(ec, calling, argv);
211 goto success;
212 case VM_METHOD_TYPE_ATTRSET:
213 vm_call_check_arity(calling, 1, argv);
214 VM_CALL_METHOD_ATTR(ret,
215 rb_ivar_set(calling->recv, vm_cc_cme(cc)->def->body.attr.id, argv[0]),
216 (void)0);
217 goto success;
218 case VM_METHOD_TYPE_IVAR:
219 vm_call_check_arity(calling, 0, argv);
220 VM_CALL_METHOD_ATTR(ret,
221 rb_attr_get(calling->recv, vm_cc_cme(cc)->def->body.attr.id),
222 (void)0);
223 goto success;
224 case VM_METHOD_TYPE_BMETHOD:
225 ret = vm_call_bmethod_body(ec, calling, argv);
226 goto success;
227 case VM_METHOD_TYPE_ZSUPER:
228 {
229 VALUE klass = RCLASS_ORIGIN(vm_cc_cme(cc)->defined_class);
230 return vm_call0_super(ec, calling, argv, klass, MISSING_SUPER);
231 }
232 case VM_METHOD_TYPE_REFINED:
233 {
234 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
235
236 if (cme->def->body.refined.orig_me) {
237 const rb_callable_method_entry_t *orig_cme = refined_method_callable_without_refinement(cme);
238 return vm_call0_cme(ec, calling, argv, orig_cme);
239 }
240
241 VALUE klass = cme->defined_class;
242 return vm_call0_super(ec, calling, argv, klass, 0);
243 }
244 case VM_METHOD_TYPE_ALIAS:
245 {
246 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
247 const rb_callable_method_entry_t *orig_cme = aliased_callable_method_entry(cme);
248
249 if (cme == orig_cme) rb_bug("same!!");
250
251 if (vm_cc_markable(cc)) {
252 return vm_call0_cme(ec, calling, argv, orig_cme);
253 }
254 else {
255 *((const rb_callable_method_entry_t **)&cc->cme_) = orig_cme;
256 goto retry;
257 }
258 }
259 case VM_METHOD_TYPE_MISSING:
260 {
261 vm_passed_block_handler_set(ec, calling->block_handler);
262 return method_missing(ec, calling->recv, vm_ci_mid(ci), calling->argc,
263 argv, MISSING_NOENTRY, calling->kw_splat);
264 }
265 case VM_METHOD_TYPE_OPTIMIZED:
266 switch (vm_cc_cme(cc)->def->body.optimized.type) {
267 case OPTIMIZED_METHOD_TYPE_SEND:
268 ret = send_internal(calling->argc, argv, calling->recv, calling->kw_splat ? CALL_FCALL_KW : CALL_FCALL);
269 goto success;
270 case OPTIMIZED_METHOD_TYPE_CALL:
271 {
272 rb_proc_t *proc;
273 GetProcPtr(calling->recv, proc);
274 ret = rb_vm_invoke_proc(ec, proc, calling->argc, argv, calling->kw_splat, calling->block_handler);
275 goto success;
276 }
277 case OPTIMIZED_METHOD_TYPE_STRUCT_AREF:
278 vm_call_check_arity(calling, 0, argv);
279 ret = vm_call_opt_struct_aref0(ec, calling);
280 goto success;
281 case OPTIMIZED_METHOD_TYPE_STRUCT_ASET:
282 vm_call_check_arity(calling, 1, argv);
283 ret = vm_call_opt_struct_aset0(ec, calling, argv[0]);
284 goto success;
285 default:
286 rb_bug("vm_call0: unsupported optimized method type (%d)", vm_cc_cme(cc)->def->body.optimized.type);
287 }
288 break;
289 case VM_METHOD_TYPE_UNDEF:
290 break;
291 }
292 rb_bug("vm_call0: unsupported method type (%d)", vm_cc_cme(cc)->def->type);
293 return Qundef;
294
295 success:
296 RUBY_VM_CHECK_INTS(ec);
297 return ret;
298}
299
300MJIT_FUNC_EXPORTED VALUE
301rb_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{
303 return rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat);
304}
305
306static inline VALUE
307vm_call_super(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_splat)
308{
309 VALUE recv = ec->cfp->self;
310 VALUE klass;
311 ID id;
312 rb_control_frame_t *cfp = ec->cfp;
313 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
314
315 if (VM_FRAME_RUBYFRAME_P(cfp)) {
316 rb_bug("vm_call_super: should not be reached");
317 }
318
319 klass = RCLASS_ORIGIN(me->defined_class);
320 klass = RCLASS_SUPER(klass);
321 id = me->def->original_id;
322 me = rb_callable_method_entry(klass, id);
323
324 if (!me) {
325 return method_missing(ec, recv, id, argc, argv, MISSING_SUPER, kw_splat);
326 }
327 return rb_vm_call_kw(ec, recv, id, argc, argv, me, kw_splat);
328}
329
330 VALUE
331rb_call_super_kw(int argc, const VALUE *argv, int kw_splat)
332{
333 rb_execution_context_t *ec = GET_EC();
334 PASS_PASSED_BLOCK_HANDLER_EC(ec);
335 return vm_call_super(ec, argc, argv, kw_splat);
336}
337
338 VALUE
339rb_call_super(int argc, const VALUE *argv)
340{
341 return rb_call_super_kw(argc, argv, RB_NO_KEYWORDS);
342}
343
344 VALUE
345rb_current_receiver(void)
346{
347 const rb_execution_context_t *ec = GET_EC();
348 rb_control_frame_t *cfp;
349 if (!ec || !(cfp = ec->cfp)) {
350 rb_raise(rb_eRuntimeError, "no self, no life");
351 }
352 return cfp->self;
353}
354
355#endif /* #ifndef MJIT_HEADER */
356
357static inline void
358stack_check(rb_execution_context_t *ec)
359{
360 if (!rb_ec_raised_p(ec, RAISED_STACKOVERFLOW) &&
361 rb_ec_stack_check(ec)) {
362 rb_ec_raised_set(ec, RAISED_STACKOVERFLOW);
363 rb_ec_stack_overflow(ec, FALSE);
364 }
365}
366
367#ifndef MJIT_HEADER
368
369void
370rb_check_stack_overflow(void)
371{
372#ifndef RB_THREAD_LOCAL_SPECIFIER
373 if (!ruby_current_ec_key) return;
374#endif
375 rb_execution_context_t *ec = GET_EC();
376 if (ec) stack_check(ec);
377}
378
379NORETURN(static void uncallable_object(VALUE recv, ID mid));
380static inline const rb_callable_method_entry_t *rb_search_method_entry(VALUE recv, ID mid);
381static 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
383static const struct rb_callcache *
384cc_new(VALUE klass, ID mid, int argc, const rb_callable_method_entry_t *cme)
385{
386 const struct rb_callcache *cc = NULL;
387
388 RB_VM_LOCK_ENTER();
389 {
390 struct rb_class_cc_entries *ccs;
391 struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass);
392 VALUE ccs_data;
393
394 if (rb_id_table_lookup(cc_tbl, mid, &ccs_data)) {
395 // ok
396 ccs = (struct rb_class_cc_entries *)ccs_data;
397 }
398 else {
399 ccs = vm_ccs_create(klass, cc_tbl, mid, cme);
400 }
401
402 for (int i=0; i<ccs->len; i++) {
403 cc = ccs->entries[i].cc;
404 if (vm_cc_cme(cc) == cme) {
405 break;
406 }
407 cc = NULL;
408 }
409
410 if (cc == NULL) {
411 const struct rb_callinfo *ci = vm_ci_new(mid, 0, argc, NULL); // 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);
415 }
416 }
417 RB_VM_LOCK_LEAVE();
418
419 return cc;
420}
421
422static VALUE
423gccct_hash(VALUE klass, ID mid)
424{
425 return (klass >> 3) ^ (VALUE)mid;
426}
427
428NOINLINE(static const struct rb_callcache *gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, ID mid, int argc, unsigned int index));
429
430static const struct rb_callcache *
431gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, ID mid, int argc, unsigned int index)
432{
433 const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
434 const struct rb_callcache *cc;
435
436 if (cme != NULL) {
437 cc = cc_new(klass, mid, argc, cme);
438 }
439 else {
440 cc = NULL;
441 }
442
443 return vm->global_cc_cache_table[index] = cc;
444}
445
446static inline const struct rb_callcache *
447gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, int argc)
448{
449 VALUE klass;
450
451 if (!SPECIAL_CONST_P(recv)) {
452 klass = RBASIC_CLASS(recv);
453 if (UNLIKELY(!klass)) uncallable_object(recv, mid);
454 }
455 else {
456 klass = CLASS_OF(recv);
457 }
458
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];
463
464 if (LIKELY(cc)) {
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)) {
469
470 VM_ASSERT(vm_cc_check_cme(cc, rb_callable_method_entry(klass, mid)));
471 RB_DEBUG_COUNTER_INC(gccct_hit);
472
473 return cc;
474 }
475 }
476 }
477 else {
478 RB_DEBUG_COUNTER_INC(gccct_null);
479 }
480
481 RB_DEBUG_COUNTER_INC(gccct_miss);
482 return gccct_method_search_slowpath(vm, klass, mid, argc, index);
483}
484
501static inline VALUE
502rb_call0(rb_execution_context_t *ec,
503 VALUE recv, ID mid, int argc, const VALUE *argv,
504 call_type call_scope, VALUE self)
505{
506 enum method_missing_reason call_status;
507 call_type scope = call_scope;
508 int kw_splat = RB_NO_KEYWORDS;
509
510 switch (scope) {
511 case CALL_PUBLIC_KW:
512 scope = CALL_PUBLIC;
513 kw_splat = 1;
514 break;
515 case CALL_FCALL_KW:
516 scope = CALL_FCALL;
517 kw_splat = 1;
518 break;
519 default:
520 break;
521 }
522
523 const struct rb_callcache *cc = gccct_method_search(ec, recv, mid, argc);
524
525 if (scope == CALL_PUBLIC) {
526 RB_DEBUG_COUNTER_INC(call0_public);
527
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);
531
532 if (UNLIKELY(call_status != MISSING_NONE)) {
533 return method_missing(ec, recv, mid, argc, argv, call_status, kw_splat);
534 }
535 else if (UNLIKELY(cc_cme != cme)) { // refinement is solved
536 stack_check(ec);
537 return rb_vm_call_kw(ec, recv, mid, argc, argv, cme, kw_splat);
538 }
539 }
540 else {
541 RB_DEBUG_COUNTER_INC(call0_other);
542 call_status = rb_method_call_status(ec, cc ? vm_cc_cme(cc) : NULL, scope, self);
543
544 if (UNLIKELY(call_status != MISSING_NONE)) {
545 return method_missing(ec, recv, mid, argc, argv, call_status, kw_splat);
546 }
547 }
548
549 stack_check(ec);
550 return vm_call0_cc(ec, recv, mid, argc, argv, cc, kw_splat);
551}
552
553 struct rescue_funcall_args {
554 VALUE defined_class;
555 VALUE recv;
556 ID mid;
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;
561 int argc;
562 const VALUE *argv;
563 int kw_splat;
564};
565
566static VALUE
567check_funcall_exec(VALUE v)
568{
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);
573}
574
575static VALUE
576check_funcall_failed(VALUE v, VALUE e)
577{
578 struct rescue_funcall_args *args = (void *)v;
579 int ret = args->respond;
580 if (!ret) {
581 switch (method_boundp(args->defined_class, args->mid,
582 BOUND_PRIVATE|BOUND_RESPONDS)) {
583 case 2:
584 ret = TRUE;
585 break;
586 case 0:
587 ret = args->respond_to_missing;
588 break;
589 default:
590 ret = FALSE;
591 break;
592 }
593 }
594 if (ret) {
595 rb_exc_raise(e);
596 }
597 return Qundef;
598}
599
600static int
601check_funcall_respond_to(rb_execution_context_t *ec, VALUE klass, VALUE recv, ID mid)
602{
603 return vm_respond_to(ec, klass, recv, mid, TRUE);
604}
605
606static int
607check_funcall_callable(rb_execution_context_t *ec, const rb_callable_method_entry_t *me)
608{
609 return rb_method_call_status(ec, me, CALL_FCALL, ec->cfp->self) == MISSING_NONE;
610}
611
612static VALUE
613check_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)
614{
615 struct rescue_funcall_args args;
616 const rb_callable_method_entry_t *cme;
617 VALUE ret = Qundef;
618
619 ret = basic_obj_respond_to_missing(ec, klass, recv,
620 ID2SYM(mid), Qtrue);
621 if (!RTEST(ret)) return def;
622 args.respond = respond > 0;
623 args.respond_to_missing = !UNDEF_P(ret);
624 ret = def;
625 cme = callable_method_entry(klass, idMethodMissing, &args.defined_class);
626
627 if (cme && !METHOD_ENTRY_BASIC(cme)) {
628 VALUE argbuf, *new_args = ALLOCV_N(VALUE, argbuf, argc+1);
629
630 new_args[0] = ID2SYM(mid);
631 #ifdef __GLIBC__
632 if (!argv) {
633 static const VALUE buf = Qfalse;
634 VM_ASSERT(argc == 0);
635 argv = &buf;
636 }
637 #endif
638 MEMCPY(new_args+1, argv, VALUE, argc);
639 ec->method_missing_reason = MISSING_NOENTRY;
640 args.ec = ec;
641 args.recv = recv;
642 args.cme = cme;
643 args.mid = mid;
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);
650 ALLOCV_END(argbuf);
651 }
652 return ret;
653}
654
655static VALUE rb_check_funcall_default_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE def, int kw_splat);
656
657 VALUE
658rb_check_funcall_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
659{
660 return rb_check_funcall_default_kw(recv, mid, argc, argv, Qundef, kw_splat);
661}
662
663 VALUE
664rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
665{
666 return rb_check_funcall_default_kw(recv, mid, argc, argv, Qundef, RB_NO_KEYWORDS);
667}
668
669static VALUE
670rb_check_funcall_default_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE def, int kw_splat)
671{
672 VM_ASSERT(ruby_thread_has_gvl_p());
673
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);
678
679 if (!respond)
680 return def;
681
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 (UNDEF_P(ret)) ret = def;
687 return ret;
688 }
689 stack_check(ec);
690 return rb_vm_call_kw(ec, recv, mid, argc, argv, me, kw_splat);
691}
692
693 VALUE
694rb_check_funcall_default(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE def)
695{
696 return rb_check_funcall_default_kw(recv, mid, argc, argv, def, RB_NO_KEYWORDS);
697}
698
699 VALUE
700rb_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)
702{
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);
707
708 if (!respond) {
709 (*hook)(FALSE, recv, mid, argc, argv, arg);
710 return Qundef;
711 }
712
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)(!UNDEF_P(ret), recv, mid, argc, argv, arg);
718 return ret;
719 }
720 stack_check(ec);
721 (*hook)(TRUE, recv, mid, argc, argv, arg);
722 return rb_vm_call_kw(ec, recv, mid, argc, argv, me, kw_splat);
723}
724
725 VALUE
726rb_check_funcall_with_hook(VALUE recv, ID mid, int argc, const VALUE *argv,
727 rb_check_funcall_hook *hook, VALUE arg)
728{
729 return rb_check_funcall_with_hook_kw(recv, mid, argc, argv, hook, arg, RB_NO_KEYWORDS);
730}
731
732const char *
733rb_type_str(enum ruby_value_type type)
734{
735#define type_case(t) t: return #t
736 switch (type) {
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);
764 case T_MASK: break;
765 }
766#undef type_case
767 return NULL;
768}
769
770static void
771uncallable_object(VALUE recv, ID mid)
772{
773 VALUE flags;
774 int type;
775 const char *typestr;
776 VALUE mname = rb_id2str(mid);
777
778 if (SPECIAL_CONST_P(recv)) {
779 rb_raise(rb_eNotImpError,
780 "method `%"PRIsVALUE"' called on unexpected immediate object (%p)",
781 mname, (void *)recv);
782 }
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);
787 }
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);
793 }
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);
799 }
800 else {
801 rb_raise(rb_eNotImpError,
802 "method `%"PRIsVALUE"' called on unexpected %s object"
803 " (%p flags=0x%"PRIxVALUE")",
804 mname, typestr, (void *)recv, flags);
805 }
806}
807
808static inline const rb_callable_method_entry_t *
809rb_search_method_entry(VALUE recv, ID mid)
810{
811 VALUE klass = CLASS_OF(recv);
812
813 if (!klass) uncallable_object(recv, mid);
814 return rb_callable_method_entry(klass, mid);
815}
816
817static inline enum method_missing_reason
818rb_method_call_status(rb_execution_context_t *ec, const rb_callable_method_entry_t *me, call_type scope, VALUE self)
819{
820 if (UNLIKELY(UNDEFINED_METHOD_ENTRY_P(me))) {
821 goto undefined;
822 }
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;
826 }
827
828 rb_method_visibility_t visi = METHOD_ENTRY_VISI(me);
829
830 /* receiver specified form for private method */
831 if (UNLIKELY(visi != METHOD_VISI_PUBLIC)) {
832 if (me->def->original_id == idMethodMissing) {
833 return MISSING_NONE;
834 }
835 else if (visi == METHOD_VISI_PRIVATE &&
836 scope == CALL_PUBLIC) {
837 return MISSING_PRIVATE;
838 }
839 /* self must be kind of a specified form for protected method */
840 else if (visi == METHOD_VISI_PROTECTED &&
841 scope == CALL_PUBLIC) {
842
843 VALUE defined_class = me->owner;
844 if (RB_TYPE_P(defined_class, T_ICLASS)) {
845 defined_class = RBASIC(defined_class)->klass;
846 }
847
848 if (UNDEF_P(self) || !rb_obj_is_kind_of(self, defined_class)) {
849 return MISSING_PROTECTED;
850 }
851 }
852 }
853
854 return MISSING_NONE;
855
856 undefined:
857 return scope == CALL_VCALL ? MISSING_VCALL : MISSING_NOENTRY;
858}
859
860
872static inline VALUE
873rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope)
874{
875 rb_execution_context_t *ec = GET_EC();
876 return rb_call0(ec, recv, mid, argc, argv, scope, ec->cfp->self);
877}
878
879NORETURN(static void raise_method_missing(rb_execution_context_t *ec, int argc, const VALUE *argv,
880 VALUE obj, enum method_missing_reason call_status));
881
882/*
883 * call-seq:
884 * obj.method_missing(symbol [, *args] ) -> result
885 *
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
893 * missing method.
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
897 * values.
898 *
899 * class Roman
900 * def roman_to_int(str)
901 * # ...
902 * end
903 *
904 * def method_missing(symbol, *args)
905 * str = symbol.id2name
906 * begin
907 * roman_to_int(str)
908 * rescue
909 * super(symbol, *args)
910 * end
911 * end
912 * end
913 *
914 * r = Roman.new
915 * r.iv #=> 4
916 * r.xxiii #=> 23
917 * r.mm #=> 2000
918 * r.foo #=> NoMethodError
919 */
920
921static VALUE
922rb_method_missing(int argc, const VALUE *argv, VALUE obj)
923{
924 rb_execution_context_t *ec = GET_EC();
925 raise_method_missing(ec, argc, argv, obj, ec->method_missing_reason);
926 UNREACHABLE_RETURN(Qnil);
927}
928
929MJIT_FUNC_EXPORTED VALUE
930rb_make_no_method_exception(VALUE exc, VALUE format, VALUE obj,
931 int argc, const VALUE *argv, int priv)
932{
933 VALUE name = argv[0];
934
935 if (!format) {
936 format = rb_fstring_lit("undefined method `%s' for %s%s%s");
937 }
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);
941 }
942 else {
943 return rb_name_err_new(format, obj, name);
944 }
945}
946
947#endif /* #ifndef MJIT_HEADER */
948
949static void
950raise_method_missing(rb_execution_context_t *ec, int argc, const VALUE *argv, VALUE obj,
951 enum method_missing_reason last_call_status)
952{
953 VALUE exc = rb_eNoMethodError;
954 VALUE format = 0;
955
956 if (UNLIKELY(argc == 0)) {
957 rb_raise(rb_eArgError, "no method name given");
958 }
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]));
963 }
964
965 stack_check(ec);
966
967 if (last_call_status & MISSING_PRIVATE) {
968 format = rb_fstring_lit("private method `%s' called for %s%s%s");
969 }
970 else if (last_call_status & MISSING_PROTECTED) {
971 format = rb_fstring_lit("protected method `%s' called for %s%s%s");
972 }
973 else if (last_call_status & MISSING_VCALL) {
974 format = rb_fstring_lit("undefined local variable or method `%s' for %s%s%s");
975 exc = rb_eNameError;
976 }
977 else if (last_call_status & MISSING_SUPER) {
978 format = rb_fstring_lit("super: no superclass method `%s' for %s%s%s");
979 }
980
981 {
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();
986 }
987 rb_exc_raise(exc);
988 }
989}
990
991static void
992vm_raise_method_missing(rb_execution_context_t *ec, int argc, const VALUE *argv,
993 VALUE obj, int call_status)
994{
995 vm_passed_block_handler_set(ec, VM_BLOCK_HANDLER_NONE);
996 raise_method_missing(ec, argc, argv, obj, call_status | MISSING_MISSING);
997}
998
999static inline VALUE
1000method_missing(rb_execution_context_t *ec, VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status, int kw_splat)
1001{
1002 VALUE *nargv, result, work, klass;
1003 VALUE block_handler = vm_passed_block_handler(ec);
1004 const rb_callable_method_entry_t *me;
1005
1006 ec->method_missing_reason = call_status;
1007
1008 if (id == idMethodMissing) {
1009 goto missing;
1010 }
1011
1012 nargv = ALLOCV_N(VALUE, work, argc + 1);
1013 nargv[0] = ID2SYM(id);
1014 #ifdef __GLIBC__
1015 if (!argv) {
1016 static const VALUE buf = Qfalse;
1017 VM_ASSERT(argc == 0);
1018 argv = &buf;
1019 }
1020 #endif
1021 MEMCPY(nargv + 1, argv, VALUE, argc);
1022 ++argc;
1023 argv = nargv;
1024
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);
1032 return result;
1033 missing:
1034 raise_method_missing(ec, argc, argv, obj, call_status | MISSING_MISSING);
1035 UNREACHABLE_RETURN(Qundef);
1036}
1037
1038#ifndef MJIT_HEADER
1039
1040static inline VALUE
1041rb_funcallv_scope(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope)
1042{
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;
1046
1047 if (LIKELY(cc) &&
1048 LIKELY(rb_method_call_status(ec, vm_cc_cme(cc), scope, self) == MISSING_NONE)) {
1049 // fastpath
1050 return vm_call0_cc(ec, recv, mid, argc, argv, cc, false);
1051 }
1052 else {
1053 return rb_call0(ec, recv, mid, argc, argv, scope, self);
1054 }
1055}
1056
1057#ifdef rb_funcallv
1058#undef rb_funcallv
1059#endif
1060 VALUE
1061rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
1062{
1063 VM_ASSERT(ruby_thread_has_gvl_p());
1064
1065 return rb_funcallv_scope(recv, mid, argc, argv, CALL_FCALL);
1066}
1067
1068 VALUE
1069rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
1070{
1071 VM_ASSERT(ruby_thread_has_gvl_p());
1072
1073 return rb_call(recv, mid, argc, argv, kw_splat ? CALL_FCALL_KW : CALL_FCALL);
1074}
1075
1076 VALUE
1077rb_apply(VALUE recv, ID mid, VALUE args)
1078{
1079 int argc;
1080 VALUE *argv, ret;
1081
1082 argc = RARRAY_LENINT(args);
1083 if (argc >= 0x100) {
1084 args = rb_ary_subseq(args, 0, argc);
1085 RBASIC_CLEAR_CLASS(args);
1086 OBJ_FREEZE(args);
1087 ret = rb_call(recv, mid, argc, RARRAY_CONST_PTR(args), CALL_FCALL);
1088 RB_GC_GUARD(args);
1089 return ret;
1090 }
1091 argv = ALLOCA_N(VALUE, argc);
1092 MEMCPY(argv, RARRAY_CONST_PTR_TRANSIENT(args), VALUE, argc);
1093
1094 return rb_funcallv(recv, mid, argc, argv);
1095}
1096
1097#ifdef rb_funcall
1098#undef rb_funcall
1099#endif
1100
1101 VALUE
1102rb_funcall(VALUE recv, ID mid, int n, ...)
1103{
1104 VALUE *argv;
1105 va_list ar;
1106
1107 if (n > 0) {
1108 long i;
1109
1110 va_start(ar, n);
1111
1112 argv = ALLOCA_N(VALUE, n);
1113
1114 for (i = 0; i < n; i++) {
1115 argv[i] = va_arg(ar, VALUE);
1116 }
1117 va_end(ar);
1118 }
1119 else {
1120 argv = 0;
1121 }
1122 return rb_funcallv(recv, mid, n, argv);
1123}
1124
1135 VALUE
1136rb_check_funcall_basic_kw(VALUE recv, ID mid, VALUE ancestor, int argc, const VALUE *argv, int kw_splat)
1137{
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 */
1142
1143 cme = rb_callable_method_entry(klass, mid);
1144 if (cme && METHOD_ENTRY_BASIC(cme) && RBASIC_CLASS(cme->defined_class) == ancestor) {
1145 ec = GET_EC();
1146 return rb_vm_call0(ec, recv, mid, argc, argv, cme, kw_splat);
1147 }
1148
1149 return Qundef;
1150}
1151
1152 VALUE
1153rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv)
1154{
1155 return rb_funcallv_scope(recv, mid, argc, argv, CALL_PUBLIC);
1156}
1157
1158 VALUE
1159rb_funcallv_public_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
1160{
1161 return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
1162}
1163
1164 VALUE
1165rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv)
1166{
1167 PASS_PASSED_BLOCK_HANDLER();
1168 return rb_funcallv_public(recv, mid, argc, argv);
1169}
1170
1171 VALUE
1172rb_funcall_passing_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
1173{
1174 PASS_PASSED_BLOCK_HANDLER();
1175 return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
1176}
1177
1178 VALUE
1179rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE passed_procval)
1180{
1181 if (!NIL_P(passed_procval)) {
1182 vm_passed_block_handler_set(GET_EC(), passed_procval);
1183 }
1184
1185 return rb_funcallv_public(recv, mid, argc, argv);
1186}
1187
1188 VALUE
1189rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE passed_procval, int kw_splat)
1190{
1191 if (!NIL_P(passed_procval)) {
1192 vm_passed_block_handler_set(GET_EC(), passed_procval);
1193 }
1194
1195 return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
1196}
1197
1198static VALUE *
1199current_vm_stack_arg(const rb_execution_context_t *ec, const VALUE *argv)
1200{
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;
1205}
1206
1207static VALUE
1208send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope)
1209{
1210 ID id;
1211 VALUE vid;
1212 VALUE self;
1213 VALUE ret, vargv = 0;
1214 rb_execution_context_t *ec = GET_EC();
1215 int public = scope == CALL_PUBLIC || scope == CALL_PUBLIC_KW;
1216
1217 if (public) {
1218 self = Qundef;
1219 }
1220 else {
1221 self = RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp)->self;
1222 }
1223
1224 if (argc == 0) {
1225 rb_raise(rb_eArgError, "no method name given");
1226 }
1227
1228 vid = *argv;
1229
1230 id = rb_check_id(&vid);
1231 if (!id) {
1232 if (rb_method_basic_definition_p(CLASS_OF(recv), idMethodMissing)) {
1233 VALUE exc = rb_make_no_method_exception(rb_eNoMethodError, 0,
1234 recv, argc, argv,
1235 !public);
1236 rb_exc_raise(exc);
1237 }
1238 if (!SYMBOL_P(*argv)) {
1239 VALUE *tmp_argv = current_vm_stack_arg(ec, argv);
1240 vid = rb_str_intern(vid);
1241 if (tmp_argv) {
1242 tmp_argv[0] = vid;
1243 }
1244 else if (argc > 1) {
1245 tmp_argv = ALLOCV_N(VALUE, vargv, argc);
1246 tmp_argv[0] = vid;
1247 MEMCPY(tmp_argv+1, argv+1, VALUE, argc-1);
1248 argv = tmp_argv;
1249 }
1250 else {
1251 argv = &vid;
1252 }
1253 }
1254 id = idMethodMissing;
1255 ec->method_missing_reason = MISSING_NOENTRY;
1256 }
1257 else {
1258 argv++; argc--;
1259 }
1260 PASS_PASSED_BLOCK_HANDLER_EC(ec);
1261 ret = rb_call0(ec, recv, id, argc, argv, scope, self);
1262 ALLOCV_END(vargv);
1263 return ret;
1264}
1265
1266static VALUE
1267send_internal_kw(int argc, const VALUE *argv, VALUE recv, call_type scope)
1268{
1269 if (rb_keyword_given_p()) {
1270 switch (scope) {
1271 case CALL_PUBLIC:
1272 scope = CALL_PUBLIC_KW;
1273 break;
1274 case CALL_FCALL:
1275 scope = CALL_FCALL_KW;
1276 break;
1277 default:
1278 break;
1279 }
1280 }
1281 return send_internal(argc, argv, recv, scope);
1282}
1283
1284/*
1285 * call-seq:
1286 * foo.send(symbol [, args...]) -> obj
1287 * foo.__send__(symbol [, args...]) -> obj
1288 * foo.send(string [, args...]) -> obj
1289 * foo.__send__(string [, args...]) -> obj
1290 *
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
1294 * to a symbol.
1295 *
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>.
1300 *
1301 * class Klass
1302 * def hello(*args)
1303 * "Hello " + args.join(' ')
1304 * end
1305 * end
1306 * k = Klass.new
1307 * k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
1308 */
1309
1310 VALUE
1311rb_f_send(int argc, VALUE *argv, VALUE recv)
1312{
1313 return send_internal_kw(argc, argv, recv, CALL_FCALL);
1314}
1315
1316/*
1317 * call-seq:
1318 * obj.public_send(symbol [, args...]) -> obj
1319 * obj.public_send(string [, args...]) -> obj
1320 *
1321 * Invokes the method identified by _symbol_, passing it any
1322 * arguments specified. Unlike send, public_send calls public
1323 * methods only.
1324 * When the method is identified by a string, the string is converted
1325 * to a symbol.
1326 *
1327 * 1.public_send(:puts, "hello") # causes NoMethodError
1328 */
1329
1330static VALUE
1331rb_f_public_send(int argc, VALUE *argv, VALUE recv)
1332{
1333 return send_internal_kw(argc, argv, recv, CALL_PUBLIC);
1334}
1335
1336/* yield */
1337
1338static inline VALUE
1339rb_yield_0_kw(int argc, const VALUE * argv, int kw_splat)
1340{
1341 return vm_yield(GET_EC(), argc, argv, kw_splat);
1342}
1343
1344static inline VALUE
1345rb_yield_0(int argc, const VALUE * argv)
1346{
1347 return vm_yield(GET_EC(), argc, argv, RB_NO_KEYWORDS);
1348}
1349
1350 VALUE
1351rb_yield_1(VALUE val)
1352{
1353 return rb_yield_0(1, &val);
1354}
1355
1356 VALUE
1357rb_yield(VALUE val)
1358{
1359 if (UNDEF_P(val)) {
1360 return rb_yield_0(0, NULL);
1361 }
1362 else {
1363 return rb_yield_0(1, &val);
1364 }
1365}
1366
1367#undef rb_yield_values
1368 VALUE
1369rb_yield_values(int n, ...)
1370{
1371 if (n == 0) {
1372 return rb_yield_0(0, 0);
1373 }
1374 else {
1375 int i;
1376 VALUE *argv;
1377 va_list args;
1378 argv = ALLOCA_N(VALUE, n);
1379
1380 va_start(args, n);
1381 for (i=0; i<n; i++) {
1382 argv[i] = va_arg(args, VALUE);
1383 }
1384 va_end(args);
1385
1386 return rb_yield_0(n, argv);
1387 }
1388}
1389
1390 VALUE
1391rb_yield_values2(int argc, const VALUE *argv)
1392{
1393 return rb_yield_0(argc, argv);
1394}
1395
1396 VALUE
1397rb_yield_values_kw(int argc, const VALUE *argv, int kw_splat)
1398{
1399 return rb_yield_0_kw(argc, argv, kw_splat);
1400}
1401
1402 VALUE
1403rb_yield_splat(VALUE values)
1404{
1405 VALUE tmp = rb_check_array_type(values);
1406 VALUE v;
1407 if (NIL_P(tmp)) {
1408 rb_raise(rb_eArgError, "not an array");
1409 }
1410 v = rb_yield_0(RARRAY_LENINT(tmp), RARRAY_CONST_PTR(tmp));
1411 RB_GC_GUARD(tmp);
1412 return v;
1413}
1414
1415 VALUE
1416rb_yield_splat_kw(VALUE values, int kw_splat)
1417{
1418 VALUE tmp = rb_check_array_type(values);
1419 VALUE v;
1420 if (NIL_P(tmp)) {
1421 rb_raise(rb_eArgError, "not an array");
1422 }
1423 v = rb_yield_0_kw(RARRAY_LENINT(tmp), RARRAY_CONST_PTR(tmp), kw_splat);
1424 RB_GC_GUARD(tmp);
1425 return v;
1426}
1427
1428 VALUE
1429rb_yield_force_blockarg(VALUE values)
1430{
1431 return vm_yield_force_blockarg(GET_EC(), values);
1432}
1433
1434 VALUE
1435 rb_yield_block(RB_BLOCK_CALL_FUNC_ARGLIST(val, arg))
1436{
1437 return vm_yield_with_block(GET_EC(), argc, argv,
1438 NIL_P(blockarg) ? VM_BLOCK_HANDLER_NONE : blockarg,
1439 rb_keyword_given_p());
1440}
1441
1442static VALUE
1443loop_i(VALUE _)
1444{
1445 for (;;) {
1446 rb_yield_0(0, 0);
1447 }
1448 return Qnil;
1449}
1450
1451static VALUE
1452loop_stop(VALUE dummy, VALUE exc)
1453{
1454 return rb_attr_get(exc, id_result);
1455}
1456
1457static VALUE
1458rb_f_loop_size(VALUE self, VALUE args, VALUE eobj)
1459{
1460 return DBL2NUM(HUGE_VAL);
1461}
1462
1463/*
1464 * call-seq:
1465 * loop { block }
1466 * loop -> an_enumerator
1467 *
1468 * Repeatedly executes the block.
1469 *
1470 * If no block is given, an enumerator is returned instead.
1471 *
1472 * loop do
1473 * print "Input: "
1474 * line = gets
1475 * break if !line or line =~ /^q/i
1476 * # ...
1477 * end
1478 *
1479 * StopIteration raised in the block breaks the loop. In this case,
1480 * loop returns the "result" value stored in the exception.
1481 *
1482 * enum = Enumerator.new { |y|
1483 * y << "one"
1484 * y << "two"
1485 * :ok
1486 * }
1487 *
1488 * result = loop {
1489 * puts enum.next
1490 * } #=> :ok
1491 */
1492
1493static VALUE
1494rb_f_loop(VALUE self)
1495{
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);
1498}
1499
1500#if VMDEBUG
1501static const char *
1502vm_frametype_name(const rb_control_frame_t *cfp);
1503#endif
1504
1505static VALUE
1506rb_iterate0(VALUE (* it_proc) (VALUE), VALUE data1,
1507 const struct vm_ifunc *const ifunc,
1508 rb_execution_context_t *ec)
1509{
1510 enum ruby_tag_type state;
1511 volatile VALUE retval = Qnil;
1512 rb_control_frame_t *const cfp = ec->cfp;
1513
1514 EC_PUSH_TAG(ec);
1515 state = EC_EXEC_TAG();
1516 if (state == 0) {
1517 iter_retry:
1518 {
1519 VALUE block_handler;
1520
1521 if (ifunc) {
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);
1525 }
1526 else {
1527 block_handler = VM_CF_BLOCK_HANDLER(cfp);
1528 }
1529 vm_passed_block_handler_set(ec, block_handler);
1530 }
1531 retval = (*it_proc) (data1);
1532 }
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);
1536
1537 if (cfp == escape_cfp) {
1538 rb_vm_rewind_cfp(ec, cfp);
1539
1540 state = 0;
1541 ec->tag->state = TAG_NONE;
1542 ec->errinfo = Qnil;
1543
1544 if (state == TAG_RETRY) goto iter_retry;
1545 retval = THROW_DATA_VAL(err);
1546 }
1547 else if (0) {
1548 SDR(); fprintf(stderr, "%p, %p\n", (void *)cfp, (void *)escape_cfp);
1549 }
1550 }
1551 EC_POP_TAG();
1552
1553 if (state) {
1554 EC_JUMP_TAG(ec, state);
1555 }
1556 return retval;
1557}
1558
1559static VALUE
1560rb_iterate_internal(VALUE (* it_proc)(VALUE), VALUE data1,
1561 rb_block_call_func_t bl_proc, VALUE data2)
1562{
1563 return rb_iterate0(it_proc, data1,
1564 bl_proc ? rb_vm_ifunc_proc_new(bl_proc, (void *)data2) : 0,
1565 GET_EC());
1566}
1567
1568 VALUE
1569 rb_iterate(VALUE (* it_proc)(VALUE), VALUE data1,
1570 rb_block_call_func_t bl_proc, VALUE data2)
1571{
1572 return rb_iterate_internal(it_proc, data1, bl_proc, data2);
1573}
1574
1575 struct iter_method_arg {
1576 VALUE obj;
1577 ID mid;
1578 int argc;
1579 const VALUE *argv;
1580 int kw_splat;
1581};
1582
1583static VALUE
1584iterate_method(VALUE obj)
1585{
1586 const struct iter_method_arg * arg =
1587 (struct iter_method_arg *) obj;
1588
1589 return rb_call(arg->obj, arg->mid, arg->argc, arg->argv, arg->kw_splat ? CALL_FCALL_KW : CALL_FCALL);
1590}
1591
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);
1593
1594 VALUE
1595 rb_block_call(VALUE obj, ID mid, int argc, const VALUE * argv,
1596 rb_block_call_func_t bl_proc, VALUE data2)
1597{
1598 return rb_block_call_kw(obj, mid, argc, argv, bl_proc, data2, RB_NO_KEYWORDS);
1599}
1600
1601 VALUE
1602rb_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)
1604{
1605 struct iter_method_arg arg;
1606
1607 arg.obj = obj;
1608 arg.mid = mid;
1609 arg.argc = argc;
1610 arg.argv = argv;
1611 arg.kw_splat = kw_splat;
1612 return rb_iterate_internal(iterate_method, (VALUE)&arg, bl_proc, data2);
1613}
1614
1615 VALUE
1616rb_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,
1618 VALUE data2)
1619{
1620 struct iter_method_arg arg;
1621 struct vm_ifunc *block;
1622
1623 if (!bl_proc) rb_raise(rb_eArgError, "NULL lambda function");
1624 arg.obj = obj;
1625 arg.mid = mid;
1626 arg.argc = argc;
1627 arg.argv = argv;
1628 arg.kw_splat = 0;
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());
1631}
1632
1633static VALUE
1634iterate_check_method(VALUE obj)
1635{
1636 const struct iter_method_arg * arg =
1637 (struct iter_method_arg *) obj;
1638
1639 return rb_check_funcall(arg->obj, arg->mid, arg->argc, arg->argv);
1640}
1641
1642 VALUE
1643rb_check_block_call(VALUE obj, ID mid, int argc, const VALUE *argv,
1644 rb_block_call_func_t bl_proc, VALUE data2)
1645{
1646 struct iter_method_arg arg;
1647
1648 arg.obj = obj;
1649 arg.mid = mid;
1650 arg.argc = argc;
1651 arg.argv = argv;
1652 arg.kw_splat = 0;
1653 return rb_iterate_internal(iterate_check_method, (VALUE)&arg, bl_proc, data2);
1654}
1655
1656 VALUE
1657rb_each(VALUE obj)
1658{
1659 return rb_call(obj, idEach, 0, 0, CALL_FCALL);
1660}
1661
1662void rb_parser_warn_location(VALUE, int);
1663
1664static VALUE eval_default_path;
1665
1666static const rb_iseq_t *
1667eval_make_iseq(VALUE src, VALUE fname, int line, const rb_binding_t *bind,
1668 const struct rb_block *base_block)
1669{
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;
1673 rb_ast_t *ast;
1674 int isolated_depth = 0;
1675
1676 // Conditionally enable coverage depending on the current mode:
1677 VALUE coverage_enabled = RBOOL(rb_get_coverage_mode() & COVERAGE_TARGET_EVAL);
1678
1679 {
1680 int depth = 1;
1681 const VALUE *ep = vm_block_ep(base_block);
1682
1683 while (1) {
1684 if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ISOLATED)) {
1685 isolated_depth = depth;
1686 break;
1687 }
1688 else if (VM_ENV_LOCAL_P(ep)) {
1689 break;
1690 }
1691 ep = VM_ENV_PREV_EP(ep);
1692 depth++;
1693 }
1694 }
1695
1696 if (!fname) {
1697 fname = rb_source_location(&line);
1698 }
1699
1700 if (!UNDEF_P(fname)) {
1701 if (!NIL_P(fname)) fname = rb_fstring(fname);
1702 }
1703 else {
1704 fname = rb_fstring_lit("(eval)");
1705 if (!eval_default_path) {
1706 eval_default_path = rb_fstring_lit("(eval)");
1707 rb_gc_register_mark_object(eval_default_path);
1708 }
1709 fname = eval_default_path;
1710 coverage_enabled = Qfalse;
1711 }
1712
1713 rb_parser_set_context(parser, parent, FALSE);
1714 ast = rb_parser_compile_string_path(parser, fname, src, line);
1715 if (ast->body.root) {
1716 if (ast->body.compile_option == Qnil) {
1717 ast->body.compile_option = rb_obj_hide(rb_ident_hash_new());
1718 }
1719 rb_hash_aset(ast->body.compile_option, rb_sym_intern_ascii_cstr("coverage_enabled"), coverage_enabled);
1720
1721 iseq = rb_iseq_new_eval(&ast->body,
1722 ISEQ_BODY(parent)->location.label,
1723 fname, Qnil, line,
1724 parent, isolated_depth);
1725 }
1726 rb_ast_dispose(ast);
1727
1728 if (iseq != NULL) {
1729 if (0 && iseq) { /* for debug */
1730 VALUE disasm = rb_iseq_disasm(iseq);
1731 printf("%s\n", StringValuePtr(disasm));
1732 }
1733
1734 rb_exec_event_hook_script_compiled(GET_EC(), iseq, src);
1735 }
1736
1737 return iseq;
1738}
1739
1740static VALUE
1741eval_string_with_cref(VALUE self, VALUE src, rb_cref_t *cref, VALUE file, int line)
1742{
1743 rb_execution_context_t *ec = GET_EC();
1744 struct rb_block block;
1745 const rb_iseq_t *iseq;
1746 rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
1747 if (!cfp) {
1748 rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread");
1749 }
1750
1751 block.as.captured = *VM_CFP_TO_CAPTURED_BLOCK(cfp);
1752 block.as.captured.self = self;
1753 block.as.captured.code.iseq = cfp->iseq;
1754 block.type = block_type_iseq;
1755
1756 iseq = eval_make_iseq(src, file, line, NULL, &block);
1757 if (!iseq) {
1758 rb_exc_raise(ec->errinfo);
1759 }
1760
1761 /* TODO: what the code checking? */
1762 if (!cref && block.as.captured.code.val) {
1763 rb_cref_t *orig_cref = vm_get_cref(vm_block_ep(&block));
1764 cref = vm_cref_dup(orig_cref);
1765 }
1766 vm_set_eval_stack(ec, iseq, cref, &block);
1767
1768 /* kick */
1769 return vm_exec(ec, true);
1770}
1771
1772static VALUE
1773eval_string_with_scope(VALUE scope, VALUE src, VALUE file, int line)
1774{
1775 rb_execution_context_t *ec = GET_EC();
1776 rb_binding_t *bind = Check_TypedStruct(scope, &ruby_binding_data_type);
1777 const rb_iseq_t *iseq = eval_make_iseq(src, file, line, bind, &bind->block);
1778 if (!iseq) {
1779 rb_exc_raise(ec->errinfo);
1780 }
1781
1782 vm_set_eval_stack(ec, iseq, NULL, &bind->block);
1783
1784 /* save new env */
1785 if (ISEQ_BODY(iseq)->local_table_size > 0) {
1786 vm_bind_update_env(scope, bind, vm_make_env_object(ec, ec->cfp));
1787 }
1788
1789 /* kick */
1790 return vm_exec(ec, true);
1791}
1792
1793/*
1794 * call-seq:
1795 * eval(string [, binding [, filename [,lineno]]]) -> obj
1796 *
1797 * Evaluates the Ruby expression(s) in <em>string</em>. If
1798 * <em>binding</em> is given, which must be a Binding object, the
1799 * evaluation is performed in its context. If the optional
1800 * <em>filename</em> and <em>lineno</em> parameters are present, they
1801 * will be used when reporting syntax errors.
1802 *
1803 * def get_binding(str)
1804 * return binding
1805 * end
1806 * str = "hello"
1807 * eval "str + ' Fred'" #=> "hello Fred"
1808 * eval "str + ' Fred'", get_binding("bye") #=> "bye Fred"
1809 */
1810
1811 VALUE
1812rb_f_eval(int argc, const VALUE *argv, VALUE self)
1813{
1814 VALUE src, scope, vfile, vline;
1815 VALUE file = Qundef;
1816 int line = 1;
1817
1818 rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
1819 SafeStringValue(src);
1820 if (argc >= 3) {
1821 StringValue(vfile);
1822 }
1823 if (argc >= 4) {
1824 line = NUM2INT(vline);
1825 }
1826
1827 if (!NIL_P(vfile))
1828 file = vfile;
1829
1830 if (NIL_P(scope))
1831 return eval_string_with_cref(self, src, NULL, file, line);
1832 else
1833 return eval_string_with_scope(scope, src, file, line);
1834}
1835
1837 VALUE
1838ruby_eval_string_from_file(const char *str, const char *filename)
1839{
1840 VALUE file = filename ? rb_str_new_cstr(filename) : 0;
1841 rb_execution_context_t *ec = GET_EC();
1842 rb_control_frame_t *cfp = ec ? rb_vm_get_ruby_level_next_cfp(ec, ec->cfp) : NULL;
1843 VALUE self = cfp ? cfp->self : rb_vm_top_self();
1844 return eval_string_with_cref(self, rb_str_new2(str), NULL, file, 1);
1845}
1846
1847 VALUE
1848rb_eval_string(const char *str)
1849{
1850 return ruby_eval_string_from_file(str, "eval");
1851}
1852
1853static VALUE
1854eval_string_protect(VALUE str)
1855{
1856 return rb_eval_string((char *)str);
1857}
1858
1859 VALUE
1860rb_eval_string_protect(const char *str, int *pstate)
1861{
1862 return rb_protect(eval_string_protect, (VALUE)str, pstate);
1863}
1864
1865 struct eval_string_wrap_arg {
1866 VALUE top_self;
1867 VALUE klass;
1868 const char *str;
1869};
1870
1871static VALUE
1872eval_string_wrap_protect(VALUE data)
1873{
1874 const struct eval_string_wrap_arg *const arg = (struct eval_string_wrap_arg*)data;
1875 rb_cref_t *cref = rb_vm_cref_new_toplevel();
1876 cref->klass_or_self = arg->klass;
1877 return eval_string_with_cref(arg->top_self, rb_str_new_cstr(arg->str), cref, rb_str_new_cstr("eval"), 1);
1878}
1879
1880 VALUE
1881rb_eval_string_wrap(const char *str, int *pstate)
1882{
1883 int state;
1884 rb_thread_t *th = GET_THREAD();
1885 VALUE self = th->top_self;
1886 VALUE wrapper = th->top_wrapper;
1887 VALUE val;
1888 struct eval_string_wrap_arg data;
1889
1890 th->top_wrapper = rb_module_new();
1891 th->top_self = rb_obj_clone(rb_vm_top_self());
1892 rb_extend_object(th->top_self, th->top_wrapper);
1893
1894 data.top_self = th->top_self;
1895 data.klass = th->top_wrapper;
1896 data.str = str;
1897
1898 val = rb_protect(eval_string_wrap_protect, (VALUE)&data, &state);
1899
1900 th->top_self = self;
1901 th->top_wrapper = wrapper;
1902
1903 if (pstate) {
1904 *pstate = state;
1905 }
1906 else if (state != TAG_NONE) {
1907 EC_JUMP_TAG(th->ec, state);
1908 }
1909 return val;
1910}
1911
1912 VALUE
1913rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat)
1914{
1915 enum ruby_tag_type state;
1916 volatile VALUE val = Qnil; /* OK */
1917 rb_execution_context_t * volatile ec = GET_EC();
1918
1919 EC_PUSH_TAG(ec);
1920 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1921 if (!RB_TYPE_P(cmd, T_STRING)) {
1922 val = rb_funcallv_kw(cmd, idCall, RARRAY_LENINT(arg),
1923 RARRAY_CONST_PTR(arg), kw_splat);
1924 }
1925 else {
1926 val = eval_string_with_cref(rb_vm_top_self(), cmd, NULL, 0, 0);
1927 }
1928 }
1929 EC_POP_TAG();
1930
1931 if (state) EC_JUMP_TAG(ec, state);
1932 return val;
1933}
1934
1935/* block eval under the class/module context */
1936
1937static VALUE
1938yield_under(VALUE self, int singleton, int argc, const VALUE *argv, int kw_splat)
1939{
1940 rb_execution_context_t *ec = GET_EC();
1941 rb_control_frame_t *cfp = ec->cfp;
1942 VALUE block_handler = VM_CF_BLOCK_HANDLER(cfp);
1943 VALUE new_block_handler = 0;
1944 const struct rb_captured_block *captured = NULL;
1945 struct rb_captured_block new_captured;
1946 const VALUE *ep = NULL;
1947 rb_cref_t *cref;
1948 int is_lambda = FALSE;
1949
1950 if (block_handler != VM_BLOCK_HANDLER_NONE) {
1951 again:
1952 switch (vm_block_handler_type(block_handler)) {
1953 case block_handler_type_iseq:
1954 captured = VM_BH_TO_CAPT_BLOCK(block_handler);
1955 new_captured = *captured;
1956 new_block_handler = VM_BH_FROM_ISEQ_BLOCK(&new_captured);
1957 break;
1958 case block_handler_type_ifunc:
1959 captured = VM_BH_TO_CAPT_BLOCK(block_handler);
1960 new_captured = *captured;
1961 new_block_handler = VM_BH_FROM_IFUNC_BLOCK(&new_captured);
1962 break;
1963 case block_handler_type_proc:
1964 is_lambda = rb_proc_lambda_p(block_handler) != Qfalse;
1965 block_handler = vm_proc_to_block_handler(VM_BH_TO_PROC(block_handler));
1966 goto again;
1967 case block_handler_type_symbol:
1968 return rb_sym_proc_call(SYM2ID(VM_BH_TO_SYMBOL(block_handler)),
1969 argc, argv, kw_splat,
1970 VM_BLOCK_HANDLER_NONE);
1971 }
1972
1973 new_captured.self = self;
1974 ep = captured->ep;
1975
1976 VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(ec->cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler);
1977 }
1978
1979 VM_ASSERT(singleton || RB_TYPE_P(self, T_MODULE) || RB_TYPE_P(self, T_CLASS));
1980 cref = vm_cref_push(ec, self, ep, TRUE, singleton);
1981
1982 return vm_yield_with_cref(ec, argc, argv, kw_splat, cref, is_lambda);
1983}
1984
1985 VALUE
1986rb_yield_refine_block(VALUE refinement, VALUE refinements)
1987{
1988 rb_execution_context_t *ec = GET_EC();
1989 VALUE block_handler = VM_CF_BLOCK_HANDLER(ec->cfp);
1990
1991 if (vm_block_handler_type(block_handler) != block_handler_type_iseq) {
1992 rb_bug("rb_yield_refine_block: an iseq block is required");
1993 }
1994 else {
1995 const struct rb_captured_block *captured = VM_BH_TO_ISEQ_BLOCK(block_handler);
1996 struct rb_captured_block new_captured = *captured;
1997 VALUE new_block_handler = VM_BH_FROM_ISEQ_BLOCK(&new_captured);
1998 const VALUE *ep = captured->ep;
1999 rb_cref_t *cref = vm_cref_push(ec, refinement, ep, TRUE, FALSE);
2000 CREF_REFINEMENTS_SET(cref, refinements);
2001 VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(ec->cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler);
2002 new_captured.self = refinement;
2003 return vm_yield_with_cref(ec, 0, NULL, RB_NO_KEYWORDS, cref, FALSE);
2004 }
2005}
2006
2007/* string eval under the class/module context */
2008static VALUE
2009eval_under(VALUE self, int singleton, VALUE src, VALUE file, int line)
2010{
2011 rb_cref_t *cref = vm_cref_push(GET_EC(), self, NULL, FALSE, singleton);
2012 SafeStringValue(src);
2013
2014 return eval_string_with_cref(self, src, cref, file, line);
2015}
2016
2017static VALUE
2018specific_eval(int argc, const VALUE *argv, VALUE self, int singleton, int kw_splat)
2019{
2020 if (rb_block_given_p()) {
2021 rb_check_arity(argc, 0, 0);
2022 return yield_under(self, singleton, 1, &self, kw_splat);
2023 }
2024 else {
2025 VALUE file = Qundef;
2026 int line = 1;
2027 VALUE code;
2028
2029 rb_check_arity(argc, 1, 3);
2030 code = argv[0];
2031 SafeStringValue(code);
2032 if (argc > 2)
2033 line = NUM2INT(argv[2]);
2034 if (argc > 1) {
2035 file = argv[1];
2036 if (!NIL_P(file)) StringValue(file);
2037 }
2038 return eval_under(self, singleton, code, file, line);
2039 }
2040}
2041
2042/*
2043 * call-seq:
2044 * obj.instance_eval(string [, filename [, lineno]] ) -> obj
2045 * obj.instance_eval {|obj| block } -> obj
2046 *
2047 * Evaluates a string containing Ruby source code, or the given block,
2048 * within the context of the receiver (_obj_). In order to set the
2049 * context, the variable +self+ is set to _obj_ while
2050 * the code is executing, giving the code access to _obj_'s
2051 * instance variables and private methods.
2052 *
2053 * When <code>instance_eval</code> is given a block, _obj_ is also
2054 * passed in as the block's only argument.
2055 *
2056 * When <code>instance_eval</code> is given a +String+, the optional
2057 * second and third parameters supply a filename and starting line number
2058 * that are used when reporting compilation errors.
2059 *
2060 * class KlassWithSecret
2061 * def initialize
2062 * @secret = 99
2063 * end
2064 * private
2065 * def the_secret
2066 * "Ssssh! The secret is #{@secret}."
2067 * end
2068 * end
2069 * k = KlassWithSecret.new
2070 * k.instance_eval { @secret } #=> 99
2071 * k.instance_eval { the_secret } #=> "Ssssh! The secret is 99."
2072 * k.instance_eval {|obj| obj == self } #=> true
2073 */
2074
2075static VALUE
2076rb_obj_instance_eval_internal(int argc, const VALUE *argv, VALUE self)
2077{
2078 return specific_eval(argc, argv, self, TRUE, RB_PASS_CALLED_KEYWORDS);
2079}
2080
2081 VALUE
2082rb_obj_instance_eval(int argc, const VALUE *argv, VALUE self)
2083{
2084 return specific_eval(argc, argv, self, TRUE, RB_NO_KEYWORDS);
2085}
2086
2087/*
2088 * call-seq:
2089 * obj.instance_exec(arg...) {|var...| block } -> obj
2090 *
2091 * Executes the given block within the context of the receiver
2092 * (_obj_). In order to set the context, the variable +self+ is set
2093 * to _obj_ while the code is executing, giving the code access to
2094 * _obj_'s instance variables. Arguments are passed as block parameters.
2095 *
2096 * class KlassWithSecret
2097 * def initialize
2098 * @secret = 99
2099 * end
2100 * end
2101 * k = KlassWithSecret.new
2102 * k.instance_exec(5) {|x| @secret+x } #=> 104
2103 */
2104
2105static VALUE
2106rb_obj_instance_exec_internal(int argc, const VALUE *argv, VALUE self)
2107{
2108 return yield_under(self, TRUE, argc, argv, RB_PASS_CALLED_KEYWORDS);
2109}
2110
2111 VALUE
2112rb_obj_instance_exec(int argc, const VALUE *argv, VALUE self)
2113{
2114 return yield_under(self, TRUE, argc, argv, RB_NO_KEYWORDS);
2115}
2116
2117/*
2118 * call-seq:
2119 * mod.class_eval(string [, filename [, lineno]]) -> obj
2120 * mod.class_eval {|mod| block } -> obj
2121 * mod.module_eval(string [, filename [, lineno]]) -> obj
2122 * mod.module_eval {|mod| block } -> obj
2123 *
2124 * Evaluates the string or block in the context of _mod_, except that when
2125 * a block is given, constant/class variable lookup is not affected. This
2126 * can be used to add methods to a class. <code>module_eval</code> returns
2127 * the result of evaluating its argument. The optional _filename_ and
2128 * _lineno_ parameters set the text for error messages.
2129 *
2130 * class Thing
2131 * end
2132 * a = %q{def hello() "Hello there!" end}
2133 * Thing.module_eval(a)
2134 * puts Thing.new.hello()
2135 * Thing.module_eval("invalid code", "dummy", 123)
2136 *
2137 * <em>produces:</em>
2138 *
2139 * Hello there!
2140 * dummy:123:in `module_eval': undefined local variable
2141 * or method `code' for Thing:Class
2142 */
2143
2144static VALUE
2145rb_mod_module_eval_internal(int argc, const VALUE *argv, VALUE mod)
2146{
2147 return specific_eval(argc, argv, mod, FALSE, RB_PASS_CALLED_KEYWORDS);
2148}
2149
2150 VALUE
2151rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod)
2152{
2153 return specific_eval(argc, argv, mod, FALSE, RB_NO_KEYWORDS);
2154}
2155
2156/*
2157 * call-seq:
2158 * mod.module_exec(arg...) {|var...| block } -> obj
2159 * mod.class_exec(arg...) {|var...| block } -> obj
2160 *
2161 * Evaluates the given block in the context of the class/module.
2162 * The method defined in the block will belong to the receiver.
2163 * Any arguments passed to the method will be passed to the block.
2164 * This can be used if the block needs to access instance variables.
2165 *
2166 * class Thing
2167 * end
2168 * Thing.class_exec{
2169 * def hello() "Hello there!" end
2170 * }
2171 * puts Thing.new.hello()
2172 *
2173 * <em>produces:</em>
2174 *
2175 * Hello there!
2176 */
2177
2178static VALUE
2179rb_mod_module_exec_internal(int argc, const VALUE *argv, VALUE mod)
2180{
2181 return yield_under(mod, FALSE, argc, argv, RB_PASS_CALLED_KEYWORDS);
2182}
2183
2184 VALUE
2185rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod)
2186{
2187 return yield_under(mod, FALSE, argc, argv, RB_NO_KEYWORDS);
2188}
2189
2190/*
2191 * Document-class: UncaughtThrowError
2192 *
2193 * Raised when +throw+ is called with a _tag_ which does not have
2194 * corresponding +catch+ block.
2195 *
2196 * throw "foo", "bar"
2197 *
2198 * <em>raises the exception:</em>
2199 *
2200 * UncaughtThrowError: uncaught throw "foo"
2201 */
2202
2203static VALUE
2204uncaught_throw_init(int argc, const VALUE *argv, VALUE exc)
2205{
2206 rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);
2207 rb_call_super(argc - 2, argv + 2);
2208 rb_ivar_set(exc, id_tag, argv[0]);
2209 rb_ivar_set(exc, id_value, argv[1]);
2210 return exc;
2211}
2212
2213/*
2214 * call-seq:
2215 * uncaught_throw.tag -> obj
2216 *
2217 * Return the tag object which was called for.
2218 */
2219
2220static VALUE
2221uncaught_throw_tag(VALUE exc)
2222{
2223 return rb_ivar_get(exc, id_tag);
2224}
2225
2226/*
2227 * call-seq:
2228 * uncaught_throw.value -> obj
2229 *
2230 * Return the return value which was called for.
2231 */
2232
2233static VALUE
2234uncaught_throw_value(VALUE exc)
2235{
2236 return rb_ivar_get(exc, id_value);
2237}
2238
2239/*
2240 * call-seq:
2241 * uncaught_throw.to_s -> string
2242 *
2243 * Returns formatted message with the inspected tag.
2244 */
2245
2246static VALUE
2247uncaught_throw_to_s(VALUE exc)
2248{
2249 VALUE mesg = rb_attr_get(exc, id_mesg);
2250 VALUE tag = uncaught_throw_tag(exc);
2251 return rb_str_format(1, &tag, mesg);
2252}
2253
2254/*
2255 * call-seq:
2256 * throw(tag [, obj])
2257 *
2258 * Transfers control to the end of the active +catch+ block
2259 * waiting for _tag_. Raises +UncaughtThrowError+ if there
2260 * is no +catch+ block for the _tag_. The optional second
2261 * parameter supplies a return value for the +catch+ block,
2262 * which otherwise defaults to +nil+. For examples, see
2263 * Kernel::catch.
2264 */
2265
2266static VALUE
2267rb_f_throw(int argc, VALUE *argv, VALUE _)
2268{
2269 VALUE tag, value;
2270
2271 rb_scan_args(argc, argv, "11", &tag, &value);
2272 rb_throw_obj(tag, value);
2273 UNREACHABLE_RETURN(Qnil);
2274}
2275
2276void
2277rb_throw_obj(VALUE tag, VALUE value)
2278{
2279 rb_execution_context_t *ec = GET_EC();
2280 struct rb_vm_tag *tt = ec->tag;
2281
2282 while (tt) {
2283 if (tt->tag == tag) {
2284 tt->retval = value;
2285 break;
2286 }
2287 tt = tt->prev;
2288 }
2289 if (!tt) {
2290 VALUE desc[3];
2291 desc[0] = tag;
2292 desc[1] = value;
2293 desc[2] = rb_str_new_cstr("uncaught throw %p");
2294 rb_exc_raise(rb_class_new_instance(numberof(desc), desc, rb_eUncaughtThrow));
2295 }
2296
2297 ec->errinfo = (VALUE)THROW_DATA_NEW(tag, NULL, TAG_THROW);
2298 EC_JUMP_TAG(ec, TAG_THROW);
2299}
2300
2301void
2302rb_throw(const char *tag, VALUE val)
2303{
2304 rb_throw_obj(rb_sym_intern_ascii_cstr(tag), val);
2305}
2306
2307static VALUE
2308catch_i(RB_BLOCK_CALL_FUNC_ARGLIST(tag, _))
2309{
2310 return rb_yield_0(1, &tag);
2311}
2312
2313/*
2314 * call-seq:
2315 * catch([tag]) {|tag| block } -> obj
2316 *
2317 * +catch+ executes its block. If +throw+ is not called, the block executes
2318 * normally, and +catch+ returns the value of the last expression evaluated.
2319 *
2320 * catch(1) { 123 } # => 123
2321 *
2322 * If <code>throw(tag2, val)</code> is called, Ruby searches up its stack for
2323 * a +catch+ block whose +tag+ has the same +object_id+ as _tag2_. When found,
2324 * the block stops executing and returns _val_ (or +nil+ if no second argument
2325 * was given to +throw+).
2326 *
2327 * catch(1) { throw(1, 456) } # => 456
2328 * catch(1) { throw(1) } # => nil
2329 *
2330 * When +tag+ is passed as the first argument, +catch+ yields it as the
2331 * parameter of the block.
2332 *
2333 * catch(1) {|x| x + 2 } # => 3
2334 *
2335 * When no +tag+ is given, +catch+ yields a new unique object (as from
2336 * +Object.new+) as the block parameter. This object can then be used as the
2337 * argument to +throw+, and will match the correct +catch+ block.
2338 *
2339 * catch do |obj_A|
2340 * catch do |obj_B|
2341 * throw(obj_B, 123)
2342 * puts "This puts is not reached"
2343 * end
2344 *
2345 * puts "This puts is displayed"
2346 * 456
2347 * end
2348 *
2349 * # => 456
2350 *
2351 * catch do |obj_A|
2352 * catch do |obj_B|
2353 * throw(obj_A, 123)
2354 * puts "This puts is still not reached"
2355 * end
2356 *
2357 * puts "Now this puts is also not reached"
2358 * 456
2359 * end
2360 *
2361 * # => 123
2362 */
2363
2364static VALUE
2365rb_f_catch(int argc, VALUE *argv, VALUE self)
2366{
2367 VALUE tag = rb_check_arity(argc, 0, 1) ? argv[0] : rb_obj_alloc(rb_cObject);
2368 return rb_catch_obj(tag, catch_i, 0);
2369}
2370
2371 VALUE
2372 rb_catch(const char *tag, rb_block_call_func_t func, VALUE data)
2373{
2374 VALUE vtag = tag ? rb_sym_intern_ascii_cstr(tag) : rb_obj_alloc(rb_cObject);
2375 return rb_catch_obj(vtag, func, data);
2376}
2377
2378static VALUE
2379vm_catch_protect(VALUE tag, rb_block_call_func *func, VALUE data,
2380 enum ruby_tag_type *stateptr, rb_execution_context_t *volatile ec)
2381{
2382 enum ruby_tag_type state;
2383 VALUE val = Qnil; /* OK */
2384 rb_control_frame_t *volatile saved_cfp = ec->cfp;
2385
2386 EC_PUSH_TAG(ec);
2387
2388 _tag.tag = tag;
2389
2390 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
2391 /* call with argc=1, argv = [tag], block = Qnil to insure compatibility */
2392 val = (*func)(tag, data, 1, (const VALUE *)&tag, Qnil);
2393 }
2394 else if (state == TAG_THROW && THROW_DATA_VAL((struct vm_throw_data *)ec->errinfo) == tag) {
2395 rb_vm_rewind_cfp(ec, saved_cfp);
2396 val = ec->tag->retval;
2397 ec->errinfo = Qnil;
2398 state = 0;
2399 }
2400 EC_POP_TAG();
2401 if (stateptr)
2402 *stateptr = state;
2403
2404 return val;
2405}
2406
2407 VALUE
2408rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, enum ruby_tag_type *stateptr)
2409{
2410 return vm_catch_protect(t, func, data, stateptr, GET_EC());
2411}
2412
2413 VALUE
2414 rb_catch_obj(VALUE t, rb_block_call_func_t func, VALUE data)
2415{
2416 enum ruby_tag_type state;
2417 rb_execution_context_t *ec = GET_EC();
2418 VALUE val = vm_catch_protect(t, (rb_block_call_func *)func, data, &state, ec);
2419 if (state) EC_JUMP_TAG(ec, state);
2420 return val;
2421}
2422
2423static void
2424local_var_list_init(struct local_var_list *vars)
2425{
2426 vars->tbl = rb_ident_hash_new();
2427 RBASIC_CLEAR_CLASS(vars->tbl);
2428}
2429
2430static VALUE
2431local_var_list_finish(struct local_var_list *vars)
2432{
2433 /* TODO: not to depend on the order of st_table */
2434 VALUE ary = rb_hash_keys(vars->tbl);
2435 rb_hash_clear(vars->tbl);
2436 vars->tbl = 0;
2437 return ary;
2438}
2439
2440static int
2441local_var_list_update(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
2442{
2443 if (existing) return ST_STOP;
2444 *value = (st_data_t)Qtrue; /* INT2FIX(arg) */
2445 return ST_CONTINUE;
2446}
2447
2448static void
2449local_var_list_add(const struct local_var_list *vars, ID lid)
2450{
2451 if (lid && rb_is_local_id(lid)) {
2452 /* should skip temporary variable */
2453 st_data_t idx = 0; /* tbl->num_entries */
2454 rb_hash_stlike_update(vars->tbl, ID2SYM(lid), local_var_list_update, idx);
2455 }
2456}
2457
2458/*
2459 * call-seq:
2460 * local_variables -> array
2461 *
2462 * Returns the names of the current local variables.
2463 *
2464 * fred = 1
2465 * for i in 1..10
2466 * # ...
2467 * end
2468 * local_variables #=> [:fred, :i]
2469 */
2470
2471static VALUE
2472rb_f_local_variables(VALUE _)
2473{
2474 struct local_var_list vars;
2475 rb_execution_context_t *ec = GET_EC();
2476 rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp));
2477 unsigned int i;
2478
2479 local_var_list_init(&vars);
2480 while (cfp) {
2481 if (cfp->iseq) {
2482 for (i = 0; i < ISEQ_BODY(cfp->iseq)->local_table_size; i++) {
2483 local_var_list_add(&vars, ISEQ_BODY(cfp->iseq)->local_table[i]);
2484 }
2485 }
2486 if (!VM_ENV_LOCAL_P(cfp->ep)) {
2487 /* block */
2488 const VALUE *ep = VM_CF_PREV_EP(cfp);
2489
2490 if (vm_collect_local_variables_in_heap(ep, &vars)) {
2491 break;
2492 }
2493 else {
2494 while (cfp->ep != ep) {
2495 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
2496 }
2497 }
2498 }
2499 else {
2500 break;
2501 }
2502 }
2503 return local_var_list_finish(&vars);
2504}
2505
2506/*
2507 * call-seq:
2508 * block_given? -> true or false
2509 *
2510 * Returns <code>true</code> if <code>yield</code> would execute a
2511 * block in the current context. The <code>iterator?</code> form
2512 * is mildly deprecated.
2513 *
2514 * def try
2515 * if block_given?
2516 * yield
2517 * else
2518 * "no block"
2519 * end
2520 * end
2521 * try #=> "no block"
2522 * try { "hello" } #=> "hello"
2523 * try do "hello" end #=> "hello"
2524 */
2525
2526static VALUE
2527rb_f_block_given_p(VALUE _)
2528{
2529 rb_execution_context_t *ec = GET_EC();
2530 rb_control_frame_t *cfp = ec->cfp;
2531 cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
2532
2533 return RBOOL(cfp != NULL && VM_CF_BLOCK_HANDLER(cfp) != VM_BLOCK_HANDLER_NONE);
2534}
2535
2536/*
2537 * call-seq:
2538 * iterator? -> true or false
2539 *
2540 * Deprecated. Use block_given? instead.
2541 */
2542
2543static VALUE
2544rb_f_iterator_p(VALUE self)
2545{
2546 rb_warn_deprecated("iterator?", "block_given?");
2547 return rb_f_block_given_p(self);
2548}
2549
2550 VALUE
2551rb_current_realfilepath(void)
2552{
2553 const rb_execution_context_t *ec = GET_EC();
2554 rb_control_frame_t *cfp = ec->cfp;
2555 cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
2556 if (cfp != NULL) {
2557 VALUE path = rb_iseq_realpath(cfp->iseq);
2558 if (RTEST(path)) return path;
2559 // eval context
2560 path = rb_iseq_path(cfp->iseq);
2561 if (path == eval_default_path) {
2562 return Qnil;
2563 }
2564 else {
2565 return path;
2566 }
2567 }
2568 return Qnil;
2569}
2570
2571void
2572Init_vm_eval(void)
2573{
2574 rb_define_global_function("eval", rb_f_eval, -1);
2575 rb_define_global_function("local_variables", rb_f_local_variables, 0);
2576 rb_define_global_function("iterator?", rb_f_iterator_p, 0);
2577 rb_define_global_function("block_given?", rb_f_block_given_p, 0);
2578
2579 rb_define_global_function("catch", rb_f_catch, -1);
2580 rb_define_global_function("throw", rb_f_throw, -1);
2581
2582 rb_define_global_function("loop", rb_f_loop, 0);
2583
2584 rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval_internal, -1);
2585 rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec_internal, -1);
2586 rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
2587
2588#if 1
2589 rb_add_method(rb_cBasicObject, id__send__,
2590 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, METHOD_VISI_PUBLIC);
2591 rb_add_method(rb_mKernel, idSend,
2592 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, METHOD_VISI_PUBLIC);
2593#else
2594 rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
2595 rb_define_method(rb_mKernel, "send", rb_f_send, -1);
2596#endif
2597 rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
2598
2599 rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec_internal, -1);
2600 rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec_internal, -1);
2601 rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval_internal, -1);
2602 rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval_internal, -1);
2603
2604 rb_eUncaughtThrow = rb_define_class("UncaughtThrowError", rb_eArgError);
2605 rb_define_method(rb_eUncaughtThrow, "initialize", uncaught_throw_init, -1);
2606 rb_define_method(rb_eUncaughtThrow, "tag", uncaught_throw_tag, 0);
2607 rb_define_method(rb_eUncaughtThrow, "value", uncaught_throw_value, 0);
2608 rb_define_method(rb_eUncaughtThrow, "to_s", uncaught_throw_to_s, 0);
2609
2610 id_result = rb_intern_const("result");
2611 id_tag = rb_intern_const("tag");
2612 id_value = rb_intern_const("value");
2613}
2614
2615#endif /* #ifndef MJIT_HEADER */
rb_define_method
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition cxxanyargs.hpp:670
rb_define_private_method
#define rb_define_private_method(klass, mid, func, arity)
Defines klass#mid and makes it private.
Definition cxxanyargs.hpp:677
rb_define_global_function
#define rb_define_global_function(mid, func, arity)
Defines rb_mKernel #mid.
Definition cxxanyargs.hpp:695
RUBY_EVENT_C_CALL
#define RUBY_EVENT_C_CALL
A method, written in C, is called.
Definition event.h:39
RUBY_EVENT_C_RETURN
#define RUBY_EVENT_C_RETURN
Return from a method, written in C.
Definition event.h:40
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition class.c:923
rb_extend_object
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
Definition eval.c:1693
rb_module_new
VALUE rb_module_new(void)
Creates a new, anonymous module.
Definition class.c:1019
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
Definition class.c:2579
rb_keyword_given_p
int rb_keyword_given_p(void)
Determines if the current method is given a keyword argument.
Definition eval.c:881
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition eval.c:868
rb_str_new2
#define rb_str_new2
Old name of rb_str_new_cstr.
Definition string.h:1675
T_COMPLEX
#define T_COMPLEX
Old name of RUBY_T_COMPLEX.
Definition value_type.h:59
T_FILE
#define T_FILE
Old name of RUBY_T_FILE.
Definition value_type.h:62
T_STRING
#define T_STRING
Old name of RUBY_T_STRING.
Definition value_type.h:78
T_MASK
#define T_MASK
Old name of RUBY_T_MASK.
Definition value_type.h:68
Qundef
#define Qundef
Old name of RUBY_Qundef.
Definition special_consts.h:62
T_NIL
#define T_NIL
Old name of RUBY_T_NIL.
Definition value_type.h:72
T_FLOAT
#define T_FLOAT
Old name of RUBY_T_FLOAT.
Definition value_type.h:64
T_IMEMO
#define T_IMEMO
Old name of RUBY_T_IMEMO.
Definition value_type.h:67
ID2SYM
#define ID2SYM
Old name of RB_ID2SYM.
Definition symbol.h:44
T_BIGNUM
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
Definition value_type.h:57
SPECIAL_CONST_P
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
Definition special_consts.h:56
T_STRUCT
#define T_STRUCT
Old name of RUBY_T_STRUCT.
Definition value_type.h:79
OBJ_FREEZE
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
Definition fl_type.h:143
T_FIXNUM
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
Definition value_type.h:63
UNREACHABLE_RETURN
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
Definition assume.h:29
SYM2ID
#define SYM2ID
Old name of RB_SYM2ID.
Definition symbol.h:45
T_DATA
#define T_DATA
Old name of RUBY_T_DATA.
Definition value_type.h:60
CLASS_OF
#define CLASS_OF
Old name of rb_class_of.
Definition globals.h:203
T_NONE
#define T_NONE
Old name of RUBY_T_NONE.
Definition value_type.h:74
T_NODE
#define T_NODE
Old name of RUBY_T_NODE.
Definition value_type.h:73
rb_ary_new4
#define rb_ary_new4
Old name of rb_ary_new_from_values.
Definition array.h:653
T_MODULE
#define T_MODULE
Old name of RUBY_T_MODULE.
Definition value_type.h:70
T_TRUE
#define T_TRUE
Old name of RUBY_T_TRUE.
Definition value_type.h:81
T_RATIONAL
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
Definition value_type.h:76
T_ICLASS
#define T_ICLASS
Old name of RUBY_T_ICLASS.
Definition value_type.h:66
T_HASH
#define T_HASH
Old name of RUBY_T_HASH.
Definition value_type.h:65
T_FALSE
#define T_FALSE
Old name of RUBY_T_FALSE.
Definition value_type.h:61
T_UNDEF
#define T_UNDEF
Old name of RUBY_T_UNDEF.
Definition value_type.h:82
Qtrue
#define Qtrue
Old name of RUBY_Qtrue.
Definition special_consts.h:61
NUM2INT
#define NUM2INT
Old name of RB_NUM2INT.
Definition int.h:44
T_ZOMBIE
#define T_ZOMBIE
Old name of RUBY_T_ZOMBIE.
Definition value_type.h:83
Qnil
#define Qnil
Old name of RUBY_Qnil.
Definition special_consts.h:60
Qfalse
#define Qfalse
Old name of RUBY_Qfalse.
Definition special_consts.h:59
T_ARRAY
#define T_ARRAY
Old name of RUBY_T_ARRAY.
Definition value_type.h:56
T_OBJECT
#define T_OBJECT
Old name of RUBY_T_OBJECT.
Definition value_type.h:75
NIL_P
#define NIL_P
Old name of RB_NIL_P.
Definition special_consts.h:55
ALLOCV_N
#define ALLOCV_N
Old name of RB_ALLOCV_N.
Definition memory.h:399
T_SYMBOL
#define T_SYMBOL
Old name of RUBY_T_SYMBOL.
Definition value_type.h:80
DBL2NUM
#define DBL2NUM
Old name of rb_float_new.
Definition double.h:29
T_MATCH
#define T_MATCH
Old name of RUBY_T_MATCH.
Definition value_type.h:69
T_CLASS
#define T_CLASS
Old name of RUBY_T_CLASS.
Definition value_type.h:58
BUILTIN_TYPE
#define BUILTIN_TYPE
Old name of RB_BUILTIN_TYPE.
Definition value_type.h:85
T_MOVED
#define T_MOVED
Old name of RUBY_T_MOVED.
Definition value_type.h:71
Check_TypedStruct
#define Check_TypedStruct(v, t)
Old name of rb_check_typeddata.
Definition rtypeddata.h:105
ALLOCV_END
#define ALLOCV_END
Old name of RB_ALLOCV_END.
Definition memory.h:400
SYMBOL_P
#define SYMBOL_P
Old name of RB_SYMBOL_P.
Definition value_type.h:88
T_REGEXP
#define T_REGEXP
Old name of RUBY_T_REGEXP.
Definition value_type.h:77
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
Definition error.c:3150
rb_eNotImpError
VALUE rb_eNotImpError
NotImplementedError exception.
Definition error.c:1101
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition eval.c:688
rb_bug
void rb_bug(const char *fmt,...)
Interpreter panic switch.
Definition error.c:794
rb_eNameError
VALUE rb_eNameError
NameError exception.
Definition error.c:1096
rb_eNoMethodError
VALUE rb_eNoMethodError
NoMethodError exception.
Definition error.c:1099
rb_eRuntimeError
VALUE rb_eRuntimeError
RuntimeError exception.
Definition error.c:1089
rb_eStopIteration
VALUE rb_eStopIteration
StopIteration exception.
Definition enumerator.c:176
rb_eArgError
VALUE rb_eArgError
ArgumentError exception.
Definition error.c:1092
rb_mKernel
VALUE rb_mKernel
Kernel module.
Definition object.c:51
rb_obj_alloc
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
Definition object.c:1940
rb_class_new_instance
VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
Allocates, then initialises an instance of the given class.
Definition object.c:1981
rb_obj_hide
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition object.c:84
rb_obj_class
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition object.c:191
rb_cBasicObject
VALUE rb_cBasicObject
BasicObject class.
Definition object.c:50
rb_cModule
VALUE rb_cModule
Module class.
Definition object.c:53
rb_obj_clone
VALUE rb_obj_clone(VALUE obj)
Produces a shallow copy of the given object.
Definition object.c:442
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
Definition object.c:788
rb_eval_string_wrap
VALUE rb_eval_string_wrap(const char *str, int *state)
Identical to rb_eval_string_protect(), except it evaluates the given string under a module binding in...
Definition vm_eval.c:1881
rb_funcall_passing_block
VALUE rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv_public(), except you can pass the passed block.
Definition vm_eval.c:1165
rb_funcall
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition vm_eval.c:1102
rb_funcallv_kw
VALUE rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
Identical to rb_funcallv(), except you can specify how to handle the last element of the given array.
Definition vm_eval.c:1069
rb_funcall_with_block
VALUE rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE procval)
Identical to rb_funcallv_public(), except you can pass a block.
Definition vm_eval.c:1179
rb_eval_string_protect
VALUE rb_eval_string_protect(const char *str, int *state)
Identical to rb_eval_string(), except it avoids potential global escapes.
Definition vm_eval.c:1860
rb_call_super_kw
VALUE rb_call_super_kw(int argc, const VALUE *argv, int kw_splat)
Identical to rb_call_super(), except you can specify how to handle the last element of the given arra...
Definition vm_eval.c:331
rb_funcallv_public
VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it only takes public methods into account.
Definition vm_eval.c:1153
rb_current_receiver
VALUE rb_current_receiver(void)
This resembles ruby's self.
Definition vm_eval.c:345
rb_funcall_passing_block_kw
VALUE rb_funcall_passing_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
Identical to rb_funcallv_passing_block(), except you can specify how to handle the last element of th...
Definition vm_eval.c:1172
rb_funcall_with_block_kw
VALUE rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE procval, int kw_splat)
Identical to rb_funcallv_with_block(), except you can specify how to handle the last element of the g...
Definition vm_eval.c:1189
rb_eval_string
VALUE rb_eval_string(const char *str)
Evaluates the given string.
Definition vm_eval.c:1848
rb_call_super
VALUE rb_call_super(int argc, const VALUE *argv)
This resembles ruby's super.
Definition vm_eval.c:339
rb_funcallv_public_kw
VALUE rb_funcallv_public_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
Identical to rb_funcallv_public(), except you can specify how to handle the last element of the given...
Definition vm_eval.c:1159
RETURN_SIZED_ENUMERATOR
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
This roughly resembles return enum_for(__callee__) unless block_given?.
Definition enumerator.h:206
UNLIMITED_ARGUMENTS
#define UNLIMITED_ARGUMENTS
This macro is used in conjunction with rb_check_arity().
Definition error.h:35
rb_check_arity
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition error.h:280
rb_is_local_id
int rb_is_local_id(ID id)
Classifies the given ID, then sees if it is a local variable.
Definition symbol.c:1061
rb_proc_lambda_p
VALUE rb_proc_lambda_p(VALUE recv)
Queries if the given object is a lambda.
Definition proc.c:293
rb_str_new_cstr
#define rb_str_new_cstr(str)
Identical to rb_str_new, except it assumes the passed pointer is a pointer to a C string.
Definition string.h:1514
rb_str_intern
VALUE rb_str_intern(VALUE str)
Identical to rb_to_symbol(), except it assumes the receiver being an instance of RString.
Definition symbol.c:851
rb_attr_get
VALUE rb_attr_get(VALUE obj, ID name)
Identical to rb_ivar_get()
Definition variable.c:1226
rb_ivar_set
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
Definition variable.c:1606
rb_ivar_get
VALUE rb_ivar_get(VALUE obj, ID name)
Identical to rb_iv_get(), except it accepts the name as an ID instead of a C string.
Definition variable.c:1218
rb_check_funcall
VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it returns RUBY_Qundef instead of raising rb_eNoMethodError.
Definition vm_eval.c:664
rb_check_funcall_kw
VALUE rb_check_funcall_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
Identical to rb_check_funcall(), except you can specify how to handle the last element of the given a...
Definition vm_eval.c:658
rb_mod_module_eval
VALUE rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod)
Identical to rb_obj_instance_eval(), except it evaluates within the context of module.
Definition vm_eval.c:2151
rb_mod_module_exec
VALUE rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod)
Identical to rb_obj_instance_exec(), except it evaluates within the context of module.
Definition vm_eval.c:2185
rb_obj_instance_exec
VALUE rb_obj_instance_exec(int argc, const VALUE *argv, VALUE recv)
Executes the given block within the context of the receiver.
Definition vm_eval.c:2112
rb_eval_cmd_kw
VALUE rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat)
This API is practically a variant of rb_proc_call_kw() now.
Definition vm_eval.c:1913
rb_apply
VALUE rb_apply(VALUE recv, ID mid, VALUE args)
Identical to rb_funcallv(), except it takes Ruby's array instead of C's.
Definition vm_eval.c:1077
rb_obj_instance_eval
VALUE rb_obj_instance_eval(int argc, const VALUE *argv, VALUE recv)
Evaluates a string containing Ruby source code, or the given block, within the context of the receive...
Definition vm_eval.c:2082
rb_intern_const
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
Definition symbol.h:276
rb_check_id
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
Definition symbol.c:1085
rb_str_format
VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt)
Formats a string.
Definition sprintf.c:214
RB_BLOCK_CALL_FUNC_ARGLIST
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
Definition iterator.h:58
rb_each
VALUE rb_each(VALUE obj)
This is a shorthand of calling obj.each.
Definition vm_eval.c:1657
rb_yield_values
VALUE rb_yield_values(int n,...)
Identical to rb_yield(), except it takes variadic number of parameters and pass them to the block.
Definition vm_eval.c:1369
rb_yield_splat
VALUE rb_yield_splat(VALUE ary)
Identical to rb_yield_values(), except it splats an array to generate the list of parameters.
Definition vm_eval.c:1403
rb_throw
void rb_throw(const char *tag, VALUE val)
Transfers control to the end of the active catch block waiting for tag.
Definition vm_eval.c:2302
rb_yield_values2
VALUE rb_yield_values2(int n, const VALUE *argv)
Identical to rb_yield_values(), except it takes the parameters as a C array instead of variadic argum...
Definition vm_eval.c:1391
rb_yield
VALUE rb_yield(VALUE val)
Yields the block.
Definition vm_eval.c:1357
rb_yield_values_kw
VALUE rb_yield_values_kw(int n, const VALUE *argv, int kw_splat)
Identical to rb_yield_values2(), except you can specify how to handle the last element of the given a...
Definition vm_eval.c:1397
rb_block_call_func_t
rb_block_call_func * rb_block_call_func_t
Shorthand type that represents an iterator-written-in-C function pointer.
Definition iterator.h:88
rb_yield_block
VALUE rb_yield_block(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
Pass a passed block.
rb_throw_obj
void rb_throw_obj(VALUE tag, VALUE val)
Identical to rb_throw(), except it allows arbitrary Ruby object to become a tag.
Definition vm_eval.c:2277
rb_block_call_func
VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
This is the type of a function that the interpreter expect for C-backended blocks.
Definition iterator.h:83
rb_block_call_kw
VALUE rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2, int kw_splat)
Identical to rb_funcallv_kw(), except it additionally passes a function as a block.
Definition vm_eval.c:1602
rb_yield_splat_kw
VALUE rb_yield_splat_kw(VALUE ary, int kw_splat)
Identical to rb_yield_splat(), except you can specify how to handle the last element of the given arr...
Definition vm_eval.c:1416
MEMCPY
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
Definition memory.h:366
ALLOCA_N
#define ALLOCA_N(type, n)
Definition memory.h:286
RB_GC_GUARD
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition memory.h:161
ruby::backward::cxxanyargs::rb_catch_obj
VALUE rb_catch_obj(VALUE q, type *w, VALUE e)
An equivalent of Kernel#catch.
Definition cxxanyargs.hpp:358
ruby::backward::cxxanyargs::rb_catch
VALUE rb_catch(const char *q, type *w, VALUE e)
An equivalent of Kernel#catch.
Definition cxxanyargs.hpp:331
ruby::backward::cxxanyargs::rb_block_call
VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
Call a method with a block.
Definition cxxanyargs.hpp:232
ruby::backward::cxxanyargs::rb_iterate
VALUE rb_iterate(onearg_type *q, VALUE w, type *e, VALUE r)
Old way to implement iterators.
Definition cxxanyargs.hpp:205
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition cxxanyargs.hpp:56
ruby::backward::cxxanyargs::rb_rescue2
VALUE rb_rescue2(type *q, VALUE w, type *e, VALUE r,...)
An equivalent of rescue clause.
Definition cxxanyargs.hpp:284
RARRAY_CONST_PTR_TRANSIENT
#define RARRAY_CONST_PTR_TRANSIENT
Just another name of rb_array_const_ptr_transient.
Definition rarray.h:70
RARRAY_LENINT
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
Definition rarray.h:343
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
Definition rarray.h:69
RBASIC_CLASS
static VALUE RBASIC_CLASS(VALUE obj)
Queries the class of an object.
Definition rbasic.h:152
RBASIC
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
RCLASS_SUPER
#define RCLASS_SUPER
Just another name of rb_class_get_superclass.
Definition rclass.h:44
RHASH_EMPTY_P
#define RHASH_EMPTY_P(h)
Checks if the hash is empty.
Definition rhash.h:92
SafeStringValue
#define SafeStringValue(v)
Definition rstring.h:104
StringValue
#define StringValue(v)
Ensures that the parameter object is a String.
Definition rstring.h:72
StringValuePtr
#define StringValuePtr(v)
Identical to StringValue, except it returns a char*.
Definition rstring.h:82
RB_PASS_CALLED_KEYWORDS
#define RB_PASS_CALLED_KEYWORDS
Pass keywords if current method is called with keywords, useful for argument delegation.
Definition scan_args.h:78
RB_NO_KEYWORDS
#define RB_NO_KEYWORDS
Do not pass keywords.
Definition scan_args.h:69
RTEST
#define RTEST
This is an old name of RB_TEST.
Definition special_consts.h:51
_
#define _(args)
This was a transition path from K&R to ANSI.
Definition stdarg.h:35
eval_string_wrap_arg
Definition vm_eval.c:1865
iter_method_arg
Definition vm_eval.c:1575
local_var_list
Definition vm_eval.c:15
rb_ast_struct
Definition node.h:412
rb_binding_t
Definition vm_core.h:1163
rb_block
Definition vm_core.h:809
rb_callable_method_entry_struct
Definition method.h:62
rb_callcache
Definition vm_callinfo.h:275
rb_callinfo
Definition vm_callinfo.h:62
rb_calling_info
Definition vm_core.h:294
rb_captured_block
Definition vm_core.h:785
rb_class_cc_entries
Definition vm_callinfo.h:501
rb_control_frame_struct
Definition vm_core.h:818
rb_cref_struct
CREF (Class REFerence)
Definition method.h:44
rb_execution_context_struct
Definition vm_core.h:899
rb_id_table
Definition id_table.c:41
rb_iseq_struct
Definition vm_core.h:526
rb_method_cfunc_struct
Definition method.h:139
rb_proc_t
Definition vm_core.h:1137
rb_thread_struct
Definition vm_core.h:984
rb_vm_struct
Definition vm_core.h:615
rb_vm_tag
Definition vm_core.h:859
rescue_funcall_args
Definition vm_eval.c:553
vm_ifunc
IFUNC (Internal FUNCtion)
Definition imemo.h:84
vm_throw_data
THROW_DATA.
Definition imemo.h:62
ID
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition value.h:52
VALUE
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
RB_TYPE_P
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition value_type.h:375
ruby_value_type
ruby_value_type
C-level type of an object.
Definition value_type.h:112