Ruby 3.2.1p31 (2023-02-08 revision 31819e82c88c6f8ecfaeb162519bfa26a14b21fd)
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"
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);
24VALUE 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{
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
330VALUE
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
338VALUE
339rb_call_super(int argc, const VALUE *argv)
340{
341 return rb_call_super_kw(argc, argv, RB_NO_KEYWORDS);
342}
343
344VALUE
346{
347 const rb_execution_context_t *ec = GET_EC();
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, cme);
400 rb_id_table_insert(cc_tbl, mid, (VALUE)ccs);
401 }
402
403 for (int i=0; i<ccs->len; i++) {
404 cc = ccs->entries[i].cc;
405 if (vm_cc_cme(cc) == cme) {
406 break;
407 }
408 cc = NULL;
409 }
410
411 if (cc == NULL) {
412 const struct rb_callinfo *ci = vm_ci_new(mid, 0, argc, NULL); // TODO: proper ci
413 cc = vm_cc_new(klass, cme, vm_call_general);
414 METHOD_ENTRY_CACHED_SET((struct rb_callable_method_entry_struct *)cme);
415 vm_ccs_push(klass, ccs, ci, cc);
416 }
417 }
418 RB_VM_LOCK_LEAVE();
419
420 return cc;
421}
422
423static VALUE
424gccct_hash(VALUE klass, ID mid)
425{
426 return (klass >> 3) ^ (VALUE)mid;
427}
428
429NOINLINE(static const struct rb_callcache *gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, ID mid, int argc, unsigned int index));
430
431static const struct rb_callcache *
432gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, ID mid, int argc, unsigned int index)
433{
434 const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
435 const struct rb_callcache *cc;
436
437 if (cme != NULL) {
438 cc = cc_new(klass, mid, argc, cme);
439 }
440 else {
441 cc = NULL;
442 }
443
444 return vm->global_cc_cache_table[index] = cc;
445}
446
447static inline const struct rb_callcache *
448gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, int argc)
449{
450 VALUE klass;
451
452 if (!SPECIAL_CONST_P(recv)) {
453 klass = RBASIC_CLASS(recv);
454 if (UNLIKELY(!klass)) uncallable_object(recv, mid);
455 }
456 else {
457 klass = CLASS_OF(recv);
458 }
459
460 // search global method cache
461 unsigned int index = (unsigned int)(gccct_hash(klass, mid) % VM_GLOBAL_CC_CACHE_TABLE_SIZE);
462 rb_vm_t *vm = rb_ec_vm_ptr(ec);
463 const struct rb_callcache *cc = vm->global_cc_cache_table[index];
464
465 if (LIKELY(cc)) {
466 if (LIKELY(vm_cc_class_check(cc, klass))) {
467 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
468 if (LIKELY(!METHOD_ENTRY_INVALIDATED(cme) &&
469 cme->called_id == mid)) {
470
471 VM_ASSERT(vm_cc_check_cme(cc, rb_callable_method_entry(klass, mid)));
472 RB_DEBUG_COUNTER_INC(gccct_hit);
473
474 return cc;
475 }
476 }
477 }
478 else {
479 RB_DEBUG_COUNTER_INC(gccct_null);
480 }
481
482 RB_DEBUG_COUNTER_INC(gccct_miss);
483 return gccct_method_search_slowpath(vm, klass, mid, argc, index);
484}
485
502static inline VALUE
503rb_call0(rb_execution_context_t *ec,
504 VALUE recv, ID mid, int argc, const VALUE *argv,
505 call_type call_scope, VALUE self)
506{
507 enum method_missing_reason call_status;
508 call_type scope = call_scope;
509 int kw_splat = RB_NO_KEYWORDS;
510
511 switch (scope) {
512 case CALL_PUBLIC_KW:
513 scope = CALL_PUBLIC;
514 kw_splat = 1;
515 break;
516 case CALL_FCALL_KW:
517 scope = CALL_FCALL;
518 kw_splat = 1;
519 break;
520 default:
521 break;
522 }
523
524 const struct rb_callcache *cc = gccct_method_search(ec, recv, mid, argc);
525
526 if (scope == CALL_PUBLIC) {
527 RB_DEBUG_COUNTER_INC(call0_public);
528
529 const rb_callable_method_entry_t *cc_cme = cc ? vm_cc_cme(cc) : NULL;
530 const rb_callable_method_entry_t *cme = callable_method_entry_refeinements0(CLASS_OF(recv), mid, NULL, true, cc_cme);
531 call_status = rb_method_call_status(ec, cme, scope, self);
532
533 if (UNLIKELY(call_status != MISSING_NONE)) {
534 return method_missing(ec, recv, mid, argc, argv, call_status, kw_splat);
535 }
536 else if (UNLIKELY(cc_cme != cme)) { // refinement is solved
537 stack_check(ec);
538 return rb_vm_call_kw(ec, recv, mid, argc, argv, cme, kw_splat);
539 }
540 }
541 else {
542 RB_DEBUG_COUNTER_INC(call0_other);
543 call_status = rb_method_call_status(ec, cc ? vm_cc_cme(cc) : NULL, scope, self);
544
545 if (UNLIKELY(call_status != MISSING_NONE)) {
546 return method_missing(ec, recv, mid, argc, argv, call_status, kw_splat);
547 }
548 }
549
550 stack_check(ec);
551 return vm_call0_cc(ec, recv, mid, argc, argv, cc, kw_splat);
552}
553
555 VALUE defined_class;
556 VALUE recv;
557 ID mid;
560 unsigned int respond: 1;
561 unsigned int respond_to_missing: 1;
562 int argc;
563 const VALUE *argv;
564 int kw_splat;
565};
566
567static VALUE
568check_funcall_exec(VALUE v)
569{
570 struct rescue_funcall_args *args = (void *)v;
571 return call_method_entry(args->ec, args->defined_class,
572 args->recv, idMethodMissing,
573 args->cme, args->argc, args->argv, args->kw_splat);
574}
575
576static VALUE
577check_funcall_failed(VALUE v, VALUE e)
578{
579 struct rescue_funcall_args *args = (void *)v;
580 int ret = args->respond;
581 if (!ret) {
582 switch (method_boundp(args->defined_class, args->mid,
583 BOUND_PRIVATE|BOUND_RESPONDS)) {
584 case 2:
585 ret = TRUE;
586 break;
587 case 0:
588 ret = args->respond_to_missing;
589 break;
590 default:
591 ret = FALSE;
592 break;
593 }
594 }
595 if (ret) {
596 rb_exc_raise(e);
597 }
598 return Qundef;
599}
600
601static int
602check_funcall_respond_to(rb_execution_context_t *ec, VALUE klass, VALUE recv, ID mid)
603{
604 return vm_respond_to(ec, klass, recv, mid, TRUE);
605}
606
607static int
608check_funcall_callable(rb_execution_context_t *ec, const rb_callable_method_entry_t *me)
609{
610 return rb_method_call_status(ec, me, CALL_FCALL, ec->cfp->self) == MISSING_NONE;
611}
612
613static VALUE
614check_funcall_missing(rb_execution_context_t *ec, VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv, int respond, VALUE def, int kw_splat)
615{
616 struct rescue_funcall_args args;
618 VALUE ret = Qundef;
619
620 ret = basic_obj_respond_to_missing(ec, klass, recv,
621 ID2SYM(mid), Qtrue);
622 if (!RTEST(ret)) return def;
623 args.respond = respond > 0;
624 args.respond_to_missing = !UNDEF_P(ret);
625 ret = def;
626 cme = callable_method_entry(klass, idMethodMissing, &args.defined_class);
627
628 if (cme && !METHOD_ENTRY_BASIC(cme)) {
629 VALUE argbuf, *new_args = ALLOCV_N(VALUE, argbuf, argc+1);
630
631 new_args[0] = ID2SYM(mid);
632 #ifdef __GLIBC__
633 if (!argv) {
634 static const VALUE buf = Qfalse;
635 VM_ASSERT(argc == 0);
636 argv = &buf;
637 }
638 #endif
639 MEMCPY(new_args+1, argv, VALUE, argc);
640 ec->method_missing_reason = MISSING_NOENTRY;
641 args.ec = ec;
642 args.recv = recv;
643 args.cme = cme;
644 args.mid = mid;
645 args.argc = argc + 1;
646 args.argv = new_args;
647 args.kw_splat = kw_splat;
648 ret = rb_rescue2(check_funcall_exec, (VALUE)&args,
649 check_funcall_failed, (VALUE)&args,
651 ALLOCV_END(argbuf);
652 }
653 return ret;
654}
655
656static VALUE rb_check_funcall_default_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE def, int kw_splat);
657
658VALUE
659rb_check_funcall_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
660{
661 return rb_check_funcall_default_kw(recv, mid, argc, argv, Qundef, kw_splat);
662}
663
664VALUE
665rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
666{
667 return rb_check_funcall_default_kw(recv, mid, argc, argv, Qundef, RB_NO_KEYWORDS);
668}
669
670static VALUE
671rb_check_funcall_default_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE def, int kw_splat)
672{
673 VM_ASSERT(ruby_thread_has_gvl_p());
674
675 VALUE klass = CLASS_OF(recv);
677 rb_execution_context_t *ec = GET_EC();
678 int respond = check_funcall_respond_to(ec, klass, recv, mid);
679
680 if (!respond)
681 return def;
682
683 me = rb_search_method_entry(recv, mid);
684 if (!check_funcall_callable(ec, me)) {
685 VALUE ret = check_funcall_missing(ec, klass, recv, mid, argc, argv,
686 respond, def, kw_splat);
687 if (UNDEF_P(ret)) ret = def;
688 return ret;
689 }
690 stack_check(ec);
691 return rb_vm_call_kw(ec, recv, mid, argc, argv, me, kw_splat);
692}
693
694VALUE
695rb_check_funcall_default(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE def)
696{
697 return rb_check_funcall_default_kw(recv, mid, argc, argv, def, RB_NO_KEYWORDS);
698}
699
700VALUE
701rb_check_funcall_with_hook_kw(VALUE recv, ID mid, int argc, const VALUE *argv,
702 rb_check_funcall_hook *hook, VALUE arg, int kw_splat)
703{
704 VALUE klass = CLASS_OF(recv);
706 rb_execution_context_t *ec = GET_EC();
707 int respond = check_funcall_respond_to(ec, klass, recv, mid);
708
709 if (!respond) {
710 (*hook)(FALSE, recv, mid, argc, argv, arg);
711 return Qundef;
712 }
713
714 me = rb_search_method_entry(recv, mid);
715 if (!check_funcall_callable(ec, me)) {
716 VALUE ret = check_funcall_missing(ec, klass, recv, mid, argc, argv,
717 respond, Qundef, kw_splat);
718 (*hook)(!UNDEF_P(ret), recv, mid, argc, argv, arg);
719 return ret;
720 }
721 stack_check(ec);
722 (*hook)(TRUE, recv, mid, argc, argv, arg);
723 return rb_vm_call_kw(ec, recv, mid, argc, argv, me, kw_splat);
724}
725
726VALUE
727rb_check_funcall_with_hook(VALUE recv, ID mid, int argc, const VALUE *argv,
728 rb_check_funcall_hook *hook, VALUE arg)
729{
730 return rb_check_funcall_with_hook_kw(recv, mid, argc, argv, hook, arg, RB_NO_KEYWORDS);
731}
732
733const char *
734rb_type_str(enum ruby_value_type type)
735{
736#define type_case(t) t: return #t
737 switch (type) {
738 case type_case(T_NONE);
739 case type_case(T_OBJECT);
740 case type_case(T_CLASS);
741 case type_case(T_MODULE);
742 case type_case(T_FLOAT);
743 case type_case(T_STRING);
744 case type_case(T_REGEXP);
745 case type_case(T_ARRAY);
746 case type_case(T_HASH);
747 case type_case(T_STRUCT);
748 case type_case(T_BIGNUM);
749 case type_case(T_FILE);
750 case type_case(T_DATA);
751 case type_case(T_MATCH);
752 case type_case(T_COMPLEX);
753 case type_case(T_RATIONAL);
754 case type_case(T_NIL);
755 case type_case(T_TRUE);
756 case type_case(T_FALSE);
757 case type_case(T_SYMBOL);
758 case type_case(T_FIXNUM);
759 case type_case(T_IMEMO);
760 case type_case(T_UNDEF);
761 case type_case(T_NODE);
762 case type_case(T_ICLASS);
763 case type_case(T_ZOMBIE);
764 case type_case(T_MOVED);
765 case T_MASK: break;
766 }
767#undef type_case
768 return NULL;
769}
770
771static void
772uncallable_object(VALUE recv, ID mid)
773{
774 VALUE flags;
775 int type;
776 const char *typestr;
777 VALUE mname = rb_id2str(mid);
778
779 if (SPECIAL_CONST_P(recv)) {
781 "method `%"PRIsVALUE"' called on unexpected immediate object (%p)",
782 mname, (void *)recv);
783 }
784 else if ((flags = RBASIC(recv)->flags) == 0) {
786 "method `%"PRIsVALUE"' called on terminated object (%p)",
787 mname, (void *)recv);
788 }
789 else if (!(typestr = rb_type_str(type = BUILTIN_TYPE(recv)))) {
791 "method `%"PRIsVALUE"' called on broken T_?""?""?(0x%02x) object"
792 " (%p flags=0x%"PRIxVALUE")",
793 mname, type, (void *)recv, flags);
794 }
795 else if (T_OBJECT <= type && type < T_NIL) {
797 "method `%"PRIsVALUE"' called on hidden %s object"
798 " (%p flags=0x%"PRIxVALUE")",
799 mname, typestr, (void *)recv, flags);
800 }
801 else {
803 "method `%"PRIsVALUE"' called on unexpected %s object"
804 " (%p flags=0x%"PRIxVALUE")",
805 mname, typestr, (void *)recv, flags);
806 }
807}
808
809static inline const rb_callable_method_entry_t *
810rb_search_method_entry(VALUE recv, ID mid)
811{
812 VALUE klass = CLASS_OF(recv);
813
814 if (!klass) uncallable_object(recv, mid);
815 return rb_callable_method_entry(klass, mid);
816}
817
818static inline enum method_missing_reason
819rb_method_call_status(rb_execution_context_t *ec, const rb_callable_method_entry_t *me, call_type scope, VALUE self)
820{
821 if (UNLIKELY(UNDEFINED_METHOD_ENTRY_P(me))) {
822 goto undefined;
823 }
824 else if (UNLIKELY(me->def->type == VM_METHOD_TYPE_REFINED)) {
825 me = rb_resolve_refined_method_callable(Qnil, me);
826 if (UNDEFINED_METHOD_ENTRY_P(me)) goto undefined;
827 }
828
829 rb_method_visibility_t visi = METHOD_ENTRY_VISI(me);
830
831 /* receiver specified form for private method */
832 if (UNLIKELY(visi != METHOD_VISI_PUBLIC)) {
833 if (me->def->original_id == idMethodMissing) {
834 return MISSING_NONE;
835 }
836 else if (visi == METHOD_VISI_PRIVATE &&
837 scope == CALL_PUBLIC) {
838 return MISSING_PRIVATE;
839 }
840 /* self must be kind of a specified form for protected method */
841 else if (visi == METHOD_VISI_PROTECTED &&
842 scope == CALL_PUBLIC) {
843
844 VALUE defined_class = me->owner;
845 if (RB_TYPE_P(defined_class, T_ICLASS)) {
846 defined_class = RBASIC(defined_class)->klass;
847 }
848
849 if (UNDEF_P(self) || !rb_obj_is_kind_of(self, defined_class)) {
850 return MISSING_PROTECTED;
851 }
852 }
853 }
854
855 return MISSING_NONE;
856
857 undefined:
858 return scope == CALL_VCALL ? MISSING_VCALL : MISSING_NOENTRY;
859}
860
861
873static inline VALUE
874rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope)
875{
876 rb_execution_context_t *ec = GET_EC();
877 return rb_call0(ec, recv, mid, argc, argv, scope, ec->cfp->self);
878}
879
880NORETURN(static void raise_method_missing(rb_execution_context_t *ec, int argc, const VALUE *argv,
881 VALUE obj, enum method_missing_reason call_status));
882
883/*
884 * call-seq:
885 * obj.method_missing(symbol [, *args] ) -> result
886 *
887 * Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
888 * <i>symbol</i> is the symbol for the method called, and <i>args</i>
889 * are any arguments that were passed to it. By default, the interpreter
890 * raises an error when this method is called. However, it is possible
891 * to override the method to provide more dynamic behavior.
892 * If it is decided that a particular method should not be handled, then
893 * <i>super</i> should be called, so that ancestors can pick up the
894 * missing method.
895 * The example below creates
896 * a class <code>Roman</code>, which responds to methods with names
897 * consisting of roman numerals, returning the corresponding integer
898 * values.
899 *
900 * class Roman
901 * def roman_to_int(str)
902 * # ...
903 * end
904 *
905 * def method_missing(symbol, *args)
906 * str = symbol.id2name
907 * begin
908 * roman_to_int(str)
909 * rescue
910 * super(symbol, *args)
911 * end
912 * end
913 * end
914 *
915 * r = Roman.new
916 * r.iv #=> 4
917 * r.xxiii #=> 23
918 * r.mm #=> 2000
919 * r.foo #=> NoMethodError
920 */
921
922static VALUE
923rb_method_missing(int argc, const VALUE *argv, VALUE obj)
924{
925 rb_execution_context_t *ec = GET_EC();
926 raise_method_missing(ec, argc, argv, obj, ec->method_missing_reason);
928}
929
930MJIT_FUNC_EXPORTED VALUE
931rb_make_no_method_exception(VALUE exc, VALUE format, VALUE obj,
932 int argc, const VALUE *argv, int priv)
933{
934 VALUE name = argv[0];
935
936 if (!format) {
937 format = rb_fstring_lit("undefined method `%s' for %s%s%s");
938 }
939 if (exc == rb_eNoMethodError) {
940 VALUE args = rb_ary_new4(argc - 1, argv + 1);
941 return rb_nomethod_err_new(format, obj, name, args, priv);
942 }
943 else {
944 return rb_name_err_new(format, obj, name);
945 }
946}
947
948#endif /* #ifndef MJIT_HEADER */
949
950static void
951raise_method_missing(rb_execution_context_t *ec, int argc, const VALUE *argv, VALUE obj,
952 enum method_missing_reason last_call_status)
953{
955 VALUE format = 0;
956
957 if (UNLIKELY(argc == 0)) {
958 rb_raise(rb_eArgError, "no method name given");
959 }
960 else if (UNLIKELY(!SYMBOL_P(argv[0]))) {
961 const VALUE e = rb_eArgError; /* TODO: TypeError? */
962 rb_raise(e, "method name must be a Symbol but %"PRIsVALUE" is given",
963 rb_obj_class(argv[0]));
964 }
965
966 stack_check(ec);
967
968 if (last_call_status & MISSING_PRIVATE) {
969 format = rb_fstring_lit("private method `%s' called for %s%s%s");
970 }
971 else if (last_call_status & MISSING_PROTECTED) {
972 format = rb_fstring_lit("protected method `%s' called for %s%s%s");
973 }
974 else if (last_call_status & MISSING_VCALL) {
975 format = rb_fstring_lit("undefined local variable or method `%s' for %s%s%s");
976 exc = rb_eNameError;
977 }
978 else if (last_call_status & MISSING_SUPER) {
979 format = rb_fstring_lit("super: no superclass method `%s' for %s%s%s");
980 }
981
982 {
983 exc = rb_make_no_method_exception(exc, format, obj, argc, argv,
984 last_call_status & (MISSING_FCALL|MISSING_VCALL));
985 if (!(last_call_status & MISSING_MISSING)) {
986 rb_vm_pop_cfunc_frame();
987 }
988 rb_exc_raise(exc);
989 }
990}
991
992static void
993vm_raise_method_missing(rb_execution_context_t *ec, int argc, const VALUE *argv,
994 VALUE obj, int call_status)
995{
996 vm_passed_block_handler_set(ec, VM_BLOCK_HANDLER_NONE);
997 raise_method_missing(ec, argc, argv, obj, call_status | MISSING_MISSING);
998}
999
1000static inline VALUE
1001method_missing(rb_execution_context_t *ec, VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status, int kw_splat)
1002{
1003 VALUE *nargv, result, work, klass;
1004 VALUE block_handler = vm_passed_block_handler(ec);
1006
1007 ec->method_missing_reason = call_status;
1008
1009 if (id == idMethodMissing) {
1010 goto missing;
1011 }
1012
1013 nargv = ALLOCV_N(VALUE, work, argc + 1);
1014 nargv[0] = ID2SYM(id);
1015 #ifdef __GLIBC__
1016 if (!argv) {
1017 static const VALUE buf = Qfalse;
1018 VM_ASSERT(argc == 0);
1019 argv = &buf;
1020 }
1021 #endif
1022 MEMCPY(nargv + 1, argv, VALUE, argc);
1023 ++argc;
1024 argv = nargv;
1025
1026 klass = CLASS_OF(obj);
1027 if (!klass) goto missing;
1028 me = rb_callable_method_entry(klass, idMethodMissing);
1029 if (!me || METHOD_ENTRY_BASIC(me)) goto missing;
1030 vm_passed_block_handler_set(ec, block_handler);
1031 result = rb_vm_call_kw(ec, obj, idMethodMissing, argc, argv, me, kw_splat);
1032 if (work) ALLOCV_END(work);
1033 return result;
1034 missing:
1035 raise_method_missing(ec, argc, argv, obj, call_status | MISSING_MISSING);
1037}
1038
1039#ifndef MJIT_HEADER
1040
1041static inline VALUE
1042rb_funcallv_scope(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope)
1043{
1044 rb_execution_context_t *ec = GET_EC();
1045 const struct rb_callcache *cc = gccct_method_search(ec, recv, mid, argc);
1046 VALUE self = ec->cfp->self;
1047
1048 if (LIKELY(cc) &&
1049 LIKELY(rb_method_call_status(ec, vm_cc_cme(cc), scope, self) == MISSING_NONE)) {
1050 // fastpath
1051 return vm_call0_cc(ec, recv, mid, argc, argv, cc, false);
1052 }
1053 else {
1054 return rb_call0(ec, recv, mid, argc, argv, scope, self);
1055 }
1056}
1057
1058#ifdef rb_funcallv
1059#undef rb_funcallv
1060#endif
1061VALUE
1062rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
1063{
1064 VM_ASSERT(ruby_thread_has_gvl_p());
1065
1066 return rb_funcallv_scope(recv, mid, argc, argv, CALL_FCALL);
1067}
1068
1069VALUE
1070rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
1071{
1072 VM_ASSERT(ruby_thread_has_gvl_p());
1073
1074 return rb_call(recv, mid, argc, argv, kw_splat ? CALL_FCALL_KW : CALL_FCALL);
1075}
1076
1077VALUE
1078rb_apply(VALUE recv, ID mid, VALUE args)
1079{
1080 int argc;
1081 VALUE *argv, ret;
1082
1083 argc = RARRAY_LENINT(args);
1084 if (argc >= 0x100) {
1085 args = rb_ary_subseq(args, 0, argc);
1086 RBASIC_CLEAR_CLASS(args);
1087 OBJ_FREEZE(args);
1088 ret = rb_call(recv, mid, argc, RARRAY_CONST_PTR(args), CALL_FCALL);
1089 RB_GC_GUARD(args);
1090 return ret;
1091 }
1092 argv = ALLOCA_N(VALUE, argc);
1093 MEMCPY(argv, RARRAY_CONST_PTR_TRANSIENT(args), VALUE, argc);
1094
1095 return rb_funcallv(recv, mid, argc, argv);
1096}
1097
1098#ifdef rb_funcall
1099#undef rb_funcall
1100#endif
1101
1102VALUE
1103rb_funcall(VALUE recv, ID mid, int n, ...)
1104{
1105 VALUE *argv;
1106 va_list ar;
1107
1108 if (n > 0) {
1109 long i;
1110
1111 va_start(ar, n);
1112
1113 argv = ALLOCA_N(VALUE, n);
1114
1115 for (i = 0; i < n; i++) {
1116 argv[i] = va_arg(ar, VALUE);
1117 }
1118 va_end(ar);
1119 }
1120 else {
1121 argv = 0;
1122 }
1123 return rb_funcallv(recv, mid, n, argv);
1124}
1125
1136VALUE
1137rb_check_funcall_basic_kw(VALUE recv, ID mid, VALUE ancestor, int argc, const VALUE *argv, int kw_splat)
1138{
1139 const rb_callable_method_entry_t *cme;
1141 VALUE klass = CLASS_OF(recv);
1142 if (!klass) return Qundef; /* hidden object */
1143
1144 cme = rb_callable_method_entry(klass, mid);
1145 if (cme && METHOD_ENTRY_BASIC(cme) && RBASIC_CLASS(cme->defined_class) == ancestor) {
1146 ec = GET_EC();
1147 return rb_vm_call0(ec, recv, mid, argc, argv, cme, kw_splat);
1148 }
1149
1150 return Qundef;
1151}
1152
1153VALUE
1154rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv)
1155{
1156 return rb_funcallv_scope(recv, mid, argc, argv, CALL_PUBLIC);
1157}
1158
1159VALUE
1160rb_funcallv_public_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
1161{
1162 return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
1163}
1164
1165VALUE
1166rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv)
1167{
1168 PASS_PASSED_BLOCK_HANDLER();
1169 return rb_funcallv_public(recv, mid, argc, argv);
1170}
1171
1172VALUE
1173rb_funcall_passing_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
1174{
1175 PASS_PASSED_BLOCK_HANDLER();
1176 return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
1177}
1178
1179VALUE
1180rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE passed_procval)
1181{
1182 if (!NIL_P(passed_procval)) {
1183 vm_passed_block_handler_set(GET_EC(), passed_procval);
1184 }
1185
1186 return rb_funcallv_public(recv, mid, argc, argv);
1187}
1188
1189VALUE
1190rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE passed_procval, int kw_splat)
1191{
1192 if (!NIL_P(passed_procval)) {
1193 vm_passed_block_handler_set(GET_EC(), passed_procval);
1194 }
1195
1196 return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
1197}
1198
1199static VALUE *
1200current_vm_stack_arg(const rb_execution_context_t *ec, const VALUE *argv)
1201{
1202 rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp);
1203 if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, prev_cfp)) return NULL;
1204 if (prev_cfp->sp + 1 != argv) return NULL;
1205 return prev_cfp->sp + 1;
1206}
1207
1208static VALUE
1209send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope)
1210{
1211 ID id;
1212 VALUE vid;
1213 VALUE self;
1214 VALUE ret, vargv = 0;
1215 rb_execution_context_t *ec = GET_EC();
1216 int public = scope == CALL_PUBLIC || scope == CALL_PUBLIC_KW;
1217
1218 if (public) {
1219 self = Qundef;
1220 }
1221 else {
1222 self = RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp)->self;
1223 }
1224
1225 if (argc == 0) {
1226 rb_raise(rb_eArgError, "no method name given");
1227 }
1228
1229 vid = *argv;
1230
1231 id = rb_check_id(&vid);
1232 if (!id) {
1233 if (rb_method_basic_definition_p(CLASS_OF(recv), idMethodMissing)) {
1234 VALUE exc = rb_make_no_method_exception(rb_eNoMethodError, 0,
1235 recv, argc, argv,
1236 !public);
1237 rb_exc_raise(exc);
1238 }
1239 if (!SYMBOL_P(*argv)) {
1240 VALUE *tmp_argv = current_vm_stack_arg(ec, argv);
1241 vid = rb_str_intern(vid);
1242 if (tmp_argv) {
1243 tmp_argv[0] = vid;
1244 }
1245 else if (argc > 1) {
1246 tmp_argv = ALLOCV_N(VALUE, vargv, argc);
1247 tmp_argv[0] = vid;
1248 MEMCPY(tmp_argv+1, argv+1, VALUE, argc-1);
1249 argv = tmp_argv;
1250 }
1251 else {
1252 argv = &vid;
1253 }
1254 }
1255 id = idMethodMissing;
1256 ec->method_missing_reason = MISSING_NOENTRY;
1257 }
1258 else {
1259 argv++; argc--;
1260 }
1261 PASS_PASSED_BLOCK_HANDLER_EC(ec);
1262 ret = rb_call0(ec, recv, id, argc, argv, scope, self);
1263 ALLOCV_END(vargv);
1264 return ret;
1265}
1266
1267static VALUE
1268send_internal_kw(int argc, const VALUE *argv, VALUE recv, call_type scope)
1269{
1270 if (rb_keyword_given_p()) {
1271 switch (scope) {
1272 case CALL_PUBLIC:
1273 scope = CALL_PUBLIC_KW;
1274 break;
1275 case CALL_FCALL:
1276 scope = CALL_FCALL_KW;
1277 break;
1278 default:
1279 break;
1280 }
1281 }
1282 return send_internal(argc, argv, recv, scope);
1283}
1284
1285/*
1286 * call-seq:
1287 * foo.send(symbol [, args...]) -> obj
1288 * foo.__send__(symbol [, args...]) -> obj
1289 * foo.send(string [, args...]) -> obj
1290 * foo.__send__(string [, args...]) -> obj
1291 *
1292 * Invokes the method identified by _symbol_, passing it any
1293 * arguments specified.
1294 * When the method is identified by a string, the string is converted
1295 * to a symbol.
1296 *
1297 * BasicObject implements +__send__+, Kernel implements +send+.
1298 * <code>__send__</code> is safer than +send+
1299 * when _obj_ has the same method name like <code>Socket</code>.
1300 * See also <code>public_send</code>.
1301 *
1302 * class Klass
1303 * def hello(*args)
1304 * "Hello " + args.join(' ')
1305 * end
1306 * end
1307 * k = Klass.new
1308 * k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
1309 */
1310
1311VALUE
1312rb_f_send(int argc, VALUE *argv, VALUE recv)
1313{
1314 return send_internal_kw(argc, argv, recv, CALL_FCALL);
1315}
1316
1317/*
1318 * call-seq:
1319 * obj.public_send(symbol [, args...]) -> obj
1320 * obj.public_send(string [, args...]) -> obj
1321 *
1322 * Invokes the method identified by _symbol_, passing it any
1323 * arguments specified. Unlike send, public_send calls public
1324 * methods only.
1325 * When the method is identified by a string, the string is converted
1326 * to a symbol.
1327 *
1328 * 1.public_send(:puts, "hello") # causes NoMethodError
1329 */
1330
1331static VALUE
1332rb_f_public_send(int argc, VALUE *argv, VALUE recv)
1333{
1334 return send_internal_kw(argc, argv, recv, CALL_PUBLIC);
1335}
1336
1337/* yield */
1338
1339static inline VALUE
1340rb_yield_0_kw(int argc, const VALUE * argv, int kw_splat)
1341{
1342 return vm_yield(GET_EC(), argc, argv, kw_splat);
1343}
1344
1345static inline VALUE
1346rb_yield_0(int argc, const VALUE * argv)
1347{
1348 return vm_yield(GET_EC(), argc, argv, RB_NO_KEYWORDS);
1349}
1350
1351VALUE
1352rb_yield_1(VALUE val)
1353{
1354 return rb_yield_0(1, &val);
1355}
1356
1357VALUE
1359{
1360 if (UNDEF_P(val)) {
1361 return rb_yield_0(0, NULL);
1362 }
1363 else {
1364 return rb_yield_0(1, &val);
1365 }
1366}
1367
1368#undef rb_yield_values
1369VALUE
1370rb_yield_values(int n, ...)
1371{
1372 if (n == 0) {
1373 return rb_yield_0(0, 0);
1374 }
1375 else {
1376 int i;
1377 VALUE *argv;
1378 va_list args;
1379 argv = ALLOCA_N(VALUE, n);
1380
1381 va_start(args, n);
1382 for (i=0; i<n; i++) {
1383 argv[i] = va_arg(args, VALUE);
1384 }
1385 va_end(args);
1386
1387 return rb_yield_0(n, argv);
1388 }
1389}
1390
1391VALUE
1392rb_yield_values2(int argc, const VALUE *argv)
1393{
1394 return rb_yield_0(argc, argv);
1395}
1396
1397VALUE
1398rb_yield_values_kw(int argc, const VALUE *argv, int kw_splat)
1399{
1400 return rb_yield_0_kw(argc, argv, kw_splat);
1401}
1402
1403VALUE
1405{
1406 VALUE tmp = rb_check_array_type(values);
1407 VALUE v;
1408 if (NIL_P(tmp)) {
1409 rb_raise(rb_eArgError, "not an array");
1410 }
1411 v = rb_yield_0(RARRAY_LENINT(tmp), RARRAY_CONST_PTR(tmp));
1412 RB_GC_GUARD(tmp);
1413 return v;
1414}
1415
1416VALUE
1417rb_yield_splat_kw(VALUE values, int kw_splat)
1418{
1419 VALUE tmp = rb_check_array_type(values);
1420 VALUE v;
1421 if (NIL_P(tmp)) {
1422 rb_raise(rb_eArgError, "not an array");
1423 }
1424 v = rb_yield_0_kw(RARRAY_LENINT(tmp), RARRAY_CONST_PTR(tmp), kw_splat);
1425 RB_GC_GUARD(tmp);
1426 return v;
1427}
1428
1429VALUE
1430rb_yield_force_blockarg(VALUE values)
1431{
1432 return vm_yield_force_blockarg(GET_EC(), values);
1433}
1434
1435VALUE
1437{
1438 return vm_yield_with_block(GET_EC(), argc, argv,
1439 NIL_P(blockarg) ? VM_BLOCK_HANDLER_NONE : blockarg,
1441}
1442
1443static VALUE
1444loop_i(VALUE _)
1445{
1446 for (;;) {
1447 rb_yield_0(0, 0);
1448 }
1449 return Qnil;
1450}
1451
1452static VALUE
1453loop_stop(VALUE dummy, VALUE exc)
1454{
1455 return rb_attr_get(exc, id_result);
1456}
1457
1458static VALUE
1459rb_f_loop_size(VALUE self, VALUE args, VALUE eobj)
1460{
1461 return DBL2NUM(HUGE_VAL);
1462}
1463
1464/*
1465 * call-seq:
1466 * loop { block }
1467 * loop -> an_enumerator
1468 *
1469 * Repeatedly executes the block.
1470 *
1471 * If no block is given, an enumerator is returned instead.
1472 *
1473 * loop do
1474 * print "Input: "
1475 * line = gets
1476 * break if !line or line =~ /^q/i
1477 * # ...
1478 * end
1479 *
1480 * StopIteration raised in the block breaks the loop. In this case,
1481 * loop returns the "result" value stored in the exception.
1482 *
1483 * enum = Enumerator.new { |y|
1484 * y << "one"
1485 * y << "two"
1486 * :ok
1487 * }
1488 *
1489 * result = loop {
1490 * puts enum.next
1491 * } #=> :ok
1492 */
1493
1494static VALUE
1495rb_f_loop(VALUE self)
1496{
1497 RETURN_SIZED_ENUMERATOR(self, 0, 0, rb_f_loop_size);
1498 return rb_rescue2(loop_i, (VALUE)0, loop_stop, (VALUE)0, rb_eStopIteration, (VALUE)0);
1499}
1500
1501#if VMDEBUG
1502static const char *
1503vm_frametype_name(const rb_control_frame_t *cfp);
1504#endif
1505
1506static VALUE
1507rb_iterate0(VALUE (* it_proc) (VALUE), VALUE data1,
1508 const struct vm_ifunc *const ifunc,
1510{
1511 enum ruby_tag_type state;
1512 volatile VALUE retval = Qnil;
1513 rb_control_frame_t *const cfp = ec->cfp;
1514
1515 EC_PUSH_TAG(ec);
1516 state = EC_EXEC_TAG();
1517 if (state == 0) {
1518 iter_retry:
1519 {
1520 VALUE block_handler;
1521
1522 if (ifunc) {
1523 struct rb_captured_block *captured = VM_CFP_TO_CAPTURED_BLOCK(cfp);
1524 captured->code.ifunc = ifunc;
1525 block_handler = VM_BH_FROM_IFUNC_BLOCK(captured);
1526 }
1527 else {
1528 block_handler = VM_CF_BLOCK_HANDLER(cfp);
1529 }
1530 vm_passed_block_handler_set(ec, block_handler);
1531 }
1532 retval = (*it_proc) (data1);
1533 }
1534 else if (state == TAG_BREAK || state == TAG_RETRY) {
1535 const struct vm_throw_data *const err = (struct vm_throw_data *)ec->errinfo;
1536 const rb_control_frame_t *const escape_cfp = THROW_DATA_CATCH_FRAME(err);
1537
1538 if (cfp == escape_cfp) {
1539 rb_vm_rewind_cfp(ec, cfp);
1540
1541 state = 0;
1542 ec->tag->state = TAG_NONE;
1543 ec->errinfo = Qnil;
1544
1545 if (state == TAG_RETRY) goto iter_retry;
1546 retval = THROW_DATA_VAL(err);
1547 }
1548 else if (0) {
1549 SDR(); fprintf(stderr, "%p, %p\n", (void *)cfp, (void *)escape_cfp);
1550 }
1551 }
1552 EC_POP_TAG();
1553
1554 if (state) {
1555 EC_JUMP_TAG(ec, state);
1556 }
1557 return retval;
1558}
1559
1560static VALUE
1561rb_iterate_internal(VALUE (* it_proc)(VALUE), VALUE data1,
1562 rb_block_call_func_t bl_proc, VALUE data2)
1563{
1564 return rb_iterate0(it_proc, data1,
1565 bl_proc ? rb_vm_ifunc_proc_new(bl_proc, (void *)data2) : 0,
1566 GET_EC());
1567}
1568
1569VALUE
1570rb_iterate(VALUE (* it_proc)(VALUE), VALUE data1,
1571 rb_block_call_func_t bl_proc, VALUE data2)
1572{
1573 return rb_iterate_internal(it_proc, data1, bl_proc, data2);
1574}
1575
1577 VALUE obj;
1578 ID mid;
1579 int argc;
1580 const VALUE *argv;
1581 int kw_splat;
1582};
1583
1584static VALUE
1585iterate_method(VALUE obj)
1586{
1587 const struct iter_method_arg * arg =
1588 (struct iter_method_arg *) obj;
1589
1590 return rb_call(arg->obj, arg->mid, arg->argc, arg->argv, arg->kw_splat ? CALL_FCALL_KW : CALL_FCALL);
1591}
1592
1593VALUE 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);
1594
1595VALUE
1596rb_block_call(VALUE obj, ID mid, int argc, const VALUE * argv,
1597 rb_block_call_func_t bl_proc, VALUE data2)
1598{
1599 return rb_block_call_kw(obj, mid, argc, argv, bl_proc, data2, RB_NO_KEYWORDS);
1600}
1601
1602VALUE
1603rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE * argv,
1604 rb_block_call_func_t bl_proc, VALUE data2, int kw_splat)
1605{
1606 struct iter_method_arg arg;
1607
1608 arg.obj = obj;
1609 arg.mid = mid;
1610 arg.argc = argc;
1611 arg.argv = argv;
1612 arg.kw_splat = kw_splat;
1613 return rb_iterate_internal(iterate_method, (VALUE)&arg, bl_proc, data2);
1614}
1615
1616VALUE
1617rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv,
1618 rb_block_call_func_t bl_proc, int min_argc, int max_argc,
1619 VALUE data2)
1620{
1621 struct iter_method_arg arg;
1622 struct vm_ifunc *block;
1623
1624 if (!bl_proc) rb_raise(rb_eArgError, "NULL lambda function");
1625 arg.obj = obj;
1626 arg.mid = mid;
1627 arg.argc = argc;
1628 arg.argv = argv;
1629 arg.kw_splat = 0;
1630 block = rb_vm_ifunc_new(bl_proc, (void *)data2, min_argc, max_argc);
1631 return rb_iterate0(iterate_method, (VALUE)&arg, block, GET_EC());
1632}
1633
1634static VALUE
1635iterate_check_method(VALUE obj)
1636{
1637 const struct iter_method_arg * arg =
1638 (struct iter_method_arg *) obj;
1639
1640 return rb_check_funcall(arg->obj, arg->mid, arg->argc, arg->argv);
1641}
1642
1643VALUE
1644rb_check_block_call(VALUE obj, ID mid, int argc, const VALUE *argv,
1645 rb_block_call_func_t bl_proc, VALUE data2)
1646{
1647 struct iter_method_arg arg;
1648
1649 arg.obj = obj;
1650 arg.mid = mid;
1651 arg.argc = argc;
1652 arg.argv = argv;
1653 arg.kw_splat = 0;
1654 return rb_iterate_internal(iterate_check_method, (VALUE)&arg, bl_proc, data2);
1655}
1656
1657VALUE
1659{
1660 return rb_call(obj, idEach, 0, 0, CALL_FCALL);
1661}
1662
1663void rb_parser_warn_location(VALUE, int);
1664
1665static VALUE eval_default_path;
1666
1667static const rb_iseq_t *
1668eval_make_iseq(VALUE src, VALUE fname, int line, const rb_binding_t *bind,
1669 const struct rb_block *base_block)
1670{
1671 const VALUE parser = rb_parser_new();
1672 const rb_iseq_t *const parent = vm_block_iseq(base_block);
1673 rb_iseq_t *iseq = NULL;
1674 rb_ast_t *ast;
1675 int isolated_depth = 0;
1676
1677 // Conditionally enable coverage depending on the current mode:
1678 VALUE coverage_enabled = RBOOL(rb_get_coverage_mode() & COVERAGE_TARGET_EVAL);
1679
1680 {
1681 int depth = 1;
1682 const VALUE *ep = vm_block_ep(base_block);
1683
1684 while (1) {
1685 if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ISOLATED)) {
1686 isolated_depth = depth;
1687 break;
1688 }
1689 else if (VM_ENV_LOCAL_P(ep)) {
1690 break;
1691 }
1692 ep = VM_ENV_PREV_EP(ep);
1693 depth++;
1694 }
1695 }
1696
1697 if (!fname) {
1698 fname = rb_source_location(&line);
1699 }
1700
1701 if (!UNDEF_P(fname)) {
1702 if (!NIL_P(fname)) fname = rb_fstring(fname);
1703 }
1704 else {
1705 fname = rb_fstring_lit("(eval)");
1706 if (!eval_default_path) {
1707 eval_default_path = rb_fstring_lit("(eval)");
1708 rb_gc_register_mark_object(eval_default_path);
1709 }
1710 fname = eval_default_path;
1711 coverage_enabled = Qfalse;
1712 }
1713
1714 rb_parser_set_context(parser, parent, FALSE);
1715 ast = rb_parser_compile_string_path(parser, fname, src, line);
1716 if (ast->body.root) {
1717 if (ast->body.compile_option == Qnil) {
1718 ast->body.compile_option = rb_obj_hide(rb_ident_hash_new());
1719 }
1720 rb_hash_aset(ast->body.compile_option, rb_sym_intern_ascii_cstr("coverage_enabled"), coverage_enabled);
1721
1722 iseq = rb_iseq_new_eval(&ast->body,
1723 ISEQ_BODY(parent)->location.label,
1724 fname, Qnil, line,
1725 parent, isolated_depth);
1726 }
1727 rb_ast_dispose(ast);
1728
1729 if (iseq != NULL) {
1730 if (0 && iseq) { /* for debug */
1731 VALUE disasm = rb_iseq_disasm(iseq);
1732 printf("%s\n", StringValuePtr(disasm));
1733 }
1734
1735 rb_exec_event_hook_script_compiled(GET_EC(), iseq, src);
1736 }
1737
1738 return iseq;
1739}
1740
1741static VALUE
1742eval_string_with_cref(VALUE self, VALUE src, rb_cref_t *cref, VALUE file, int line)
1743{
1744 rb_execution_context_t *ec = GET_EC();
1745 struct rb_block block;
1746 const rb_iseq_t *iseq;
1747 rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
1748 if (!cfp) {
1749 rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread");
1750 }
1751
1752 block.as.captured = *VM_CFP_TO_CAPTURED_BLOCK(cfp);
1753 block.as.captured.self = self;
1754 block.as.captured.code.iseq = cfp->iseq;
1755 block.type = block_type_iseq;
1756
1757 iseq = eval_make_iseq(src, file, line, NULL, &block);
1758 if (!iseq) {
1759 rb_exc_raise(ec->errinfo);
1760 }
1761
1762 /* TODO: what the code checking? */
1763 if (!cref && block.as.captured.code.val) {
1764 rb_cref_t *orig_cref = vm_get_cref(vm_block_ep(&block));
1765 cref = vm_cref_dup(orig_cref);
1766 }
1767 vm_set_eval_stack(ec, iseq, cref, &block);
1768
1769 /* kick */
1770 return vm_exec(ec, true);
1771}
1772
1773static VALUE
1774eval_string_with_scope(VALUE scope, VALUE src, VALUE file, int line)
1775{
1776 rb_execution_context_t *ec = GET_EC();
1777 rb_binding_t *bind = Check_TypedStruct(scope, &ruby_binding_data_type);
1778 const rb_iseq_t *iseq = eval_make_iseq(src, file, line, bind, &bind->block);
1779 if (!iseq) {
1780 rb_exc_raise(ec->errinfo);
1781 }
1782
1783 vm_set_eval_stack(ec, iseq, NULL, &bind->block);
1784
1785 /* save new env */
1786 if (ISEQ_BODY(iseq)->local_table_size > 0) {
1787 vm_bind_update_env(scope, bind, vm_make_env_object(ec, ec->cfp));
1788 }
1789
1790 /* kick */
1791 return vm_exec(ec, true);
1792}
1793
1794/*
1795 * call-seq:
1796 * eval(string [, binding [, filename [,lineno]]]) -> obj
1797 *
1798 * Evaluates the Ruby expression(s) in <em>string</em>. If
1799 * <em>binding</em> is given, which must be a Binding object, the
1800 * evaluation is performed in its context. If the optional
1801 * <em>filename</em> and <em>lineno</em> parameters are present, they
1802 * will be used when reporting syntax errors.
1803 *
1804 * def get_binding(str)
1805 * return binding
1806 * end
1807 * str = "hello"
1808 * eval "str + ' Fred'" #=> "hello Fred"
1809 * eval "str + ' Fred'", get_binding("bye") #=> "bye Fred"
1810 */
1811
1812VALUE
1813rb_f_eval(int argc, const VALUE *argv, VALUE self)
1814{
1815 VALUE src, scope, vfile, vline;
1816 VALUE file = Qundef;
1817 int line = 1;
1818
1819 rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
1820 SafeStringValue(src);
1821 if (argc >= 3) {
1822 StringValue(vfile);
1823 }
1824 if (argc >= 4) {
1825 line = NUM2INT(vline);
1826 }
1827
1828 if (!NIL_P(vfile))
1829 file = vfile;
1830
1831 if (NIL_P(scope))
1832 return eval_string_with_cref(self, src, NULL, file, line);
1833 else
1834 return eval_string_with_scope(scope, src, file, line);
1835}
1836
1838VALUE
1839ruby_eval_string_from_file(const char *str, const char *filename)
1840{
1841 VALUE file = filename ? rb_str_new_cstr(filename) : 0;
1842 rb_execution_context_t *ec = GET_EC();
1843 rb_control_frame_t *cfp = ec ? rb_vm_get_ruby_level_next_cfp(ec, ec->cfp) : NULL;
1844 VALUE self = cfp ? cfp->self : rb_vm_top_self();
1845 return eval_string_with_cref(self, rb_str_new2(str), NULL, file, 1);
1846}
1847
1848VALUE
1849rb_eval_string(const char *str)
1850{
1851 return ruby_eval_string_from_file(str, "eval");
1852}
1853
1854static VALUE
1855eval_string_protect(VALUE str)
1856{
1857 return rb_eval_string((char *)str);
1858}
1859
1860VALUE
1861rb_eval_string_protect(const char *str, int *pstate)
1862{
1863 return rb_protect(eval_string_protect, (VALUE)str, pstate);
1864}
1865
1867 VALUE top_self;
1868 VALUE klass;
1869 const char *str;
1870};
1871
1872static VALUE
1873eval_string_wrap_protect(VALUE data)
1874{
1875 const struct eval_string_wrap_arg *const arg = (struct eval_string_wrap_arg*)data;
1876 rb_cref_t *cref = rb_vm_cref_new_toplevel();
1877 cref->klass_or_self = arg->klass;
1878 return eval_string_with_cref(arg->top_self, rb_str_new_cstr(arg->str), cref, rb_str_new_cstr("eval"), 1);
1879}
1880
1881VALUE
1882rb_eval_string_wrap(const char *str, int *pstate)
1883{
1884 int state;
1885 rb_thread_t *th = GET_THREAD();
1886 VALUE self = th->top_self;
1887 VALUE wrapper = th->top_wrapper;
1888 VALUE val;
1889 struct eval_string_wrap_arg data;
1890
1891 th->top_wrapper = rb_module_new();
1892 th->top_self = rb_obj_clone(rb_vm_top_self());
1893 rb_extend_object(th->top_self, th->top_wrapper);
1894
1895 data.top_self = th->top_self;
1896 data.klass = th->top_wrapper;
1897 data.str = str;
1898
1899 val = rb_protect(eval_string_wrap_protect, (VALUE)&data, &state);
1900
1901 th->top_self = self;
1902 th->top_wrapper = wrapper;
1903
1904 if (pstate) {
1905 *pstate = state;
1906 }
1907 else if (state != TAG_NONE) {
1908 EC_JUMP_TAG(th->ec, state);
1909 }
1910 return val;
1911}
1912
1913VALUE
1914rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat)
1915{
1916 enum ruby_tag_type state;
1917 volatile VALUE val = Qnil; /* OK */
1918 rb_execution_context_t * volatile ec = GET_EC();
1919
1920 EC_PUSH_TAG(ec);
1921 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1922 if (!RB_TYPE_P(cmd, T_STRING)) {
1923 val = rb_funcallv_kw(cmd, idCall, RARRAY_LENINT(arg),
1924 RARRAY_CONST_PTR(arg), kw_splat);
1925 }
1926 else {
1927 val = eval_string_with_cref(rb_vm_top_self(), cmd, NULL, 0, 0);
1928 }
1929 }
1930 EC_POP_TAG();
1931
1932 if (state) EC_JUMP_TAG(ec, state);
1933 return val;
1934}
1935
1936/* block eval under the class/module context */
1937
1938static VALUE
1939yield_under(VALUE self, int singleton, int argc, const VALUE *argv, int kw_splat)
1940{
1941 rb_execution_context_t *ec = GET_EC();
1942 rb_control_frame_t *cfp = ec->cfp;
1943 VALUE block_handler = VM_CF_BLOCK_HANDLER(cfp);
1944 VALUE new_block_handler = 0;
1945 const struct rb_captured_block *captured = NULL;
1946 struct rb_captured_block new_captured;
1947 const VALUE *ep = NULL;
1948 rb_cref_t *cref;
1949 int is_lambda = FALSE;
1950
1951 if (block_handler != VM_BLOCK_HANDLER_NONE) {
1952 again:
1953 switch (vm_block_handler_type(block_handler)) {
1954 case block_handler_type_iseq:
1955 captured = VM_BH_TO_CAPT_BLOCK(block_handler);
1956 new_captured = *captured;
1957 new_block_handler = VM_BH_FROM_ISEQ_BLOCK(&new_captured);
1958 break;
1959 case block_handler_type_ifunc:
1960 captured = VM_BH_TO_CAPT_BLOCK(block_handler);
1961 new_captured = *captured;
1962 new_block_handler = VM_BH_FROM_IFUNC_BLOCK(&new_captured);
1963 break;
1964 case block_handler_type_proc:
1965 is_lambda = rb_proc_lambda_p(block_handler) != Qfalse;
1966 block_handler = vm_proc_to_block_handler(VM_BH_TO_PROC(block_handler));
1967 goto again;
1968 case block_handler_type_symbol:
1969 return rb_sym_proc_call(SYM2ID(VM_BH_TO_SYMBOL(block_handler)),
1970 argc, argv, kw_splat,
1971 VM_BLOCK_HANDLER_NONE);
1972 }
1973
1974 new_captured.self = self;
1975 ep = captured->ep;
1976
1977 VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(ec->cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler);
1978 }
1979
1980 VM_ASSERT(singleton || RB_TYPE_P(self, T_MODULE) || RB_TYPE_P(self, T_CLASS));
1981 cref = vm_cref_push(ec, self, ep, TRUE, singleton);
1982
1983 return vm_yield_with_cref(ec, argc, argv, kw_splat, cref, is_lambda);
1984}
1985
1986VALUE
1987rb_yield_refine_block(VALUE refinement, VALUE refinements)
1988{
1989 rb_execution_context_t *ec = GET_EC();
1990 VALUE block_handler = VM_CF_BLOCK_HANDLER(ec->cfp);
1991
1992 if (vm_block_handler_type(block_handler) != block_handler_type_iseq) {
1993 rb_bug("rb_yield_refine_block: an iseq block is required");
1994 }
1995 else {
1996 const struct rb_captured_block *captured = VM_BH_TO_ISEQ_BLOCK(block_handler);
1997 struct rb_captured_block new_captured = *captured;
1998 VALUE new_block_handler = VM_BH_FROM_ISEQ_BLOCK(&new_captured);
1999 const VALUE *ep = captured->ep;
2000 rb_cref_t *cref = vm_cref_push(ec, refinement, ep, TRUE, FALSE);
2001 CREF_REFINEMENTS_SET(cref, refinements);
2002 VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(ec->cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler);
2003 new_captured.self = refinement;
2004 return vm_yield_with_cref(ec, 0, NULL, RB_NO_KEYWORDS, cref, FALSE);
2005 }
2006}
2007
2008/* string eval under the class/module context */
2009static VALUE
2010eval_under(VALUE self, int singleton, VALUE src, VALUE file, int line)
2011{
2012 rb_cref_t *cref = vm_cref_push(GET_EC(), self, NULL, FALSE, singleton);
2013 SafeStringValue(src);
2014
2015 return eval_string_with_cref(self, src, cref, file, line);
2016}
2017
2018static VALUE
2019specific_eval(int argc, const VALUE *argv, VALUE self, int singleton, int kw_splat)
2020{
2021 if (rb_block_given_p()) {
2022 rb_check_arity(argc, 0, 0);
2023 return yield_under(self, singleton, 1, &self, kw_splat);
2024 }
2025 else {
2026 VALUE file = Qundef;
2027 int line = 1;
2028 VALUE code;
2029
2030 rb_check_arity(argc, 1, 3);
2031 code = argv[0];
2032 SafeStringValue(code);
2033 if (argc > 2)
2034 line = NUM2INT(argv[2]);
2035 if (argc > 1) {
2036 file = argv[1];
2037 if (!NIL_P(file)) StringValue(file);
2038 }
2039 return eval_under(self, singleton, code, file, line);
2040 }
2041}
2042
2043/*
2044 * call-seq:
2045 * obj.instance_eval(string [, filename [, lineno]] ) -> obj
2046 * obj.instance_eval {|obj| block } -> obj
2047 *
2048 * Evaluates a string containing Ruby source code, or the given block,
2049 * within the context of the receiver (_obj_). In order to set the
2050 * context, the variable +self+ is set to _obj_ while
2051 * the code is executing, giving the code access to _obj_'s
2052 * instance variables and private methods.
2053 *
2054 * When <code>instance_eval</code> is given a block, _obj_ is also
2055 * passed in as the block's only argument.
2056 *
2057 * When <code>instance_eval</code> is given a +String+, the optional
2058 * second and third parameters supply a filename and starting line number
2059 * that are used when reporting compilation errors.
2060 *
2061 * class KlassWithSecret
2062 * def initialize
2063 * @secret = 99
2064 * end
2065 * private
2066 * def the_secret
2067 * "Ssssh! The secret is #{@secret}."
2068 * end
2069 * end
2070 * k = KlassWithSecret.new
2071 * k.instance_eval { @secret } #=> 99
2072 * k.instance_eval { the_secret } #=> "Ssssh! The secret is 99."
2073 * k.instance_eval {|obj| obj == self } #=> true
2074 */
2075
2076static VALUE
2077rb_obj_instance_eval_internal(int argc, const VALUE *argv, VALUE self)
2078{
2079 return specific_eval(argc, argv, self, TRUE, RB_PASS_CALLED_KEYWORDS);
2080}
2081
2082VALUE
2083rb_obj_instance_eval(int argc, const VALUE *argv, VALUE self)
2084{
2085 return specific_eval(argc, argv, self, TRUE, RB_NO_KEYWORDS);
2086}
2087
2088/*
2089 * call-seq:
2090 * obj.instance_exec(arg...) {|var...| block } -> obj
2091 *
2092 * Executes the given block within the context of the receiver
2093 * (_obj_). In order to set the context, the variable +self+ is set
2094 * to _obj_ while the code is executing, giving the code access to
2095 * _obj_'s instance variables. Arguments are passed as block parameters.
2096 *
2097 * class KlassWithSecret
2098 * def initialize
2099 * @secret = 99
2100 * end
2101 * end
2102 * k = KlassWithSecret.new
2103 * k.instance_exec(5) {|x| @secret+x } #=> 104
2104 */
2105
2106static VALUE
2107rb_obj_instance_exec_internal(int argc, const VALUE *argv, VALUE self)
2108{
2109 return yield_under(self, TRUE, argc, argv, RB_PASS_CALLED_KEYWORDS);
2110}
2111
2112VALUE
2113rb_obj_instance_exec(int argc, const VALUE *argv, VALUE self)
2114{
2115 return yield_under(self, TRUE, argc, argv, RB_NO_KEYWORDS);
2116}
2117
2118/*
2119 * call-seq:
2120 * mod.class_eval(string [, filename [, lineno]]) -> obj
2121 * mod.class_eval {|mod| block } -> obj
2122 * mod.module_eval(string [, filename [, lineno]]) -> obj
2123 * mod.module_eval {|mod| block } -> obj
2124 *
2125 * Evaluates the string or block in the context of _mod_, except that when
2126 * a block is given, constant/class variable lookup is not affected. This
2127 * can be used to add methods to a class. <code>module_eval</code> returns
2128 * the result of evaluating its argument. The optional _filename_ and
2129 * _lineno_ parameters set the text for error messages.
2130 *
2131 * class Thing
2132 * end
2133 * a = %q{def hello() "Hello there!" end}
2134 * Thing.module_eval(a)
2135 * puts Thing.new.hello()
2136 * Thing.module_eval("invalid code", "dummy", 123)
2137 *
2138 * <em>produces:</em>
2139 *
2140 * Hello there!
2141 * dummy:123:in `module_eval': undefined local variable
2142 * or method `code' for Thing:Class
2143 */
2144
2145static VALUE
2146rb_mod_module_eval_internal(int argc, const VALUE *argv, VALUE mod)
2147{
2148 return specific_eval(argc, argv, mod, FALSE, RB_PASS_CALLED_KEYWORDS);
2149}
2150
2151VALUE
2152rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod)
2153{
2154 return specific_eval(argc, argv, mod, FALSE, RB_NO_KEYWORDS);
2155}
2156
2157/*
2158 * call-seq:
2159 * mod.module_exec(arg...) {|var...| block } -> obj
2160 * mod.class_exec(arg...) {|var...| block } -> obj
2161 *
2162 * Evaluates the given block in the context of the class/module.
2163 * The method defined in the block will belong to the receiver.
2164 * Any arguments passed to the method will be passed to the block.
2165 * This can be used if the block needs to access instance variables.
2166 *
2167 * class Thing
2168 * end
2169 * Thing.class_exec{
2170 * def hello() "Hello there!" end
2171 * }
2172 * puts Thing.new.hello()
2173 *
2174 * <em>produces:</em>
2175 *
2176 * Hello there!
2177 */
2178
2179static VALUE
2180rb_mod_module_exec_internal(int argc, const VALUE *argv, VALUE mod)
2181{
2182 return yield_under(mod, FALSE, argc, argv, RB_PASS_CALLED_KEYWORDS);
2183}
2184
2185VALUE
2186rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod)
2187{
2188 return yield_under(mod, FALSE, argc, argv, RB_NO_KEYWORDS);
2189}
2190
2191/*
2192 * Document-class: UncaughtThrowError
2193 *
2194 * Raised when +throw+ is called with a _tag_ which does not have
2195 * corresponding +catch+ block.
2196 *
2197 * throw "foo", "bar"
2198 *
2199 * <em>raises the exception:</em>
2200 *
2201 * UncaughtThrowError: uncaught throw "foo"
2202 */
2203
2204static VALUE
2205uncaught_throw_init(int argc, const VALUE *argv, VALUE exc)
2206{
2207 rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);
2208 rb_call_super(argc - 2, argv + 2);
2209 rb_ivar_set(exc, id_tag, argv[0]);
2210 rb_ivar_set(exc, id_value, argv[1]);
2211 return exc;
2212}
2213
2214/*
2215 * call-seq:
2216 * uncaught_throw.tag -> obj
2217 *
2218 * Return the tag object which was called for.
2219 */
2220
2221static VALUE
2222uncaught_throw_tag(VALUE exc)
2223{
2224 return rb_ivar_get(exc, id_tag);
2225}
2226
2227/*
2228 * call-seq:
2229 * uncaught_throw.value -> obj
2230 *
2231 * Return the return value which was called for.
2232 */
2233
2234static VALUE
2235uncaught_throw_value(VALUE exc)
2236{
2237 return rb_ivar_get(exc, id_value);
2238}
2239
2240/*
2241 * call-seq:
2242 * uncaught_throw.to_s -> string
2243 *
2244 * Returns formatted message with the inspected tag.
2245 */
2246
2247static VALUE
2248uncaught_throw_to_s(VALUE exc)
2249{
2250 VALUE mesg = rb_attr_get(exc, id_mesg);
2251 VALUE tag = uncaught_throw_tag(exc);
2252 return rb_str_format(1, &tag, mesg);
2253}
2254
2255/*
2256 * call-seq:
2257 * throw(tag [, obj])
2258 *
2259 * Transfers control to the end of the active +catch+ block
2260 * waiting for _tag_. Raises +UncaughtThrowError+ if there
2261 * is no +catch+ block for the _tag_. The optional second
2262 * parameter supplies a return value for the +catch+ block,
2263 * which otherwise defaults to +nil+. For examples, see
2264 * Kernel::catch.
2265 */
2266
2267static VALUE
2268rb_f_throw(int argc, VALUE *argv, VALUE _)
2269{
2270 VALUE tag, value;
2271
2272 rb_scan_args(argc, argv, "11", &tag, &value);
2273 rb_throw_obj(tag, value);
2275}
2276
2277void
2279{
2280 rb_execution_context_t *ec = GET_EC();
2281 struct rb_vm_tag *tt = ec->tag;
2282
2283 while (tt) {
2284 if (tt->tag == tag) {
2285 tt->retval = value;
2286 break;
2287 }
2288 tt = tt->prev;
2289 }
2290 if (!tt) {
2291 VALUE desc[3];
2292 desc[0] = tag;
2293 desc[1] = value;
2294 desc[2] = rb_str_new_cstr("uncaught throw %p");
2295 rb_exc_raise(rb_class_new_instance(numberof(desc), desc, rb_eUncaughtThrow));
2296 }
2297
2298 ec->errinfo = (VALUE)THROW_DATA_NEW(tag, NULL, TAG_THROW);
2299 EC_JUMP_TAG(ec, TAG_THROW);
2300}
2301
2302void
2303rb_throw(const char *tag, VALUE val)
2304{
2305 rb_throw_obj(rb_sym_intern_ascii_cstr(tag), val);
2306}
2307
2308static VALUE
2309catch_i(RB_BLOCK_CALL_FUNC_ARGLIST(tag, _))
2310{
2311 return rb_yield_0(1, &tag);
2312}
2313
2314/*
2315 * call-seq:
2316 * catch([tag]) {|tag| block } -> obj
2317 *
2318 * +catch+ executes its block. If +throw+ is not called, the block executes
2319 * normally, and +catch+ returns the value of the last expression evaluated.
2320 *
2321 * catch(1) { 123 } # => 123
2322 *
2323 * If <code>throw(tag2, val)</code> is called, Ruby searches up its stack for
2324 * a +catch+ block whose +tag+ has the same +object_id+ as _tag2_. When found,
2325 * the block stops executing and returns _val_ (or +nil+ if no second argument
2326 * was given to +throw+).
2327 *
2328 * catch(1) { throw(1, 456) } # => 456
2329 * catch(1) { throw(1) } # => nil
2330 *
2331 * When +tag+ is passed as the first argument, +catch+ yields it as the
2332 * parameter of the block.
2333 *
2334 * catch(1) {|x| x + 2 } # => 3
2335 *
2336 * When no +tag+ is given, +catch+ yields a new unique object (as from
2337 * +Object.new+) as the block parameter. This object can then be used as the
2338 * argument to +throw+, and will match the correct +catch+ block.
2339 *
2340 * catch do |obj_A|
2341 * catch do |obj_B|
2342 * throw(obj_B, 123)
2343 * puts "This puts is not reached"
2344 * end
2345 *
2346 * puts "This puts is displayed"
2347 * 456
2348 * end
2349 *
2350 * # => 456
2351 *
2352 * catch do |obj_A|
2353 * catch do |obj_B|
2354 * throw(obj_A, 123)
2355 * puts "This puts is still not reached"
2356 * end
2357 *
2358 * puts "Now this puts is also not reached"
2359 * 456
2360 * end
2361 *
2362 * # => 123
2363 */
2364
2365static VALUE
2366rb_f_catch(int argc, VALUE *argv, VALUE self)
2367{
2368 VALUE tag = rb_check_arity(argc, 0, 1) ? argv[0] : rb_obj_alloc(rb_cObject);
2369 return rb_catch_obj(tag, catch_i, 0);
2370}
2371
2372VALUE
2373rb_catch(const char *tag, rb_block_call_func_t func, VALUE data)
2374{
2375 VALUE vtag = tag ? rb_sym_intern_ascii_cstr(tag) : rb_obj_alloc(rb_cObject);
2376 return rb_catch_obj(vtag, func, data);
2377}
2378
2379static VALUE
2380vm_catch_protect(VALUE tag, rb_block_call_func *func, VALUE data,
2381 enum ruby_tag_type *stateptr, rb_execution_context_t *volatile ec)
2382{
2383 enum ruby_tag_type state;
2384 VALUE val = Qnil; /* OK */
2385 rb_control_frame_t *volatile saved_cfp = ec->cfp;
2386
2387 EC_PUSH_TAG(ec);
2388
2389 _tag.tag = tag;
2390
2391 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
2392 /* call with argc=1, argv = [tag], block = Qnil to insure compatibility */
2393 val = (*func)(tag, data, 1, (const VALUE *)&tag, Qnil);
2394 }
2395 else if (state == TAG_THROW && THROW_DATA_VAL((struct vm_throw_data *)ec->errinfo) == tag) {
2396 rb_vm_rewind_cfp(ec, saved_cfp);
2397 val = ec->tag->retval;
2398 ec->errinfo = Qnil;
2399 state = 0;
2400 }
2401 EC_POP_TAG();
2402 if (stateptr)
2403 *stateptr = state;
2404
2405 return val;
2406}
2407
2408VALUE
2409rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, enum ruby_tag_type *stateptr)
2410{
2411 return vm_catch_protect(t, func, data, stateptr, GET_EC());
2412}
2413
2414VALUE
2416{
2417 enum ruby_tag_type state;
2418 rb_execution_context_t *ec = GET_EC();
2419 VALUE val = vm_catch_protect(t, (rb_block_call_func *)func, data, &state, ec);
2420 if (state) EC_JUMP_TAG(ec, state);
2421 return val;
2422}
2423
2424static void
2425local_var_list_init(struct local_var_list *vars)
2426{
2427 vars->tbl = rb_ident_hash_new();
2428 RBASIC_CLEAR_CLASS(vars->tbl);
2429}
2430
2431static VALUE
2432local_var_list_finish(struct local_var_list *vars)
2433{
2434 /* TODO: not to depend on the order of st_table */
2435 VALUE ary = rb_hash_keys(vars->tbl);
2436 rb_hash_clear(vars->tbl);
2437 vars->tbl = 0;
2438 return ary;
2439}
2440
2441static int
2442local_var_list_update(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
2443{
2444 if (existing) return ST_STOP;
2445 *value = (st_data_t)Qtrue; /* INT2FIX(arg) */
2446 return ST_CONTINUE;
2447}
2448
2449static void
2450local_var_list_add(const struct local_var_list *vars, ID lid)
2451{
2452 if (lid && rb_is_local_id(lid)) {
2453 /* should skip temporary variable */
2454 st_data_t idx = 0; /* tbl->num_entries */
2455 rb_hash_stlike_update(vars->tbl, ID2SYM(lid), local_var_list_update, idx);
2456 }
2457}
2458
2459/*
2460 * call-seq:
2461 * local_variables -> array
2462 *
2463 * Returns the names of the current local variables.
2464 *
2465 * fred = 1
2466 * for i in 1..10
2467 * # ...
2468 * end
2469 * local_variables #=> [:fred, :i]
2470 */
2471
2472static VALUE
2473rb_f_local_variables(VALUE _)
2474{
2475 struct local_var_list vars;
2476 rb_execution_context_t *ec = GET_EC();
2477 rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp));
2478 unsigned int i;
2479
2480 local_var_list_init(&vars);
2481 while (cfp) {
2482 if (cfp->iseq) {
2483 for (i = 0; i < ISEQ_BODY(cfp->iseq)->local_table_size; i++) {
2484 local_var_list_add(&vars, ISEQ_BODY(cfp->iseq)->local_table[i]);
2485 }
2486 }
2487 if (!VM_ENV_LOCAL_P(cfp->ep)) {
2488 /* block */
2489 const VALUE *ep = VM_CF_PREV_EP(cfp);
2490
2491 if (vm_collect_local_variables_in_heap(ep, &vars)) {
2492 break;
2493 }
2494 else {
2495 while (cfp->ep != ep) {
2496 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
2497 }
2498 }
2499 }
2500 else {
2501 break;
2502 }
2503 }
2504 return local_var_list_finish(&vars);
2505}
2506
2507/*
2508 * call-seq:
2509 * block_given? -> true or false
2510 *
2511 * Returns <code>true</code> if <code>yield</code> would execute a
2512 * block in the current context. The <code>iterator?</code> form
2513 * is mildly deprecated.
2514 *
2515 * def try
2516 * if block_given?
2517 * yield
2518 * else
2519 * "no block"
2520 * end
2521 * end
2522 * try #=> "no block"
2523 * try { "hello" } #=> "hello"
2524 * try do "hello" end #=> "hello"
2525 */
2526
2527static VALUE
2528rb_f_block_given_p(VALUE _)
2529{
2530 rb_execution_context_t *ec = GET_EC();
2531 rb_control_frame_t *cfp = ec->cfp;
2532 cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
2533
2534 return RBOOL(cfp != NULL && VM_CF_BLOCK_HANDLER(cfp) != VM_BLOCK_HANDLER_NONE);
2535}
2536
2537/*
2538 * call-seq:
2539 * iterator? -> true or false
2540 *
2541 * Deprecated. Use block_given? instead.
2542 */
2543
2544static VALUE
2545rb_f_iterator_p(VALUE self)
2546{
2547 rb_warn_deprecated("iterator?", "block_given?");
2548 return rb_f_block_given_p(self);
2549}
2550
2551VALUE
2552rb_current_realfilepath(void)
2553{
2554 const rb_execution_context_t *ec = GET_EC();
2555 rb_control_frame_t *cfp = ec->cfp;
2556 cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
2557 if (cfp != NULL) {
2558 VALUE path = rb_iseq_realpath(cfp->iseq);
2559 if (RTEST(path)) return path;
2560 // eval context
2561 path = rb_iseq_path(cfp->iseq);
2562 if (path == eval_default_path) {
2563 return Qnil;
2564 }
2565 else {
2566 return path;
2567 }
2568 }
2569 return Qnil;
2570}
2571
2572void
2573Init_vm_eval(void)
2574{
2575 rb_define_global_function("eval", rb_f_eval, -1);
2576 rb_define_global_function("local_variables", rb_f_local_variables, 0);
2577 rb_define_global_function("iterator?", rb_f_iterator_p, 0);
2578 rb_define_global_function("block_given?", rb_f_block_given_p, 0);
2579
2580 rb_define_global_function("catch", rb_f_catch, -1);
2581 rb_define_global_function("throw", rb_f_throw, -1);
2582
2583 rb_define_global_function("loop", rb_f_loop, 0);
2584
2585 rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval_internal, -1);
2586 rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec_internal, -1);
2587 rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
2588
2589#if 1
2590 rb_add_method(rb_cBasicObject, id__send__,
2591 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, METHOD_VISI_PUBLIC);
2592 rb_add_method(rb_mKernel, idSend,
2593 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, METHOD_VISI_PUBLIC);
2594#else
2595 rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
2596 rb_define_method(rb_mKernel, "send", rb_f_send, -1);
2597#endif
2598 rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
2599
2600 rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec_internal, -1);
2601 rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec_internal, -1);
2602 rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval_internal, -1);
2603 rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval_internal, -1);
2604
2605 rb_eUncaughtThrow = rb_define_class("UncaughtThrowError", rb_eArgError);
2606 rb_define_method(rb_eUncaughtThrow, "initialize", uncaught_throw_init, -1);
2607 rb_define_method(rb_eUncaughtThrow, "tag", uncaught_throw_tag, 0);
2608 rb_define_method(rb_eUncaughtThrow, "value", uncaught_throw_value, 0);
2609 rb_define_method(rb_eUncaughtThrow, "to_s", uncaught_throw_to_s, 0);
2610
2611 id_result = rb_intern_const("result");
2612 id_tag = rb_intern_const("tag");
2613 id_value = rb_intern_const("value");
2614}
2615
2616#endif /* #ifndef MJIT_HEADER */
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition: cxxanyargs.hpp:670
#define rb_define_private_method(klass, mid, func, arity)
Defines klass#mid and makes it private.
Definition: cxxanyargs.hpp:677
#define rb_define_global_function(mid, func, arity)
Defines rb_mKernel #mid.
Definition: cxxanyargs.hpp:695
#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:888
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
Definition: eval.c:1689
VALUE rb_module_new(void)
Creates a new, anonymous module.
Definition: class.c:979
int rb_keyword_given_p(void)
Determines if the current method is given a keyword argument.
Definition: eval.c:877
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:864
#define rb_str_new2
Old name of rb_str_new_cstr.
Definition: string.h:1675
#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 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:29
#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:3148
VALUE rb_rescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2,...)
An equivalent of rescue clause.
Definition: eval.c:893
VALUE rb_eNotImpError
NotImplementedError exception.
Definition: error.c:1101
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:684
void rb_bug(const char *fmt,...)
Interpreter panic switch.
Definition: error.c:794
VALUE rb_eNameError
NameError exception.
Definition: error.c:1096
VALUE rb_eNoMethodError
NoMethodError exception.
Definition: error.c:1099
VALUE rb_eRuntimeError
RuntimeError exception.
Definition: error.c:1089
VALUE rb_eStopIteration
StopIteration exception.
Definition: enumerator.c:173
VALUE rb_eArgError
ArgumentError exception.
Definition: error.c:1092
VALUE rb_mKernel
Kernel module.
Definition: object.c:51
VALUE rb_cObject
Documented in include/ruby/internal/globals.h.
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
Definition: object.c:1939
VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
Allocates, then initialises an instance of the given class.
Definition: object.c:1980
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition: object.c:84
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition: object.c:190
VALUE rb_cBasicObject
BasicObject class.
Definition: object.c:50
VALUE rb_cModule
Module class.
Definition: object.c:53
VALUE rb_obj_clone(VALUE obj)
Produces a shallow copy of the given object.
Definition: object.c:441
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:787
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:1882
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:1166
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:1070
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:1180
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:1861
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
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:1154
VALUE rb_current_receiver(void)
This resembles ruby's self.
Definition: vm_eval.c:345
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:1173
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:1190
VALUE rb_eval_string(const char *str)
Evaluates the given string.
Definition: vm_eval.c:1849
VALUE rb_call_super(int argc, const VALUE *argv)
This resembles ruby's super.
Definition: vm_eval.c:339
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:1160
#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
int rb_is_local_id(ID id)
Classifies the given ID, then sees if it is a local variable.
Definition: symbol.c:1060
VALUE rb_proc_lambda_p(VALUE recv)
Queries if the given object is a lambda.
Definition: proc.c:293
#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
VALUE rb_str_intern(VALUE str)
Identical to rb_to_symbol(), except it assumes the receiver being an instance of RString.
Definition: symbol.c:844
VALUE rb_attr_get(VALUE obj, ID name)
Identical to rb_ivar_get()
Definition: variable.c:1223
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:1593
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:1215
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:665
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:659
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:2152
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:2186
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:2113
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:1914
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:1078
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:2083
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
Definition: symbol.c:1084
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_each(VALUE obj)
This is a shorthand of calling obj.each.
Definition: vm_eval.c:1658
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:1404
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:2303
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:1392
VALUE rb_yield(VALUE val)
Yields the block.
Definition: vm_eval.c:1358
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:1398
rb_block_call_func * rb_block_call_func_t
Shorthand type that represents an iterator-written-in-C function pointer.
Definition: iterator.h:88
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:2278
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_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:1603
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:1417
#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 rb_catch_obj(VALUE q, type *w, VALUE e)
An equivalent of Kernel#catch.
Definition: cxxanyargs.hpp:358
VALUE rb_catch(const char *q, type *w, VALUE e)
An equivalent of Kernel#catch.
Definition: cxxanyargs.hpp:331
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
VALUE rb_iterate(onearg_type *q, VALUE w, type *e, VALUE r)
Old way to implement iterators.
Definition: cxxanyargs.hpp:205
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
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
Definition: rarray.h:69
#define RBASIC(obj)
Convenient casting macro.
Definition: rbasic.h:40
#define RCLASS_SUPER
Just another name of rb_class_get_superclass.
Definition: rclass.h:44
#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
Definition: method.h:62
CREF (Class REFerence)
Definition: method.h:44
IFUNC (Internal FUNCtion)
Definition: imemo.h:84
THROW_DATA.
Definition: imemo.h:62
uintptr_t VALUE
Type that represents a Ruby object.
Definition: value.h:40
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition: value.h:52
ruby_value_type
C-level type of an object.
Definition: value_type.h:112