Ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e0ba6b95ab71a441357ed5484e33498)
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
14struct local_var_list {
15 VALUE tbl;
16};
17
18static 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);
19static 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);
20static inline VALUE vm_yield(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_splat);
21static inline VALUE vm_yield_with_block(rb_execution_context_t *ec, int argc, const VALUE *argv, VALUE block_handler, int kw_splat);
22static inline VALUE vm_yield_force_blockarg(rb_execution_context_t *ec, VALUE args);
23VALUE vm_exec(rb_execution_context_t *ec, bool mjit_enable_p);
24static 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);
25static int vm_collect_local_variables_in_heap(const VALUE *dfp, const struct local_var_list *vars);
26
27static VALUE rb_eUncaughtThrow;
28static ID id_result, id_tag, id_value;
29#define id_mesg idMesg
30
31typedef enum call_type {
32 CALL_PUBLIC,
33 CALL_FCALL,
34 CALL_VCALL,
35 CALL_PUBLIC_KW,
36 CALL_FCALL_KW,
37 CALL_TYPE_MAX
38} call_type;
39
40static VALUE send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope);
41static VALUE vm_call0_body(rb_execution_context_t* ec, struct rb_calling_info *calling, const VALUE *argv);
42
43#ifndef MJIT_HEADER
44
45MJIT_FUNC_EXPORTED VALUE
46rb_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)
47{
48 struct rb_calling_info calling = {
49 .ci = &VM_CI_ON_STACK(id, kw_splat ? VM_CALL_KW_SPLAT : 0, argc, NULL),
50 .cc = &VM_CC_ON_STACK(Qfalse, vm_call_general, { 0 }, cme),
51 .block_handler = vm_passed_block_handler(ec),
52 .recv = recv,
53 .argc = argc,
54 .kw_splat = kw_splat,
55 };
56
57 return vm_call0_body(ec, &calling, argv);
58}
59
60MJIT_FUNC_EXPORTED VALUE
61rb_vm_call_with_refinements(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE *argv, int kw_splat)
62{
64 rb_callable_method_entry_with_refinements(CLASS_OF(recv), id, NULL);
65 if (me) {
66 return rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat);
67 }
68 else {
69 /* fallback to funcall (e.g. method_missing) */
70 return rb_funcallv(recv, id, argc, argv);
71 }
72}
73
74static inline VALUE
75vm_call0_cc(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE *argv, const struct rb_callcache *cc, int kw_splat)
76{
77 struct rb_calling_info calling = {
78 .ci = &VM_CI_ON_STACK(id, kw_splat ? VM_CALL_KW_SPLAT : 0, argc, NULL),
79 .cc = cc,
80 .block_handler = vm_passed_block_handler(ec),
81 .recv = recv,
82 .argc = argc,
83 .kw_splat = kw_splat,
84 };
85
86 return vm_call0_body(ec, &calling, argv);
87}
88
89static VALUE
90vm_call0_cme(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv, const rb_callable_method_entry_t *cme)
91{
92 calling->cc = &VM_CC_ON_STACK(Qfalse, vm_call_general, { 0 }, cme);
93 return vm_call0_body(ec, calling, argv);
94}
95
96static VALUE
97vm_call0_super(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv, VALUE klass, enum method_missing_reason ex)
98{
99 ID mid = vm_ci_mid(calling->ci);
100 klass = RCLASS_SUPER(klass);
101
102 if (klass) {
103 const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
104
105 if (cme) {
106 RUBY_VM_CHECK_INTS(ec);
107 return vm_call0_cme(ec, calling, argv, cme);
108 }
109 }
110
111 vm_passed_block_handler_set(ec, calling->block_handler);
112 return method_missing(ec, calling->recv, mid, calling->argc, argv, ex, calling->kw_splat);
113}
114
115static VALUE
116vm_call0_cfunc_with_frame(rb_execution_context_t* ec, struct rb_calling_info *calling, const VALUE *argv)
117{
118 const struct rb_callinfo *ci = calling->ci;
119 VALUE val;
120 const rb_callable_method_entry_t *me = vm_cc_cme(calling->cc);
121 const rb_method_cfunc_t *cfunc = UNALIGNED_MEMBER_PTR(me->def, body.cfunc);
122 int len = cfunc->argc;
123 VALUE recv = calling->recv;
124 int argc = calling->argc;
125 ID mid = vm_ci_mid(ci);
126 VALUE block_handler = calling->block_handler;
127 int frame_flags = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
128
129 if (calling->kw_splat) {
130 if (argc > 0 && RB_TYPE_P(argv[argc-1], T_HASH) && RHASH_EMPTY_P(argv[argc-1])) {
131 argc--;
132 }
133 else {
134 frame_flags |= VM_FRAME_FLAG_CFRAME_KW;
135 }
136 }
137
138 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id);
139 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, recv, me->def->original_id, mid, me->owner, Qnil);
140 {
141 rb_control_frame_t *reg_cfp = ec->cfp;
142
143 vm_push_frame(ec, 0, frame_flags, recv,
144 block_handler, (VALUE)me,
145 0, reg_cfp->sp, 0, 0);
146
147 if (len >= 0) rb_check_arity(argc, len, len);
148
149 val = (*cfunc->invoker)(recv, argc, argv, cfunc->func);
150
151 CHECK_CFP_CONSISTENCY("vm_call0_cfunc_with_frame");
152 rb_vm_pop_frame(ec);
153 }
154 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, recv, me->def->original_id, mid, me->owner, val);
155 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, me->owner, me->def->original_id);
156
157 return val;
158}
159
160static VALUE
161vm_call0_cfunc(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv)
162{
163 return vm_call0_cfunc_with_frame(ec, calling, argv);
164}
165
166static void
167vm_call_check_arity(struct rb_calling_info *calling, int argc, const VALUE *argv)
168{
169 if (calling->kw_splat &&
170 calling->argc > 0 &&
171 RB_TYPE_P(argv[calling->argc-1], T_HASH) &&
172 RHASH_EMPTY_P(argv[calling->argc-1])) {
173 calling->argc--;
174 }
175
176 rb_check_arity(calling->argc, argc, argc);
177}
178
179/* `ci' should point temporal value (on stack value) */
180static VALUE
181vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv)
182{
183 const struct rb_callinfo *ci = calling->ci;
184 const struct rb_callcache *cc = calling->cc;
185 VALUE ret;
186
187 retry:
188
189 switch (vm_cc_cme(cc)->def->type) {
190 case VM_METHOD_TYPE_ISEQ:
191 {
192 rb_control_frame_t *reg_cfp = ec->cfp;
193 int i;
194
195 CHECK_VM_STACK_OVERFLOW(reg_cfp, calling->argc + 1);
196 vm_check_canary(ec, reg_cfp->sp);
197
198 *reg_cfp->sp++ = calling->recv;
199 for (i = 0; i < calling->argc; i++) {
200 *reg_cfp->sp++ = argv[i];
201 }
202
203 vm_call_iseq_setup(ec, reg_cfp, calling);
204 VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);
205 return vm_exec(ec, true); /* CHECK_INTS in this function */
206 }
207 case VM_METHOD_TYPE_NOTIMPLEMENTED:
208 case VM_METHOD_TYPE_CFUNC:
209 ret = vm_call0_cfunc(ec, calling, argv);
210 goto success;
211 case VM_METHOD_TYPE_ATTRSET:
212 vm_call_check_arity(calling, 1, argv);
213 VM_CALL_METHOD_ATTR(ret,
214 rb_ivar_set(calling->recv, vm_cc_cme(cc)->def->body.attr.id, argv[0]),
215 (void)0);
216 goto success;
217 case VM_METHOD_TYPE_IVAR:
218 vm_call_check_arity(calling, 0, argv);
219 VM_CALL_METHOD_ATTR(ret,
220 rb_attr_get(calling->recv, vm_cc_cme(cc)->def->body.attr.id),
221 (void)0);
222 goto success;
223 case VM_METHOD_TYPE_BMETHOD:
224 ret = vm_call_bmethod_body(ec, calling, argv);
225 goto success;
226 case VM_METHOD_TYPE_ZSUPER:
227 {
228 VALUE klass = RCLASS_ORIGIN(vm_cc_cme(cc)->defined_class);
229 return vm_call0_super(ec, calling, argv, klass, MISSING_SUPER);
230 }
231 case VM_METHOD_TYPE_REFINED:
232 {
233 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
234
235 if (cme->def->body.refined.orig_me) {
236 const rb_callable_method_entry_t *orig_cme = refined_method_callable_without_refinement(cme);
237 return vm_call0_cme(ec, calling, argv, orig_cme);
238 }
239
240 VALUE klass = cme->defined_class;
241 return vm_call0_super(ec, calling, argv, klass, 0);
242 }
243 case VM_METHOD_TYPE_ALIAS:
244 {
245 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
246 const rb_callable_method_entry_t *orig_cme = aliased_callable_method_entry(cme);
247
248 if (cme == orig_cme) rb_bug("same!!");
249
250 if (vm_cc_markable(cc)) {
251 return vm_call0_cme(ec, calling, argv, orig_cme);
252 }
253 else {
254 *((const rb_callable_method_entry_t **)&cc->cme_) = orig_cme;
255 goto retry;
256 }
257 }
258 case VM_METHOD_TYPE_MISSING:
259 {
260 vm_passed_block_handler_set(ec, calling->block_handler);
261 return method_missing(ec, calling->recv, vm_ci_mid(ci), calling->argc,
262 argv, MISSING_NOENTRY, calling->kw_splat);
263 }
264 case VM_METHOD_TYPE_OPTIMIZED:
265 switch (vm_cc_cme(cc)->def->body.optimized.type) {
266 case OPTIMIZED_METHOD_TYPE_SEND:
267 ret = send_internal(calling->argc, argv, calling->recv, calling->kw_splat ? CALL_FCALL_KW : CALL_FCALL);
268 goto success;
269 case OPTIMIZED_METHOD_TYPE_CALL:
270 {
271 rb_proc_t *proc;
272 GetProcPtr(calling->recv, proc);
273 ret = rb_vm_invoke_proc(ec, proc, calling->argc, argv, calling->kw_splat, calling->block_handler);
274 goto success;
275 }
276 case OPTIMIZED_METHOD_TYPE_STRUCT_AREF:
277 vm_call_check_arity(calling, 0, argv);
278 ret = vm_call_opt_struct_aref0(ec, calling);
279 goto success;
280 case OPTIMIZED_METHOD_TYPE_STRUCT_ASET:
281 vm_call_check_arity(calling, 1, argv);
282 ret = vm_call_opt_struct_aset0(ec, calling, argv[0]);
283 goto success;
284 default:
285 rb_bug("vm_call0: unsupported optimized method type (%d)", vm_cc_cme(cc)->def->body.optimized.type);
286 }
287 break;
288 case VM_METHOD_TYPE_UNDEF:
289 break;
290 }
291 rb_bug("vm_call0: unsupported method type (%d)", vm_cc_cme(cc)->def->type);
292 return Qundef;
293
294 success:
295 RUBY_VM_CHECK_INTS(ec);
296 return ret;
297}
298
299MJIT_FUNC_EXPORTED VALUE
300rb_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)
301{
302 return rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat);
303}
304
305static inline VALUE
306vm_call_super(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_splat)
307{
308 VALUE recv = ec->cfp->self;
309 VALUE klass;
310 ID id;
311 rb_control_frame_t *cfp = ec->cfp;
312 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
313
314 if (VM_FRAME_RUBYFRAME_P(cfp)) {
315 rb_bug("vm_call_super: should not be reached");
316 }
317
318 klass = RCLASS_ORIGIN(me->defined_class);
319 klass = RCLASS_SUPER(klass);
320 id = me->def->original_id;
321 me = rb_callable_method_entry(klass, id);
322
323 if (!me) {
324 return method_missing(ec, recv, id, argc, argv, MISSING_SUPER, kw_splat);
325 }
326 return rb_vm_call_kw(ec, recv, id, argc, argv, me, kw_splat);
327}
328
329VALUE
330rb_call_super_kw(int argc, const VALUE *argv, int kw_splat)
331{
332 rb_execution_context_t *ec = GET_EC();
333 PASS_PASSED_BLOCK_HANDLER_EC(ec);
334 return vm_call_super(ec, argc, argv, kw_splat);
335}
336
337VALUE
338rb_call_super(int argc, const VALUE *argv)
339{
340 return rb_call_super_kw(argc, argv, RB_NO_KEYWORDS);
341}
342
343VALUE
345{
346 const rb_execution_context_t *ec = GET_EC();
348 if (!ec || !(cfp = ec->cfp)) {
349 rb_raise(rb_eRuntimeError, "no self, no life");
350 }
351 return cfp->self;
352}
353
354#endif /* #ifndef MJIT_HEADER */
355
356static inline void
357stack_check(rb_execution_context_t *ec)
358{
359 if (!rb_ec_raised_p(ec, RAISED_STACKOVERFLOW) &&
360 rb_ec_stack_check(ec)) {
361 rb_ec_raised_set(ec, RAISED_STACKOVERFLOW);
362 rb_ec_stack_overflow(ec, FALSE);
363 }
364}
365
366#ifndef MJIT_HEADER
367
368void
369rb_check_stack_overflow(void)
370{
371#ifndef RB_THREAD_LOCAL_SPECIFIER
372 if (!ruby_current_ec_key) return;
373#endif
374 rb_execution_context_t *ec = GET_EC();
375 if (ec) stack_check(ec);
376}
377
378NORETURN(static void uncallable_object(VALUE recv, ID mid));
379static inline const rb_callable_method_entry_t *rb_search_method_entry(VALUE recv, ID mid);
380static 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);
381
382static const struct rb_callcache *
383cc_new(VALUE klass, ID mid, int argc, const rb_callable_method_entry_t *cme)
384{
385 const struct rb_callcache *cc = NULL;
386
387 RB_VM_LOCK_ENTER();
388 {
389 struct rb_class_cc_entries *ccs;
390 struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass);
391 VALUE ccs_data;
392
393 if (rb_id_table_lookup(cc_tbl, mid, &ccs_data)) {
394 // ok
395 ccs = (struct rb_class_cc_entries *)ccs_data;
396 }
397 else {
398 ccs = vm_ccs_create(klass, cme);
399 rb_id_table_insert(cc_tbl, mid, (VALUE)ccs);
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, false); // TODO: proper ci
412 cc = vm_cc_new(klass, cme, vm_call_general);
413 METHOD_ENTRY_CACHED_SET((struct rb_callable_method_entry_struct *)cme);
414 vm_ccs_push(klass, ccs, ci, cc);
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
554 VALUE defined_class;
555 VALUE recv;
556 ID mid;
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;
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 = (ret != Qundef);
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
657VALUE
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
663VALUE
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);
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 (ret == Qundef) 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
693VALUE
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
699VALUE
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);
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)(ret != Qundef, 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
725VALUE
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 (self == Qundef || !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);
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);
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);
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
1060VALUE
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
1068VALUE
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
1076VALUE
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
1101VALUE
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
1135VALUE
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;
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
1152VALUE
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
1158VALUE
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
1164VALUE
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
1171VALUE
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
1178VALUE
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
1188VALUE
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
1310VALUE
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
1350VALUE
1351rb_yield_1(VALUE val)
1352{
1353 return rb_yield_0(1, &val);
1354}
1355
1356VALUE
1357rb_yield(VALUE val)
1358{
1359 if (val == Qundef) {
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
1368VALUE
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
1390VALUE
1391rb_yield_values2(int argc, const VALUE *argv)
1392{
1393 return rb_yield_0(argc, argv);
1394}
1395
1396VALUE
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
1402VALUE
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
1415VALUE
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
1428VALUE
1429rb_yield_force_blockarg(VALUE values)
1430{
1431 return vm_yield_force_blockarg(GET_EC(), values);
1432}
1433
1434VALUE
1436{
1437 return vm_yield_with_block(GET_EC(), argc, argv,
1438 NIL_P(blockarg) ? VM_BLOCK_HANDLER_NONE : blockarg,
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 =~ /^qQ/
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,
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
1568VALUE
1569rb_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
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
1592VALUE 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
1594VALUE
1595rb_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
1601VALUE
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
1615VALUE
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
1642VALUE
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
1656VALUE
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 int depth = 1;
1677 const VALUE *ep = vm_block_ep(base_block);
1678
1679 while (1) {
1680 if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ISOLATED)) {
1681 isolated_depth = depth;
1682 break;
1683 }
1684 else if (VM_ENV_LOCAL_P(ep)) {
1685 break;
1686 }
1687 ep = VM_ENV_PREV_EP(ep);
1688 depth++;
1689 }
1690 }
1691
1692 if (!fname) {
1693 fname = rb_source_location(&line);
1694 }
1695
1696 if (fname != Qundef) {
1697 if (!NIL_P(fname)) fname = rb_fstring(fname);
1698 }
1699 else {
1700 fname = rb_fstring_lit("(eval)");
1701 if (!eval_default_path) {
1702 eval_default_path = rb_fstring_lit("(eval)");
1703 rb_gc_register_mark_object(eval_default_path);
1704 }
1705 fname = eval_default_path;
1706 }
1707
1708 rb_parser_set_context(parser, parent, FALSE);
1709 ast = rb_parser_compile_string_path(parser, fname, src, line);
1710 if (ast->body.root) {
1711 iseq = rb_iseq_new_eval(&ast->body,
1712 parent->body->location.label,
1713 fname, Qnil, INT2FIX(line),
1714 parent, isolated_depth);
1715 }
1716 rb_ast_dispose(ast);
1717
1718 if (iseq != NULL) {
1719 if (0 && iseq) { /* for debug */
1720 VALUE disasm = rb_iseq_disasm(iseq);
1721 printf("%s\n", StringValuePtr(disasm));
1722 }
1723
1724 rb_exec_event_hook_script_compiled(GET_EC(), iseq, src);
1725 }
1726
1727 return iseq;
1728}
1729
1730static VALUE
1731eval_string_with_cref(VALUE self, VALUE src, rb_cref_t *cref, VALUE file, int line)
1732{
1733 rb_execution_context_t *ec = GET_EC();
1734 struct rb_block block;
1735 const rb_iseq_t *iseq;
1736 rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
1737 if (!cfp) {
1738 rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread");
1739 }
1740
1741 block.as.captured = *VM_CFP_TO_CAPTURED_BLOCK(cfp);
1742 block.as.captured.self = self;
1743 block.as.captured.code.iseq = cfp->iseq;
1744 block.type = block_type_iseq;
1745
1746 iseq = eval_make_iseq(src, file, line, NULL, &block);
1747 if (!iseq) {
1748 rb_exc_raise(ec->errinfo);
1749 }
1750
1751 /* TODO: what the code checking? */
1752 if (!cref && block.as.captured.code.val) {
1753 rb_cref_t *orig_cref = vm_get_cref(vm_block_ep(&block));
1754 cref = vm_cref_dup(orig_cref);
1755 }
1756 vm_set_eval_stack(ec, iseq, cref, &block);
1757
1758 /* kick */
1759 return vm_exec(ec, true);
1760}
1761
1762static VALUE
1763eval_string_with_scope(VALUE scope, VALUE src, VALUE file, int line)
1764{
1765 rb_execution_context_t *ec = GET_EC();
1766 rb_binding_t *bind = Check_TypedStruct(scope, &ruby_binding_data_type);
1767 const rb_iseq_t *iseq = eval_make_iseq(src, file, line, bind, &bind->block);
1768 if (!iseq) {
1769 rb_exc_raise(ec->errinfo);
1770 }
1771
1772 vm_set_eval_stack(ec, iseq, NULL, &bind->block);
1773
1774 /* save new env */
1775 if (iseq->body->local_table_size > 0) {
1776 vm_bind_update_env(scope, bind, vm_make_env_object(ec, ec->cfp));
1777 }
1778
1779 /* kick */
1780 return vm_exec(ec, true);
1781}
1782
1783/*
1784 * call-seq:
1785 * eval(string [, binding [, filename [,lineno]]]) -> obj
1786 *
1787 * Evaluates the Ruby expression(s) in <em>string</em>. If
1788 * <em>binding</em> is given, which must be a Binding object, the
1789 * evaluation is performed in its context. If the optional
1790 * <em>filename</em> and <em>lineno</em> parameters are present, they
1791 * will be used when reporting syntax errors.
1792 *
1793 * def get_binding(str)
1794 * return binding
1795 * end
1796 * str = "hello"
1797 * eval "str + ' Fred'" #=> "hello Fred"
1798 * eval "str + ' Fred'", get_binding("bye") #=> "bye Fred"
1799 */
1800
1801VALUE
1802rb_f_eval(int argc, const VALUE *argv, VALUE self)
1803{
1804 VALUE src, scope, vfile, vline;
1805 VALUE file = Qundef;
1806 int line = 1;
1807
1808 rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
1809 SafeStringValue(src);
1810 if (argc >= 3) {
1811 StringValue(vfile);
1812 }
1813 if (argc >= 4) {
1814 line = NUM2INT(vline);
1815 }
1816
1817 if (!NIL_P(vfile))
1818 file = vfile;
1819
1820 if (NIL_P(scope))
1821 return eval_string_with_cref(self, src, NULL, file, line);
1822 else
1823 return eval_string_with_scope(scope, src, file, line);
1824}
1825
1827VALUE
1828ruby_eval_string_from_file(const char *str, const char *filename)
1829{
1830 VALUE file = filename ? rb_str_new_cstr(filename) : 0;
1831 return eval_string_with_cref(rb_vm_top_self(), rb_str_new2(str), NULL, file, 1);
1832}
1833
1834VALUE
1835rb_eval_string(const char *str)
1836{
1837 return ruby_eval_string_from_file(str, "eval");
1838}
1839
1840static VALUE
1841eval_string_protect(VALUE str)
1842{
1843 return rb_eval_string((char *)str);
1844}
1845
1846VALUE
1847rb_eval_string_protect(const char *str, int *pstate)
1848{
1849 return rb_protect(eval_string_protect, (VALUE)str, pstate);
1850}
1851
1853 VALUE top_self;
1854 VALUE klass;
1855 const char *str;
1856};
1857
1858static VALUE
1859eval_string_wrap_protect(VALUE data)
1860{
1861 const struct eval_string_wrap_arg *const arg = (struct eval_string_wrap_arg*)data;
1862 rb_cref_t *cref = rb_vm_cref_new_toplevel();
1863 cref->klass_or_self = arg->klass;
1864 return eval_string_with_cref(arg->top_self, rb_str_new_cstr(arg->str), cref, rb_str_new_cstr("eval"), 1);
1865}
1866
1867VALUE
1868rb_eval_string_wrap(const char *str, int *pstate)
1869{
1870 int state;
1871 rb_thread_t *th = GET_THREAD();
1872 VALUE self = th->top_self;
1873 VALUE wrapper = th->top_wrapper;
1874 VALUE val;
1875 struct eval_string_wrap_arg data;
1876
1877 th->top_wrapper = rb_module_new();
1878 th->top_self = rb_obj_clone(rb_vm_top_self());
1879 rb_extend_object(th->top_self, th->top_wrapper);
1880
1881 data.top_self = th->top_self;
1882 data.klass = th->top_wrapper;
1883 data.str = str;
1884
1885 val = rb_protect(eval_string_wrap_protect, (VALUE)&data, &state);
1886
1887 th->top_self = self;
1888 th->top_wrapper = wrapper;
1889
1890 if (pstate) {
1891 *pstate = state;
1892 }
1893 else if (state != TAG_NONE) {
1894 EC_JUMP_TAG(th->ec, state);
1895 }
1896 return val;
1897}
1898
1899VALUE
1900rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat)
1901{
1902 enum ruby_tag_type state;
1903 volatile VALUE val = Qnil; /* OK */
1904 rb_execution_context_t * volatile ec = GET_EC();
1905
1906 EC_PUSH_TAG(ec);
1907 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1908 if (!RB_TYPE_P(cmd, T_STRING)) {
1909 val = rb_funcallv_kw(cmd, idCall, RARRAY_LENINT(arg),
1910 RARRAY_CONST_PTR(arg), kw_splat);
1911 }
1912 else {
1913 val = eval_string_with_cref(rb_vm_top_self(), cmd, NULL, 0, 0);
1914 }
1915 }
1916 EC_POP_TAG();
1917
1918 if (state) EC_JUMP_TAG(ec, state);
1919 return val;
1920}
1921
1922/* block eval under the class/module context */
1923
1924static VALUE
1925yield_under(VALUE self, int singleton, int argc, const VALUE *argv, int kw_splat)
1926{
1927 rb_execution_context_t *ec = GET_EC();
1928 rb_control_frame_t *cfp = ec->cfp;
1929 VALUE block_handler = VM_CF_BLOCK_HANDLER(cfp);
1930 VALUE new_block_handler = 0;
1931 const struct rb_captured_block *captured = NULL;
1932 struct rb_captured_block new_captured;
1933 const VALUE *ep = NULL;
1934 rb_cref_t *cref;
1935 int is_lambda = FALSE;
1936
1937 if (block_handler != VM_BLOCK_HANDLER_NONE) {
1938 again:
1939 switch (vm_block_handler_type(block_handler)) {
1940 case block_handler_type_iseq:
1941 captured = VM_BH_TO_CAPT_BLOCK(block_handler);
1942 new_captured = *captured;
1943 new_block_handler = VM_BH_FROM_ISEQ_BLOCK(&new_captured);
1944 break;
1945 case block_handler_type_ifunc:
1946 captured = VM_BH_TO_CAPT_BLOCK(block_handler);
1947 new_captured = *captured;
1948 new_block_handler = VM_BH_FROM_IFUNC_BLOCK(&new_captured);
1949 break;
1950 case block_handler_type_proc:
1951 is_lambda = rb_proc_lambda_p(block_handler) != Qfalse;
1952 block_handler = vm_proc_to_block_handler(VM_BH_TO_PROC(block_handler));
1953 goto again;
1954 case block_handler_type_symbol:
1955 return rb_sym_proc_call(SYM2ID(VM_BH_TO_SYMBOL(block_handler)),
1956 argc, argv, kw_splat,
1957 VM_BLOCK_HANDLER_NONE);
1958 }
1959
1960 new_captured.self = self;
1961 ep = captured->ep;
1962
1963 VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(ec->cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler);
1964 }
1965
1966 VM_ASSERT(singleton || RB_TYPE_P(self, T_MODULE) || RB_TYPE_P(self, T_CLASS));
1967 cref = vm_cref_push(ec, self, ep, TRUE, singleton);
1968
1969 return vm_yield_with_cref(ec, argc, argv, kw_splat, cref, is_lambda);
1970}
1971
1972VALUE
1973rb_yield_refine_block(VALUE refinement, VALUE refinements)
1974{
1975 rb_execution_context_t *ec = GET_EC();
1976 VALUE block_handler = VM_CF_BLOCK_HANDLER(ec->cfp);
1977
1978 if (vm_block_handler_type(block_handler) != block_handler_type_iseq) {
1979 rb_bug("rb_yield_refine_block: an iseq block is required");
1980 }
1981 else {
1982 const struct rb_captured_block *captured = VM_BH_TO_ISEQ_BLOCK(block_handler);
1983 struct rb_captured_block new_captured = *captured;
1984 VALUE new_block_handler = VM_BH_FROM_ISEQ_BLOCK(&new_captured);
1985 const VALUE *ep = captured->ep;
1986 rb_cref_t *cref = vm_cref_push(ec, refinement, ep, TRUE, FALSE);
1987 CREF_REFINEMENTS_SET(cref, refinements);
1988 VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(ec->cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler);
1989 new_captured.self = refinement;
1990 return vm_yield_with_cref(ec, 0, NULL, RB_NO_KEYWORDS, cref, FALSE);
1991 }
1992}
1993
1994/* string eval under the class/module context */
1995static VALUE
1996eval_under(VALUE self, int singleton, VALUE src, VALUE file, int line)
1997{
1998 rb_cref_t *cref = vm_cref_push(GET_EC(), self, NULL, FALSE, singleton);
1999 SafeStringValue(src);
2000
2001 return eval_string_with_cref(self, src, cref, file, line);
2002}
2003
2004static VALUE
2005specific_eval(int argc, const VALUE *argv, VALUE self, int singleton, int kw_splat)
2006{
2007 if (rb_block_given_p()) {
2008 rb_check_arity(argc, 0, 0);
2009 return yield_under(self, singleton, 1, &self, kw_splat);
2010 }
2011 else {
2012 VALUE file = Qundef;
2013 int line = 1;
2014 VALUE code;
2015
2016 rb_check_arity(argc, 1, 3);
2017 code = argv[0];
2018 SafeStringValue(code);
2019 if (argc > 2)
2020 line = NUM2INT(argv[2]);
2021 if (argc > 1) {
2022 file = argv[1];
2023 if (!NIL_P(file)) StringValue(file);
2024 }
2025 return eval_under(self, singleton, code, file, line);
2026 }
2027}
2028
2029/*
2030 * call-seq:
2031 * obj.instance_eval(string [, filename [, lineno]] ) -> obj
2032 * obj.instance_eval {|obj| block } -> obj
2033 *
2034 * Evaluates a string containing Ruby source code, or the given block,
2035 * within the context of the receiver (_obj_). In order to set the
2036 * context, the variable +self+ is set to _obj_ while
2037 * the code is executing, giving the code access to _obj_'s
2038 * instance variables and private methods.
2039 *
2040 * When <code>instance_eval</code> is given a block, _obj_ is also
2041 * passed in as the block's only argument.
2042 *
2043 * When <code>instance_eval</code> is given a +String+, the optional
2044 * second and third parameters supply a filename and starting line number
2045 * that are used when reporting compilation errors.
2046 *
2047 * class KlassWithSecret
2048 * def initialize
2049 * @secret = 99
2050 * end
2051 * private
2052 * def the_secret
2053 * "Ssssh! The secret is #{@secret}."
2054 * end
2055 * end
2056 * k = KlassWithSecret.new
2057 * k.instance_eval { @secret } #=> 99
2058 * k.instance_eval { the_secret } #=> "Ssssh! The secret is 99."
2059 * k.instance_eval {|obj| obj == self } #=> true
2060 */
2061
2062static VALUE
2063rb_obj_instance_eval_internal(int argc, const VALUE *argv, VALUE self)
2064{
2065 return specific_eval(argc, argv, self, TRUE, RB_PASS_CALLED_KEYWORDS);
2066}
2067
2068VALUE
2069rb_obj_instance_eval(int argc, const VALUE *argv, VALUE self)
2070{
2071 return specific_eval(argc, argv, self, TRUE, RB_NO_KEYWORDS);
2072}
2073
2074/*
2075 * call-seq:
2076 * obj.instance_exec(arg...) {|var...| block } -> obj
2077 *
2078 * Executes the given block within the context of the receiver
2079 * (_obj_). In order to set the context, the variable +self+ is set
2080 * to _obj_ while the code is executing, giving the code access to
2081 * _obj_'s instance variables. Arguments are passed as block parameters.
2082 *
2083 * class KlassWithSecret
2084 * def initialize
2085 * @secret = 99
2086 * end
2087 * end
2088 * k = KlassWithSecret.new
2089 * k.instance_exec(5) {|x| @secret+x } #=> 104
2090 */
2091
2092static VALUE
2093rb_obj_instance_exec_internal(int argc, const VALUE *argv, VALUE self)
2094{
2095 return yield_under(self, TRUE, argc, argv, RB_PASS_CALLED_KEYWORDS);
2096}
2097
2098VALUE
2099rb_obj_instance_exec(int argc, const VALUE *argv, VALUE self)
2100{
2101 return yield_under(self, TRUE, argc, argv, RB_NO_KEYWORDS);
2102}
2103
2104/*
2105 * call-seq:
2106 * mod.class_eval(string [, filename [, lineno]]) -> obj
2107 * mod.class_eval {|mod| block } -> obj
2108 * mod.module_eval(string [, filename [, lineno]]) -> obj
2109 * mod.module_eval {|mod| block } -> obj
2110 *
2111 * Evaluates the string or block in the context of _mod_, except that when
2112 * a block is given, constant/class variable lookup is not affected. This
2113 * can be used to add methods to a class. <code>module_eval</code> returns
2114 * the result of evaluating its argument. The optional _filename_ and
2115 * _lineno_ parameters set the text for error messages.
2116 *
2117 * class Thing
2118 * end
2119 * a = %q{def hello() "Hello there!" end}
2120 * Thing.module_eval(a)
2121 * puts Thing.new.hello()
2122 * Thing.module_eval("invalid code", "dummy", 123)
2123 *
2124 * <em>produces:</em>
2125 *
2126 * Hello there!
2127 * dummy:123:in `module_eval': undefined local variable
2128 * or method `code' for Thing:Class
2129 */
2130
2131static VALUE
2132rb_mod_module_eval_internal(int argc, const VALUE *argv, VALUE mod)
2133{
2134 return specific_eval(argc, argv, mod, FALSE, RB_PASS_CALLED_KEYWORDS);
2135}
2136
2137VALUE
2138rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod)
2139{
2140 return specific_eval(argc, argv, mod, FALSE, RB_NO_KEYWORDS);
2141}
2142
2143/*
2144 * call-seq:
2145 * mod.module_exec(arg...) {|var...| block } -> obj
2146 * mod.class_exec(arg...) {|var...| block } -> obj
2147 *
2148 * Evaluates the given block in the context of the class/module.
2149 * The method defined in the block will belong to the receiver.
2150 * Any arguments passed to the method will be passed to the block.
2151 * This can be used if the block needs to access instance variables.
2152 *
2153 * class Thing
2154 * end
2155 * Thing.class_exec{
2156 * def hello() "Hello there!" end
2157 * }
2158 * puts Thing.new.hello()
2159 *
2160 * <em>produces:</em>
2161 *
2162 * Hello there!
2163 */
2164
2165static VALUE
2166rb_mod_module_exec_internal(int argc, const VALUE *argv, VALUE mod)
2167{
2168 return yield_under(mod, FALSE, argc, argv, RB_PASS_CALLED_KEYWORDS);
2169}
2170
2171VALUE
2172rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod)
2173{
2174 return yield_under(mod, FALSE, argc, argv, RB_NO_KEYWORDS);
2175}
2176
2177/*
2178 * Document-class: UncaughtThrowError
2179 *
2180 * Raised when +throw+ is called with a _tag_ which does not have
2181 * corresponding +catch+ block.
2182 *
2183 * throw "foo", "bar"
2184 *
2185 * <em>raises the exception:</em>
2186 *
2187 * UncaughtThrowError: uncaught throw "foo"
2188 */
2189
2190static VALUE
2191uncaught_throw_init(int argc, const VALUE *argv, VALUE exc)
2192{
2194 rb_call_super(argc - 2, argv + 2);
2195 rb_ivar_set(exc, id_tag, argv[0]);
2196 rb_ivar_set(exc, id_value, argv[1]);
2197 return exc;
2198}
2199
2200/*
2201 * call-seq:
2202 * uncaught_throw.tag -> obj
2203 *
2204 * Return the tag object which was called for.
2205 */
2206
2207static VALUE
2208uncaught_throw_tag(VALUE exc)
2209{
2210 return rb_ivar_get(exc, id_tag);
2211}
2212
2213/*
2214 * call-seq:
2215 * uncaught_throw.value -> obj
2216 *
2217 * Return the return value which was called for.
2218 */
2219
2220static VALUE
2221uncaught_throw_value(VALUE exc)
2222{
2223 return rb_ivar_get(exc, id_value);
2224}
2225
2226/*
2227 * call-seq:
2228 * uncaught_throw.to_s -> string
2229 *
2230 * Returns formatted message with the inspected tag.
2231 */
2232
2233static VALUE
2234uncaught_throw_to_s(VALUE exc)
2235{
2236 VALUE mesg = rb_attr_get(exc, id_mesg);
2237 VALUE tag = uncaught_throw_tag(exc);
2238 return rb_str_format(1, &tag, mesg);
2239}
2240
2241/*
2242 * call-seq:
2243 * throw(tag [, obj])
2244 *
2245 * Transfers control to the end of the active +catch+ block
2246 * waiting for _tag_. Raises +UncaughtThrowError+ if there
2247 * is no +catch+ block for the _tag_. The optional second
2248 * parameter supplies a return value for the +catch+ block,
2249 * which otherwise defaults to +nil+. For examples, see
2250 * Kernel::catch.
2251 */
2252
2253static VALUE
2254rb_f_throw(int argc, VALUE *argv, VALUE _)
2255{
2256 VALUE tag, value;
2257
2258 rb_scan_args(argc, argv, "11", &tag, &value);
2259 rb_throw_obj(tag, value);
2261}
2262
2263void
2264rb_throw_obj(VALUE tag, VALUE value)
2265{
2266 rb_execution_context_t *ec = GET_EC();
2267 struct rb_vm_tag *tt = ec->tag;
2268
2269 while (tt) {
2270 if (tt->tag == tag) {
2271 tt->retval = value;
2272 break;
2273 }
2274 tt = tt->prev;
2275 }
2276 if (!tt) {
2277 VALUE desc[3];
2278 desc[0] = tag;
2279 desc[1] = value;
2280 desc[2] = rb_str_new_cstr("uncaught throw %p");
2281 rb_exc_raise(rb_class_new_instance(numberof(desc), desc, rb_eUncaughtThrow));
2282 }
2283
2284 ec->errinfo = (VALUE)THROW_DATA_NEW(tag, NULL, TAG_THROW);
2285 EC_JUMP_TAG(ec, TAG_THROW);
2286}
2287
2288void
2289rb_throw(const char *tag, VALUE val)
2290{
2291 rb_throw_obj(rb_sym_intern_ascii_cstr(tag), val);
2292}
2293
2294static VALUE
2295catch_i(RB_BLOCK_CALL_FUNC_ARGLIST(tag, _))
2296{
2297 return rb_yield_0(1, &tag);
2298}
2299
2300/*
2301 * call-seq:
2302 * catch([tag]) {|tag| block } -> obj
2303 *
2304 * +catch+ executes its block. If +throw+ is not called, the block executes
2305 * normally, and +catch+ returns the value of the last expression evaluated.
2306 *
2307 * catch(1) { 123 } # => 123
2308 *
2309 * If <code>throw(tag2, val)</code> is called, Ruby searches up its stack for
2310 * a +catch+ block whose +tag+ has the same +object_id+ as _tag2_. When found,
2311 * the block stops executing and returns _val_ (or +nil+ if no second argument
2312 * was given to +throw+).
2313 *
2314 * catch(1) { throw(1, 456) } # => 456
2315 * catch(1) { throw(1) } # => nil
2316 *
2317 * When +tag+ is passed as the first argument, +catch+ yields it as the
2318 * parameter of the block.
2319 *
2320 * catch(1) {|x| x + 2 } # => 3
2321 *
2322 * When no +tag+ is given, +catch+ yields a new unique object (as from
2323 * +Object.new+) as the block parameter. This object can then be used as the
2324 * argument to +throw+, and will match the correct +catch+ block.
2325 *
2326 * catch do |obj_A|
2327 * catch do |obj_B|
2328 * throw(obj_B, 123)
2329 * puts "This puts is not reached"
2330 * end
2331 *
2332 * puts "This puts is displayed"
2333 * 456
2334 * end
2335 *
2336 * # => 456
2337 *
2338 * catch do |obj_A|
2339 * catch do |obj_B|
2340 * throw(obj_A, 123)
2341 * puts "This puts is still not reached"
2342 * end
2343 *
2344 * puts "Now this puts is also not reached"
2345 * 456
2346 * end
2347 *
2348 * # => 123
2349 */
2350
2351static VALUE
2352rb_f_catch(int argc, VALUE *argv, VALUE self)
2353{
2354 VALUE tag = rb_check_arity(argc, 0, 1) ? argv[0] : rb_obj_alloc(rb_cObject);
2355 return rb_catch_obj(tag, catch_i, 0);
2356}
2357
2358VALUE
2359rb_catch(const char *tag, rb_block_call_func_t func, VALUE data)
2360{
2361 VALUE vtag = tag ? rb_sym_intern_ascii_cstr(tag) : rb_obj_alloc(rb_cObject);
2362 return rb_catch_obj(vtag, func, data);
2363}
2364
2365static VALUE
2366vm_catch_protect(VALUE tag, rb_block_call_func *func, VALUE data,
2367 enum ruby_tag_type *stateptr, rb_execution_context_t *volatile ec)
2368{
2369 enum ruby_tag_type state;
2370 VALUE val = Qnil; /* OK */
2371 rb_control_frame_t *volatile saved_cfp = ec->cfp;
2372
2373 EC_PUSH_TAG(ec);
2374
2375 _tag.tag = tag;
2376
2377 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
2378 /* call with argc=1, argv = [tag], block = Qnil to insure compatibility */
2379 val = (*func)(tag, data, 1, (const VALUE *)&tag, Qnil);
2380 }
2381 else if (state == TAG_THROW && THROW_DATA_VAL((struct vm_throw_data *)ec->errinfo) == tag) {
2382 rb_vm_rewind_cfp(ec, saved_cfp);
2383 val = ec->tag->retval;
2384 ec->errinfo = Qnil;
2385 state = 0;
2386 }
2387 EC_POP_TAG();
2388 if (stateptr)
2389 *stateptr = state;
2390
2391 return val;
2392}
2393
2394VALUE
2395rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, enum ruby_tag_type *stateptr)
2396{
2397 return vm_catch_protect(t, func, data, stateptr, GET_EC());
2398}
2399
2400VALUE
2401rb_catch_obj(VALUE t, rb_block_call_func_t func, VALUE data)
2402{
2403 enum ruby_tag_type state;
2404 rb_execution_context_t *ec = GET_EC();
2405 VALUE val = vm_catch_protect(t, (rb_block_call_func *)func, data, &state, ec);
2406 if (state) EC_JUMP_TAG(ec, state);
2407 return val;
2408}
2409
2410static void
2411local_var_list_init(struct local_var_list *vars)
2412{
2413 vars->tbl = rb_ident_hash_new();
2414 RBASIC_CLEAR_CLASS(vars->tbl);
2415}
2416
2417static VALUE
2418local_var_list_finish(struct local_var_list *vars)
2419{
2420 /* TODO: not to depend on the order of st_table */
2421 VALUE ary = rb_hash_keys(vars->tbl);
2422 rb_hash_clear(vars->tbl);
2423 vars->tbl = 0;
2424 return ary;
2425}
2426
2427static int
2428local_var_list_update(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
2429{
2430 if (existing) return ST_STOP;
2431 *value = (st_data_t)Qtrue; /* INT2FIX(arg) */
2432 return ST_CONTINUE;
2433}
2434
2435static void
2436local_var_list_add(const struct local_var_list *vars, ID lid)
2437{
2438 if (lid && rb_is_local_id(lid)) {
2439 /* should skip temporary variable */
2440 st_data_t idx = 0; /* tbl->num_entries */
2441 rb_hash_stlike_update(vars->tbl, ID2SYM(lid), local_var_list_update, idx);
2442 }
2443}
2444
2445/*
2446 * call-seq:
2447 * local_variables -> array
2448 *
2449 * Returns the names of the current local variables.
2450 *
2451 * fred = 1
2452 * for i in 1..10
2453 * # ...
2454 * end
2455 * local_variables #=> [:fred, :i]
2456 */
2457
2458static VALUE
2459rb_f_local_variables(VALUE _)
2460{
2461 struct local_var_list vars;
2462 rb_execution_context_t *ec = GET_EC();
2463 rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp));
2464 unsigned int i;
2465
2466 local_var_list_init(&vars);
2467 while (cfp) {
2468 if (cfp->iseq) {
2469 for (i = 0; i < cfp->iseq->body->local_table_size; i++) {
2470 local_var_list_add(&vars, cfp->iseq->body->local_table[i]);
2471 }
2472 }
2473 if (!VM_ENV_LOCAL_P(cfp->ep)) {
2474 /* block */
2475 const VALUE *ep = VM_CF_PREV_EP(cfp);
2476
2477 if (vm_collect_local_variables_in_heap(ep, &vars)) {
2478 break;
2479 }
2480 else {
2481 while (cfp->ep != ep) {
2482 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
2483 }
2484 }
2485 }
2486 else {
2487 break;
2488 }
2489 }
2490 return local_var_list_finish(&vars);
2491}
2492
2493/*
2494 * call-seq:
2495 * block_given? -> true or false
2496 *
2497 * Returns <code>true</code> if <code>yield</code> would execute a
2498 * block in the current context. The <code>iterator?</code> form
2499 * is mildly deprecated.
2500 *
2501 * def try
2502 * if block_given?
2503 * yield
2504 * else
2505 * "no block"
2506 * end
2507 * end
2508 * try #=> "no block"
2509 * try { "hello" } #=> "hello"
2510 * try do "hello" end #=> "hello"
2511 */
2512
2513static VALUE
2514rb_f_block_given_p(VALUE _)
2515{
2516 rb_execution_context_t *ec = GET_EC();
2517 rb_control_frame_t *cfp = ec->cfp;
2518 cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
2519
2520 return RBOOL(cfp != NULL && VM_CF_BLOCK_HANDLER(cfp) != VM_BLOCK_HANDLER_NONE);
2521}
2522
2523/*
2524 * call-seq:
2525 * iterator? -> true or false
2526 *
2527 * Deprecated. Use block_given? instead.
2528 */
2529
2530static VALUE
2531rb_f_iterator_p(VALUE self)
2532{
2533 rb_warn_deprecated("iterator?", "block_given?");
2534 return rb_f_block_given_p(self);
2535}
2536
2537VALUE
2538rb_current_realfilepath(void)
2539{
2540 const rb_execution_context_t *ec = GET_EC();
2541 rb_control_frame_t *cfp = ec->cfp;
2542 cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
2543 if (cfp != NULL) {
2544 VALUE path = rb_iseq_realpath(cfp->iseq);
2545 if (RTEST(path)) return path;
2546 // eval context
2547 path = rb_iseq_path(cfp->iseq);
2548 if (path == eval_default_path) {
2549 return Qnil;
2550 }
2551 else {
2552 return path;
2553 }
2554 }
2555 return Qnil;
2556}
2557
2558void
2559Init_vm_eval(void)
2560{
2561 rb_define_global_function("eval", rb_f_eval, -1);
2562 rb_define_global_function("local_variables", rb_f_local_variables, 0);
2563 rb_define_global_function("iterator?", rb_f_iterator_p, 0);
2564 rb_define_global_function("block_given?", rb_f_block_given_p, 0);
2565
2566 rb_define_global_function("catch", rb_f_catch, -1);
2567 rb_define_global_function("throw", rb_f_throw, -1);
2568
2569 rb_define_global_function("loop", rb_f_loop, 0);
2570
2571 rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval_internal, -1);
2572 rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec_internal, -1);
2573 rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
2574
2575#if 1
2576 rb_add_method(rb_cBasicObject, id__send__,
2577 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, METHOD_VISI_PUBLIC);
2578 rb_add_method(rb_mKernel, idSend,
2579 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, METHOD_VISI_PUBLIC);
2580#else
2581 rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
2582 rb_define_method(rb_mKernel, "send", rb_f_send, -1);
2583#endif
2584 rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
2585
2586 rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec_internal, -1);
2587 rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec_internal, -1);
2588 rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval_internal, -1);
2589 rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval_internal, -1);
2590
2591 rb_eUncaughtThrow = rb_define_class("UncaughtThrowError", rb_eArgError);
2592 rb_define_method(rb_eUncaughtThrow, "initialize", uncaught_throw_init, -1);
2593 rb_define_method(rb_eUncaughtThrow, "tag", uncaught_throw_tag, 0);
2594 rb_define_method(rb_eUncaughtThrow, "value", uncaught_throw_value, 0);
2595 rb_define_method(rb_eUncaughtThrow, "to_s", uncaught_throw_to_s, 0);
2596
2597 id_result = rb_intern_const("result");
2598 id_tag = rb_intern_const("tag");
2599 id_value = rb_intern_const("value");
2600}
2601
2602#endif /* #ifndef MJIT_HEADER */
#define rb_define_private_method(klass, mid, func, arity)
Defines klass#mid and makes it private.
Definition: cxxanyargs.hpp:677
#define RUBY_EVENT_C_CALL
A method, written in C, is called.
Definition: event.h:39
#define RUBY_EVENT_C_RETURN
Return from a method, written in C.
Definition: event.h:40
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:837
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
Definition: eval.c:1579
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:2406
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a method.
Definition: class.c:1914
int rb_keyword_given_p(void)
Determines if the current method is given a keyword argument.
Definition: eval.c:863
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:850
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:2110
#define rb_str_new2
Old name of rb_str_new_cstr.
Definition: string.h:1738
#define T_COMPLEX
Old name of RUBY_T_COMPLEX.
Definition: value_type.h:59
#define T_FILE
Old name of RUBY_T_FILE.
Definition: value_type.h:62
#define T_STRING
Old name of RUBY_T_STRING.
Definition: value_type.h:78
#define T_MASK
Old name of RUBY_T_MASK.
Definition: value_type.h:68
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
Definition: long.h:48
#define T_NIL
Old name of RUBY_T_NIL.
Definition: value_type.h:72
#define T_FLOAT
Old name of RUBY_T_FLOAT.
Definition: value_type.h:64
#define T_IMEMO
Old name of RUBY_T_IMEMO.
Definition: value_type.h:67
#define ID2SYM
Old name of RB_ID2SYM.
Definition: symbol.h:44
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
Definition: value_type.h:57
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
#define T_STRUCT
Old name of RUBY_T_STRUCT.
Definition: value_type.h:79
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
Definition: fl_type.h:143
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
Definition: value_type.h:63
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
Definition: assume.h:31
#define SYM2ID
Old name of RB_SYM2ID.
Definition: symbol.h:45
#define T_DATA
Old name of RUBY_T_DATA.
Definition: value_type.h:60
#define CLASS_OF
Old name of rb_class_of.
Definition: globals.h:203
#define T_NONE
Old name of RUBY_T_NONE.
Definition: value_type.h:74
#define T_NODE
Old name of RUBY_T_NODE.
Definition: value_type.h:73
#define rb_ary_new4
Old name of rb_ary_new_from_values.
Definition: array.h:653
#define T_MODULE
Old name of RUBY_T_MODULE.
Definition: value_type.h:70
#define T_TRUE
Old name of RUBY_T_TRUE.
Definition: value_type.h:81
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
Definition: value_type.h:76
#define T_ICLASS
Old name of RUBY_T_ICLASS.
Definition: value_type.h:66
#define T_HASH
Old name of RUBY_T_HASH.
Definition: value_type.h:65
#define T_FALSE
Old name of RUBY_T_FALSE.
Definition: value_type.h:61
#define T_UNDEF
Old name of RUBY_T_UNDEF.
Definition: value_type.h:82
#define Qtrue
Old name of RUBY_Qtrue.
#define NUM2INT
Old name of RB_NUM2INT.
Definition: int.h:44
#define T_ZOMBIE
Old name of RUBY_T_ZOMBIE.
Definition: value_type.h:83
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
Definition: value_type.h:56
#define T_OBJECT
Old name of RUBY_T_OBJECT.
Definition: value_type.h:75
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
Definition: memory.h:399
#define T_SYMBOL
Old name of RUBY_T_SYMBOL.
Definition: value_type.h:80
#define DBL2NUM
Old name of rb_float_new.
Definition: double.h:29
#define T_MATCH
Old name of RUBY_T_MATCH.
Definition: value_type.h:69
#define T_CLASS
Old name of RUBY_T_CLASS.
Definition: value_type.h:58
#define BUILTIN_TYPE
Old name of RB_BUILTIN_TYPE.
Definition: value_type.h:85
#define T_MOVED
Old name of RUBY_T_MOVED.
Definition: value_type.h:71
#define Check_TypedStruct(v, t)
Old name of rb_check_typeddata.
Definition: rtypeddata.h:105
#define ALLOCV_END
Old name of RB_ALLOCV_END.
Definition: memory.h:400
#define SYMBOL_P
Old name of RB_SYMBOL_P.
Definition: value_type.h:88
#define T_REGEXP
Old name of RUBY_T_REGEXP.
Definition: value_type.h:77
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
Definition: error.c:3021
VALUE rb_rescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2,...)
An equivalent of rescue clause.
Definition: eval.c:879
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:671
void rb_bug(const char *fmt,...)
Interpreter panic switch.
Definition: error.c:802
VALUE rb_eStopIteration
StopIteration exception.
Definition: enumerator.c:141
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:1868
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
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition: vm_eval.c:1102
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
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
Definition: vm_eval.c:1061
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
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:1847
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:330
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
VALUE rb_current_receiver(void)
This resembles ruby's self.
Definition: vm_eval.c:344
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
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
VALUE rb_eval_string(const char *str)
Evaluates the given string in an isolated binding.
Definition: vm_eval.c:1835
VALUE rb_call_super(int argc, const VALUE *argv)
This resembles ruby's super.
Definition: vm_eval.c:338
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
void rb_gc_register_mark_object(VALUE object)
Inform the garbage collector that object is a live Ruby object that should not be moved.
Definition: gc.c:8686
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
Definition: array.c:989
VALUE rb_ary_subseq(VALUE ary, long beg, long len)
Obtains a part of the passed array.
Definition: array.c:1707
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
This roughly resembles return enum_for(__callee__) unless block_given?.
Definition: enumerator.h:206
#define UNLIMITED_ARGUMENTS
This macro is used in conjunction with rb_check_arity().
Definition: error.h:35
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition: error.h:294
VALUE rb_hash_clear(VALUE hash)
Swipes everything out of the passed hash table.
Definition: hash.c:2829
int rb_is_local_id(ID id)
Classifies the given ID, then sees if it is a local variable.
Definition: symbol.c:1042
VALUE rb_proc_lambda_p(VALUE recv)
Queries if the given object is a lambda.
Definition: proc.c:293
VALUE rb_protect(VALUE(*func)(VALUE args), VALUE args, int *state)
Protects a function call from potential global escapes from the function.
VALUE rb_str_new_cstr(const char *ptr)
Identical to rb_str_new(), except it assumes the passed pointer is a pointer to a C string.
Definition: string.c:952
VALUE rb_str_intern(VALUE str)
Identical to rb_to_symbol(), except it assumes the receiver being an instance of RString.
Definition: symbol.c:837
VALUE rb_attr_get(VALUE obj, ID name)
Identical to rb_ivar_get()
Definition: variable.c:1293
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:1575
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:1285
int rb_method_basic_definition_p(VALUE klass, ID mid)
Well... Let us hesitate from describing what a "basic definition" is.
Definition: vm_method.c:2643
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
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
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:2138
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:2172
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:2099
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:1900
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
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:2069
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
Definition: symbol.h:276
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
Definition: symbol.c:1066
VALUE rb_id2str(ID id)
Identical to rb_id2name(), except it returns a Ruby's String instead of C's.
Definition: symbol.c:935
VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt)
Formats a string.
Definition: sprintf.c:214
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
Definition: iterator.h:58
VALUE rb_catch_obj(VALUE tag, rb_block_call_func_t func, VALUE data)
Identical to rb_catch(), except it catches arbitrary Ruby objects.
Definition: vm_eval.c:2401
VALUE rb_each(VALUE obj)
This is a shorthand of calling obj.each.
Definition: vm_eval.c:1657
VALUE rb_block_call(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2)
Identical to rb_funcallv(), except it additionally passes a function as a block.
Definition: vm_eval.c:1595
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
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
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:2289
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
VALUE rb_yield(VALUE val)
Yields the block.
Definition: vm_eval.c:1357
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
VALUE rb_yield_block(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
Pass a passed block.
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:2264
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
VALUE rb_iterate(VALUE(*func1)(VALUE), VALUE data1, rb_block_call_func_t proc, VALUE data2)
Old way to iterate a block.
Definition: vm_eval.c:1569
VALUE rb_catch(const char *tag, rb_block_call_func_t func, VALUE data)
Executes the passed block and catches values thrown from inside of it.
Definition: vm_eval.c:2359
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
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
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
Definition: memory.h:366
#define ALLOCA_N(type, n)
Definition: memory.h:286
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition: memory.h:161
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:56
#define RARRAY_CONST_PTR_TRANSIENT
Just another name of rb_array_const_ptr_transient.
Definition: rarray.h:70
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
Definition: rarray.h:324
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
Definition: rarray.h:69
static VALUE RBASIC_CLASS(VALUE obj)
Queries the class of an object.
Definition: rbasic.h:152
#define RBASIC(obj)
Convenient casting macro.
Definition: rbasic.h:40
#define RCLASS_SUPER
Just another name of rb_class_get_superclass.
Definition: rclass.h:46
#define RHASH_EMPTY_P(h)
Checks if the hash is empty.
Definition: rhash.h:92
#define SafeStringValue(v)
Definition: rstring.h:104
#define StringValue(v)
Ensures that the parameter object is a String.
Definition: rstring.h:72
#define StringValuePtr(v)
Identical to StringValue, except it returns a char*.
Definition: rstring.h:82
#define RB_PASS_CALLED_KEYWORDS
Pass keywords if current method is called with keywords, useful for argument delegation.
Definition: scan_args.h:78
#define RB_NO_KEYWORDS
Do not pass keywords.
Definition: scan_args.h:69
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
Definition: stdarg.h:35
CREF (Class REFerence)
IFUNC (Internal FUNCtion)
uintptr_t VALUE
Type that represents a Ruby object.
Definition: value.h:40
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