Ruby: eval.c Source File

Ruby 4.0.5p0 (2026-05-20 revision 64336ffd0ee9e1f4c05891695a3d7b49cb709721)

eval.c
1/**********************************************************************
2
3 eval.c -
4
5 $Author$
6 created at: Thu Jun 10 14:22:17 JST 1993
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 "ruby/internal/config.h"
15
16#ifdef HAVE_SYS_PRCTL_H
17#include <sys/prctl.h>
18#endif
19
20#include "eval_intern.h"
21#include "internal.h"
22#include "internal/class.h"
23#include "internal/cont.h"
24#include "internal/error.h"
25#include "internal/eval.h"
26#include "internal/gc.h"
27#include "internal/hash.h"
28#include "internal/inits.h"
29#include "internal/io.h"
30#include "internal/object.h"
31#include "internal/thread.h"
32#include "internal/variable.h"
33#include "ruby/fiber/scheduler.h"
34#include "iseq.h"
35#include "probes.h"
36#include "probes_helper.h"
37#include "ruby/vm.h"
38#include "vm_core.h"
39#include "ractor_core.h"
40
41NORETURN(static void rb_raise_jump(VALUE, VALUE));
42void rb_ec_clear_current_thread_trace_func(const rb_execution_context_t *ec);
43void rb_ec_clear_all_trace_func(const rb_execution_context_t *ec);
44
45static int rb_ec_cleanup(rb_execution_context_t *ec, enum ruby_tag_type ex);
46static int rb_ec_exec_node(rb_execution_context_t *ec, void *n);
47
48 VALUE rb_eLocalJumpError;
49 VALUE rb_eSysStackError;
50
51 ID ruby_static_id_signo, ruby_static_id_status;
52extern ID ruby_static_id_cause;
53#define id_cause ruby_static_id_cause
54
55#define exception_error GET_VM()->special_exceptions[ruby_error_reenter]
56
57#include "eval_error.c"
58#include "eval_jump.c"
59
60#define CLASS_OR_MODULE_P(obj) \
61 (!SPECIAL_CONST_P(obj) && \
62 (BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE))
63
64int
65ruby_setup(void)
66{
67 enum ruby_tag_type state;
68
69 if (GET_VM())
70 return 0;
71
72 /*
73 * Disable THP early before mallocs happen because we want this to
74 * affect as many future pages as possible for CoW-friendliness
75 */
76#if defined(__linux__) && defined(PR_SET_THP_DISABLE)
77 prctl(PR_SET_THP_DISABLE, 1, 0, 0, 0);
78#endif
79 Init_BareVM();
80 rb_vm_encoded_insn_data_table_init();
81 Init_enable_box();
82 Init_vm_objects();
83 Init_root_box();
84 Init_fstring_table();
85
86 EC_PUSH_TAG(GET_EC());
87 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
88 rb_call_inits();
89 ruby_prog_init();
90 GET_VM()->running = 1;
91 }
92 EC_POP_TAG();
93
94 return state;
95}
96
97void
98ruby_init(void)
99{
100 int state = ruby_setup();
101 if (state) {
102 if (RTEST(ruby_debug)) {
103 rb_execution_context_t *ec = GET_EC();
104 rb_ec_error_print(ec, ec->errinfo);
105 }
106 exit(EXIT_FAILURE);
107 }
108}
109
110void *
111ruby_options(int argc, char **argv)
112{
113 rb_execution_context_t *ec = GET_EC();
114 enum ruby_tag_type state;
115 void *volatile iseq = 0;
116
117 EC_PUSH_TAG(ec);
118 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
119 iseq = ruby_process_options(argc, argv);
120 }
121 else {
122 rb_ec_clear_current_thread_trace_func(ec);
123 int exitcode = error_handle(ec, ec->errinfo, state);
124 ec->errinfo = Qnil; /* just been handled */
125 iseq = (void *)INT2FIX(exitcode);
126 }
127 EC_POP_TAG();
128 return iseq;
129}
130
131static void
132rb_ec_fiber_scheduler_finalize(rb_execution_context_t *ec)
133{
134 enum ruby_tag_type state;
135
136 EC_PUSH_TAG(ec);
137 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
138 rb_fiber_scheduler_set(Qnil);
139 }
140 else {
141 state = error_handle(ec, ec->errinfo, state);
142 }
143 EC_POP_TAG();
144}
145
146static void
147rb_ec_teardown(rb_execution_context_t *ec)
148{
149 // If the user code defined a scheduler for the top level thread, run it:
150 rb_ec_fiber_scheduler_finalize(ec);
151
152 EC_PUSH_TAG(ec);
153 if (EC_EXEC_TAG() == TAG_NONE) {
154 rb_vm_trap_exit(rb_ec_vm_ptr(ec));
155 }
156 EC_POP_TAG();
157 rb_ec_exec_end_proc(ec);
158 rb_ec_clear_all_trace_func(ec);
159}
160
161static void
162rb_ec_finalize(rb_execution_context_t *ec)
163{
164 ruby_sig_finalize();
165 ec->errinfo = Qnil;
166 rb_objspace_call_finalizer();
167}
168
169void
170ruby_finalize(void)
171{
172 rb_execution_context_t *ec = GET_EC();
173 rb_ec_teardown(ec);
174 rb_ec_finalize(ec);
175}
176
177int
178ruby_cleanup(int ex)
179{
180 return rb_ec_cleanup(GET_EC(), (enum ruby_tag_type)ex);
181}
182
183static int
184rb_ec_cleanup(rb_execution_context_t *ec, enum ruby_tag_type ex)
185{
186 int state;
187 volatile VALUE save_error = Qundef;
188 volatile int sysex = EXIT_SUCCESS;
189 volatile int signaled = 0;
190 rb_thread_t *th = rb_ec_thread_ptr(ec);
191 rb_thread_t *const volatile th0 = th;
192 volatile int step = 0;
193 volatile VALUE message = Qnil;
194 VALUE buf;
195
196 rb_threadptr_interrupt(th);
197 rb_threadptr_check_signal(th);
198
199 EC_PUSH_TAG(ec);
200 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
201 RUBY_VM_CHECK_INTS(ec);
202
203 step_0: step++;
204 save_error = ec->errinfo;
205 if (THROW_DATA_P(ec->errinfo)) ec->errinfo = Qnil;
206
207 /* exits with failure but silently when an exception raised
208 * here */
209 rb_ec_teardown(ec);
210
211 step_1: step++;
212 VALUE err = ec->errinfo;
213 volatile int mode0 = 0, mode1 = 0;
214 if (err != save_error && !NIL_P(err)) {
215 mode0 = exiting_split(err, &sysex, &signaled);
216 }
217
218 /* exceptions after here will be ignored */
219
220 /* build error message including causes */
221 err = ATOMIC_VALUE_EXCHANGE(save_error, Qnil);
222
223 if (!NIL_P(err) && !THROW_DATA_P(err)) {
224 mode1 = exiting_split(err, (mode0 & EXITING_WITH_STATUS) ? NULL : &sysex, &signaled);
225 if (mode1 & EXITING_WITH_MESSAGE) {
226 buf = rb_str_new(NULL, 0);
227 rb_ec_error_print_detailed(ec, err, buf, Qundef);
228 message = buf;
229 }
230 }
231
232 step_2: step++;
233 /* protect from Thread#raise */
234 th->status = THREAD_KILLED;
235
236 rb_ractor_terminate_all();
237
238 step_3: step++;
239 if (!NIL_P(buf = message)) {
240 warn_print_str(buf);
241 }
242 else if (!NIL_OR_UNDEF_P(err = save_error) ||
243 (ex != TAG_NONE && !((mode0|mode1) & EXITING_WITH_STATUS))) {
244 sysex = error_handle(ec, err, ex);
245 }
246 }
247 else {
248 th = th0;
249 switch (step) {
250 case 0: goto step_0;
251 case 1: goto step_1;
252 case 2: goto step_2;
253 case 3: goto step_3;
254 }
255 }
256
257 rb_ec_finalize(ec);
258
259 /* unlock again if finalizer took mutexes. */
260 rb_threadptr_unlock_all_locking_mutexes(th);
261 th = th0;
262 EC_POP_TAG();
263 th = th0;
264 rb_thread_stop_timer_thread();
265 ruby_vm_destruct(th->vm);
266 // For YJIT, call this after ruby_vm_destruct() frees jit_cont for the root fiber.
267 rb_jit_cont_finish();
268
269 if (signaled) ruby_default_signal(signaled);
270
271 return sysex;
272}
273
274static int
275rb_ec_exec_node(rb_execution_context_t *ec, void *n)
276{
277 volatile int state;
278 rb_iseq_t *iseq = (rb_iseq_t *)n;
279 if (!n) return 0;
280
281 EC_PUSH_TAG(ec);
282 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
283 rb_iseq_eval_main(iseq);
284 }
285 EC_POP_TAG();
286 return state;
287}
288
289void
290ruby_stop(int ex)
291{
292 exit(ruby_cleanup(ex));
293}
294
295int
296ruby_executable_node(void *n, int *status)
297{
298 VALUE v = (VALUE)n;
299 int s;
300
301 switch (v) {
302 case Qtrue: s = EXIT_SUCCESS; break;
303 case Qfalse: s = EXIT_FAILURE; break;
304 default:
305 if (!FIXNUM_P(v)) return TRUE;
306 s = FIX2INT(v);
307 }
308 if (status) *status = s;
309 return FALSE;
310}
311
312int
313ruby_run_node(void *n)
314{
315 rb_execution_context_t *ec = GET_EC();
316 int status;
317 if (!ruby_executable_node(n, &status)) {
318 rb_ec_cleanup(ec, (NIL_P(ec->errinfo) ? TAG_NONE : TAG_RAISE));
319 return status;
320 }
321 return rb_ec_cleanup(ec, rb_ec_exec_node(ec, n));
322}
323
324int
325ruby_exec_node(void *n)
326{
327 return rb_ec_exec_node(GET_EC(), n);
328}
329
330/*
331 * call-seq:
332 * Module.nesting -> array
333 *
334 * Returns the list of +Modules+ nested at the point of call.
335 *
336 * module M1
337 * module M2
338 * $a = Module.nesting
339 * end
340 * end
341 * $a #=> [M1::M2, M1]
342 * $a[0].name #=> "M1::M2"
343 */
344
345static VALUE
346rb_mod_nesting(VALUE _)
347{
348 VALUE ary = rb_ary_new();
349 const rb_cref_t *cref = rb_vm_cref();
350
351 while (cref && CREF_NEXT(cref)) {
352 VALUE klass = CREF_CLASS(cref);
353 if (!CREF_PUSHED_BY_EVAL(cref) &&
354 !NIL_P(klass)) {
355 rb_ary_push(ary, klass);
356 }
357 cref = CREF_NEXT(cref);
358 }
359 return ary;
360}
361
362/*
363 * call-seq:
364 * Module.constants -> array
365 * Module.constants(inherited) -> array
366 *
367 * In the first form, returns an array of the names of all
368 * constants accessible from the point of call.
369 * This list includes the names of all modules and classes
370 * defined in the global scope.
371 *
372 * Module.constants.first(4)
373 * # => [:ARGF, :ARGV, :ArgumentError, :Array]
374 *
375 * Module.constants.include?(:SEEK_SET) # => false
376 *
377 * class IO
378 * Module.constants.include?(:SEEK_SET) # => true
379 * end
380 *
381 * The second form calls the instance method +constants+.
382 */
383
384static VALUE
385rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
386{
387 const rb_cref_t *cref = rb_vm_cref();
388 VALUE klass;
389 VALUE cbase = 0;
390 void *data = 0;
391
392 if (argc > 0 || mod != rb_cModule) {
393 return rb_mod_constants(argc, argv, mod);
394 }
395
396 while (cref) {
397 klass = CREF_CLASS(cref);
398 if (!CREF_PUSHED_BY_EVAL(cref) &&
399 !NIL_P(klass)) {
400 data = rb_mod_const_at(CREF_CLASS(cref), data);
401 if (!cbase) {
402 cbase = klass;
403 }
404 }
405 cref = CREF_NEXT(cref);
406 }
407
408 if (cbase) {
409 data = rb_mod_const_of(cbase, data);
410 }
411 return rb_const_list(data);
412}
413
420void
421rb_class_modify_check(VALUE klass)
422{
423 if (SPECIAL_CONST_P(klass)) {
424 Check_Type(klass, T_CLASS);
425 }
426 if (RB_TYPE_P(klass, T_MODULE)) {
427 // TODO: shouldn't this only happen in a few places?
428 rb_class_set_initialized(klass);
429 }
430 if (OBJ_FROZEN(klass)) {
431 if (RCLASS_SINGLETON_P(klass)) {
432 klass = RCLASS_ATTACHED_OBJECT(klass);
433 }
434 rb_error_frozen_object(klass);
435 }
436}
437
438NORETURN(static void rb_longjmp(rb_execution_context_t *, enum ruby_tag_type, volatile VALUE, VALUE));
439static VALUE get_errinfo(void);
440#define get_ec_errinfo(ec) rb_ec_get_errinfo(ec)
441
442static VALUE
443exc_setup_cause(VALUE exc, VALUE cause)
444{
445#if OPT_SUPPORT_JOKE
446 if (NIL_P(cause)) {
447 ID id_true_cause;
448 CONST_ID(id_true_cause, "true_cause");
449
450 cause = rb_attr_get(rb_eFatal, id_true_cause);
451 if (NIL_P(cause)) {
452 cause = rb_exc_new_cstr(rb_eFatal, "because using such Ruby");
453 rb_ivar_set(cause, id_cause, INT2FIX(42)); /* the answer */
454 OBJ_FREEZE(cause);
455 rb_ivar_set(rb_eFatal, id_true_cause, cause);
456 }
457 }
458#endif
459 if (!NIL_P(cause) && cause != exc) {
460 rb_ivar_set(exc, id_cause, cause);
461 if (!rb_ivar_defined(cause, id_cause)) {
462 rb_ivar_set(cause, id_cause, Qnil);
463 }
464 }
465 return exc;
466}
467
468static inline VALUE
469exc_setup_message(const rb_execution_context_t *ec, VALUE mesg, VALUE *cause)
470{
471 int nocause = 0;
472 int nocircular = 0;
473
474 if (NIL_P(mesg)) {
475 mesg = ec->errinfo;
476 if (INTERNAL_EXCEPTION_P(mesg)) EC_JUMP_TAG(ec, TAG_FATAL);
477 nocause = 1;
478 }
479 if (NIL_P(mesg)) {
480 mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
481 nocause = 0;
482 nocircular = 1;
483 }
484 if (UNDEF_P(*cause)) {
485 if (nocause) {
486 *cause = Qnil;
487 nocircular = 1;
488 }
489 else if (!rb_ivar_defined(mesg, id_cause)) {
490 *cause = get_ec_errinfo(ec);
491 }
492 else {
493 nocircular = 1;
494 }
495 }
496 else if (!NIL_P(*cause) && !rb_obj_is_kind_of(*cause, rb_eException)) {
497 rb_raise(rb_eTypeError, "exception object expected");
498 }
499
500 if (!nocircular && !NIL_P(*cause) && !UNDEF_P(*cause) && *cause != mesg) {
501#if 0 /* maybe critical for some cases */
502 rb_exc_check_circular_cause(*cause);
503#else
504 VALUE c = *cause;
505 while (!NIL_P(c)) {
506 if (c == mesg) {
507 rb_raise(rb_eArgError, "circular causes");
508 }
509 if (THROW_DATA_P(c)) {
510 break;
511 }
512 c = rb_attr_get(c, id_cause);
513 }
514#endif
515 }
516 return mesg;
517}
518
519static void
520setup_exception(rb_execution_context_t *ec, enum ruby_tag_type tag, volatile VALUE mesg, VALUE cause)
521{
522 VALUE e;
523 int line;
524 const char *file = rb_source_location_cstr(&line);
525 const char *const volatile file0 = file;
526
527 if ((file && !NIL_P(mesg)) || !UNDEF_P(cause)) {
528 volatile int state = 0;
529
530 EC_PUSH_TAG(ec);
531 if (EC_EXEC_TAG() == TAG_NONE && !(state = rb_ec_set_raised(ec))) {
532 VALUE bt = rb_get_backtrace(mesg);
533 if (!NIL_P(bt) || UNDEF_P(cause)) {
534 if (OBJ_FROZEN(mesg)) {
535 mesg = rb_obj_dup(mesg);
536 }
537 }
538 if (!UNDEF_P(cause) && !THROW_DATA_P(cause)) {
539 exc_setup_cause(mesg, cause);
540 }
541 if (NIL_P(bt)) {
542 VALUE at = rb_ec_backtrace_object(ec);
543 rb_ivar_set(mesg, idBt_locations, at);
544 set_backtrace(mesg, at);
545 }
546 rb_ec_reset_raised(ec);
547 }
548 EC_POP_TAG();
549 file = file0;
550 if (state) goto fatal;
551 }
552
553 if (!NIL_P(mesg)) {
554 ec->errinfo = mesg;
555 }
556
557 if (RTEST(ruby_debug) && !NIL_P(e = ec->errinfo) &&
558 !rb_obj_is_kind_of(e, rb_eSystemExit)) {
559 enum ruby_tag_type state;
560
561 mesg = e;
562 EC_PUSH_TAG(ec);
563 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
564 ec->errinfo = Qnil;
565 e = rb_obj_as_string(mesg);
566 ec->errinfo = mesg;
567 if (file && line) {
568 e = rb_sprintf("Exception '%"PRIsVALUE"' at %s:%d - %"PRIsVALUE"\n",
569 rb_obj_class(mesg), file, line, e);
570 }
571 else if (file) {
572 e = rb_sprintf("Exception '%"PRIsVALUE"' at %s - %"PRIsVALUE"\n",
573 rb_obj_class(mesg), file, e);
574 }
575 else {
576 e = rb_sprintf("Exception '%"PRIsVALUE"' - %"PRIsVALUE"\n",
577 rb_obj_class(mesg), e);
578 }
579 warn_print_str(e);
580 }
581 EC_POP_TAG();
582 if (state == TAG_FATAL && ec->errinfo == exception_error) {
583 ec->errinfo = mesg;
584 }
585 else if (state) {
586 rb_ec_reset_raised(ec);
587 EC_JUMP_TAG(ec, state);
588 }
589 }
590
591 if (rb_ec_set_raised(ec)) {
592 goto fatal;
593 }
594
595 if (tag != TAG_FATAL) {
596 RUBY_DTRACE_HOOK(RAISE, rb_obj_classname(ec->errinfo));
597 EXEC_EVENT_HOOK(ec, RUBY_EVENT_RAISE, ec->cfp->self, 0, 0, 0, mesg);
598 }
599 return;
600
601 fatal:
602 ec->errinfo = exception_error;
603 rb_ec_reset_raised(ec);
604 EC_JUMP_TAG(ec, TAG_FATAL);
605}
606
608void
609rb_ec_setup_exception(const rb_execution_context_t *ec, VALUE mesg, VALUE cause)
610{
611 if (UNDEF_P(cause)) {
612 cause = get_ec_errinfo(ec);
613 }
614 if (cause != mesg) {
615 if (THROW_DATA_P(cause)) {
616 cause = Qnil;
617 }
618
619 rb_ivar_set(mesg, id_cause, cause);
620 }
621}
622
623static void
624rb_longjmp(rb_execution_context_t *ec, enum ruby_tag_type tag, volatile VALUE mesg, VALUE cause)
625{
626 mesg = exc_setup_message(ec, mesg, &cause);
627 setup_exception(ec, tag, mesg, cause);
628 rb_ec_raised_clear(ec);
629 EC_JUMP_TAG(ec, tag);
630}
631
632static VALUE make_exception(int argc, const VALUE *argv, int isstr);
633
634NORETURN(static void rb_exc_exception(VALUE mesg, enum ruby_tag_type tag, VALUE cause));
635
636static void
637rb_exc_exception(VALUE mesg, enum ruby_tag_type tag, VALUE cause)
638{
639 if (!NIL_P(mesg)) {
640 mesg = make_exception(1, &mesg, FALSE);
641 }
642 rb_longjmp(GET_EC(), tag, mesg, cause);
643}
644
652void
653rb_exc_raise(VALUE mesg)
654{
655 rb_exc_exception(mesg, TAG_RAISE, Qundef);
656}
657
665void
666rb_exc_fatal(VALUE mesg)
667{
668 rb_exc_exception(mesg, TAG_FATAL, Qnil);
669}
670
671void
672rb_interrupt(void)
673{
674 rb_exc_raise(rb_exc_new(rb_eInterrupt, 0, 0));
675}
676
677static int
678extract_raise_options(int argc, VALUE *argv, VALUE *cause)
679{
680 // Keyword arguments:
681 static ID keywords[1] = {0};
682 if (!keywords[0]) {
683 CONST_ID(keywords[0], "cause");
684 }
685
686 if (argc > 0) {
687 VALUE options;
688 argc = rb_scan_args(argc, argv, "*:", NULL, &options);
689
690 if (!NIL_P(options)) {
691 if (!RHASH_EMPTY_P(options)) {
692 // Extract optional cause keyword argument, leaving any other options alone:
693 rb_get_kwargs(options, keywords, 0, -2, cause);
694
695 // If there were any other options, add them back to the arguments:
696 if (!RHASH_EMPTY_P(options)) argv[argc++] = options;
697 }
698 }
699 }
700
701 return argc;
702}
703
712 VALUE
713rb_exception_setup(int argc, VALUE *argv)
714{
715 rb_execution_context_t *ec = GET_EC();
716
717 // Extract cause keyword argument:
718 VALUE cause = Qundef;
719 argc = extract_raise_options(argc, argv, &cause);
720
721 // Validate cause-only case:
722 if (argc == 0 && !UNDEF_P(cause)) {
723 rb_raise(rb_eArgError, "only cause is given with no arguments");
724 }
725
726 // Create exception:
727 VALUE exception;
728 if (argc == 0) {
729 exception = rb_exc_new(rb_eRuntimeError, 0, 0);
730 }
731 else {
732 exception = rb_make_exception(argc, argv);
733 }
734
735 VALUE resolved_cause = Qnil;
736
737 // Resolve cause with validation:
738 if (UNDEF_P(cause)) {
739 // No explicit cause - use automatic cause chaining from calling context:
740 resolved_cause = rb_ec_get_errinfo(ec);
741
742 // Prevent self-referential cause (e.g. `raise $!`):
743 if (resolved_cause == exception) {
744 resolved_cause = Qnil;
745 }
746 }
747 else if (NIL_P(cause)) {
748 // Explicit nil cause - prevent chaining:
749 resolved_cause = Qnil;
750 }
751 else {
752 // Explicit cause - validate and assign:
753 if (!rb_obj_is_kind_of(cause, rb_eException)) {
754 rb_raise(rb_eTypeError, "exception object expected");
755 }
756
757 if (cause == exception) {
758 // Prevent self-referential cause (e.g. `raise error, cause: error`) - although I'm not sure this is good behaviour, it's inherited from `Kernel#raise`.
759 resolved_cause = Qnil;
760 }
761 else {
762 // Check for circular causes:
763 VALUE current_cause = cause;
764 while (!NIL_P(current_cause)) {
765 // We guarantee that the cause chain is always terminated. Then, creating an exception with an existing cause is not circular as long as exception is not an existing cause of any other exception.
766 if (current_cause == exception) {
767 rb_raise(rb_eArgError, "circular causes");
768 }
769 if (THROW_DATA_P(current_cause)) {
770 break;
771 }
772 current_cause = rb_attr_get(current_cause, id_cause);
773 }
774 resolved_cause = cause;
775 }
776 }
777
778 // Apply cause to exception object (duplicate if frozen):
779 if (!UNDEF_P(resolved_cause)) {
780 if (OBJ_FROZEN(exception)) {
781 exception = rb_obj_dup(exception);
782 }
783 rb_ivar_set(exception, id_cause, resolved_cause);
784 }
785
786 return exception;
787}
788
789 VALUE
790rb_f_raise(int argc, VALUE *argv)
791{
792 VALUE cause = Qundef;
793 argc = extract_raise_options(argc, argv, &cause);
794
795 VALUE exception;
796
797 // Bare re-raise case:
798 if (argc == 0) {
799 // Cause was extracted, but no arguments were provided:
800 if (!UNDEF_P(cause)) {
801 rb_raise(rb_eArgError, "only cause is given with no arguments");
802 }
803
804 // Otherwise, re-raise the current exception:
805 exception = get_errinfo();
806 if (!NIL_P(exception)) {
807 argc = 1;
808 argv = &exception;
809 }
810 }
811
812 rb_raise_jump(rb_make_exception(argc, argv), cause);
813
814 UNREACHABLE_RETURN(Qnil);
815}
816
817/*
818 * call-seq:
819 * raise(exception, message = exception.to_s, backtrace = nil, cause: $!)
820 * raise(message = nil, cause: $!)
821 *
822 * Raises an exception;
823 * see {Exceptions}[rdoc-ref:exceptions.md].
824 *
825 * Argument +exception+ sets the class of the new exception;
826 * it should be class Exception or one of its subclasses
827 * (most commonly, RuntimeError or StandardError),
828 * or an instance of one of those classes:
829 *
830 * begin
831 * raise(StandardError)
832 * rescue => x
833 * p x.class
834 * end
835 * # => StandardError
836 *
837 * Argument +message+ sets the stored message in the new exception,
838 * which may be retrieved by method Exception#message;
839 * the message must be
840 * a {string-convertible object}[rdoc-ref:implicit_conversion.rdoc@String-Convertible+Objects]
841 * or +nil+:
842 *
843 * begin
844 * raise(StandardError, 'Boom')
845 * rescue => x
846 * p x.message
847 * end
848 * # => "Boom"
849 *
850 * If argument +message+ is not given,
851 * the message is the exception class name.
852 *
853 * See {Messages}[rdoc-ref:exceptions.md@Messages].
854 *
855 * Argument +backtrace+ might be used to modify the backtrace of the new exception,
856 * as reported by Exception#backtrace and Exception#backtrace_locations;
857 * the backtrace must be an array of Thread::Backtrace::Location, an array of
858 * strings, a single string, or +nil+.
859 *
860 * Using the array of Thread::Backtrace::Location instances is the most consistent option
861 * and should be preferred when possible. The necessary value might be obtained
862 * from #caller_locations, or copied from Exception#backtrace_locations of another
863 * error:
864 *
865 * begin
866 * do_some_work()
867 * rescue ZeroDivisionError => ex
868 * raise(LogicalError, "You have an error in your math", ex.backtrace_locations)
869 * end
870 *
871 * The ways, both Exception#backtrace and Exception#backtrace_locations of the
872 * raised error are set to the same backtrace.
873 *
874 * When the desired stack of locations is not available and should
875 * be constructed from scratch, an array of strings or a singular
876 * string can be used. In this case, only Exception#backtrace is set:
877 *
878 * begin
879 * raise(StandardError, 'Boom', %w[dsl.rb:3 framework.rb:1])
880 * rescue => ex
881 * p ex.backtrace
882 * # => ["dsl.rb:3", "framework.rb:1"]
883 * p ex.backtrace_locations
884 * # => nil
885 * end
886 *
887 * If argument +backtrace+ is not given,
888 * the backtrace is set according to an array of Thread::Backtrace::Location objects,
889 * as derived from the call stack.
890 *
891 * See {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
892 *
893 * Keyword argument +cause+ sets the stored cause in the new exception,
894 * which may be retrieved by method Exception#cause;
895 * the cause must be an exception object (Exception or one of its subclasses),
896 * or +nil+:
897 *
898 * begin
899 * raise(StandardError, cause: RuntimeError.new)
900 * rescue => x
901 * p x.cause
902 * end
903 * # => #<RuntimeError: RuntimeError>
904 *
905 * If keyword argument +cause+ is not given,
906 * the cause is the value of <tt>$!</tt>.
907 *
908 * See {Cause}[rdoc-ref:exceptions.md@Cause].
909 *
910 * In the alternate calling sequence,
911 * where argument +exception+ _not_ given,
912 * raises a new exception of the class given by <tt>$!</tt>,
913 * or of class RuntimeError if <tt>$!</tt> is +nil+:
914 *
915 * begin
916 * raise
917 * rescue => x
918 * p x
919 * end
920 * # => RuntimeError
921 *
922 * With argument +exception+ not given,
923 * argument +message+ and keyword argument +cause+ may be given,
924 * but argument +backtrace+ may not be given.
925 *
926 * +cause+ can not be given as an only argument.
927 *
928 */
929
930static VALUE
931f_raise(int c, VALUE *v, VALUE _)
932{
933 return rb_f_raise(c, v);
934}
935
936static VALUE
937make_exception(int argc, const VALUE *argv, int isstr)
938{
939 VALUE mesg, exc;
940
941 mesg = Qnil;
942 switch (argc) {
943 case 0:
944 return Qnil;
945 case 1:
946 exc = argv[0];
947 if (isstr &&! NIL_P(exc)) {
948 mesg = rb_check_string_type(exc);
949 if (!NIL_P(mesg)) {
950 return rb_exc_new3(rb_eRuntimeError, mesg);
951 }
952 }
953
954 case 2:
955 case 3:
956 break;
957 default:
958 rb_error_arity(argc, 0, 3);
959 }
960 if (NIL_P(mesg)) {
961 mesg = rb_check_funcall(argv[0], idException, argc != 1, &argv[1]);
962 }
963 if (UNDEF_P(mesg)) {
964 rb_raise(rb_eTypeError, "exception class/object expected");
965 }
966 if (!rb_obj_is_kind_of(mesg, rb_eException)) {
967 rb_raise(rb_eTypeError, "exception object expected");
968 }
969 if (argc == 3) {
970 set_backtrace(mesg, argv[2]);
971 }
972
973 return mesg;
974}
975
976 VALUE
977rb_make_exception(int argc, const VALUE *argv)
978{
979 return make_exception(argc, argv, TRUE);
980}
981
984static void
985rb_raise_jump(VALUE mesg, VALUE cause)
986{
987 rb_execution_context_t *ec = GET_EC();
988 const rb_control_frame_t *cfp = ec->cfp;
989 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
990 VALUE klass = me->owner;
991 VALUE self = cfp->self;
992 ID mid = me->called_id;
993
994 rb_vm_pop_frame(ec);
995 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, self, me->def->original_id, mid, klass, Qnil);
996
997 rb_longjmp(ec, TAG_RAISE, mesg, cause);
998}
999
1000void
1001rb_jump_tag(int tag)
1002{
1003 if (UNLIKELY(tag < TAG_RETURN || tag > TAG_FATAL)) {
1004 unknown_longjmp_status(tag);
1005 }
1006 EC_JUMP_TAG(GET_EC(), tag);
1007}
1008
1009int
1010rb_block_given_p(void)
1011{
1012 if (rb_vm_frame_block_handler(GET_EC()->cfp) == VM_BLOCK_HANDLER_NONE) {
1013 return FALSE;
1014 }
1015 else {
1016 return TRUE;
1017 }
1018}
1019
1020int rb_vm_cframe_keyword_p(const rb_control_frame_t *cfp);
1021
1022int
1023rb_keyword_given_p(void)
1024{
1025 return rb_vm_cframe_keyword_p(GET_EC()->cfp);
1026}
1027
1028 VALUE rb_eThreadError;
1029
1030void
1031rb_need_block(void)
1032{
1033 if (!rb_block_given_p()) {
1034 rb_vm_localjump_error("no block given", Qnil, 0);
1035 }
1036}
1037
1038 VALUE
1039rb_rescue2(VALUE (* b_proc) (VALUE), VALUE data1,
1040 VALUE (* r_proc) (VALUE, VALUE), VALUE data2, ...)
1041{
1042 va_list ap;
1043 va_start(ap, data2);
1044 VALUE ret = rb_vrescue2(b_proc, data1, r_proc, data2, ap);
1045 va_end(ap);
1046 return ret;
1047}
1048
1049 VALUE
1050rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1,
1051 VALUE (* r_proc) (VALUE, VALUE), VALUE data2,
1052 va_list args)
1053{
1054 enum ruby_tag_type state;
1055 rb_execution_context_t * volatile ec = GET_EC();
1056 rb_control_frame_t *volatile cfp = ec->cfp;
1057 volatile VALUE result = Qfalse;
1058 volatile VALUE e_info = ec->errinfo;
1059
1060 EC_PUSH_TAG(ec);
1061 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1062 retry_entry:
1063 result = (*b_proc) (data1);
1064 }
1065 else if (result) {
1066 /* escape from r_proc */
1067 if (state == TAG_RETRY) {
1068 state = TAG_NONE;
1069 ec->errinfo = Qnil;
1070 result = Qfalse;
1071 goto retry_entry;
1072 }
1073 }
1074 else {
1075 rb_vm_rewind_cfp(ec, cfp);
1076
1077 if (state == TAG_RAISE) {
1078 int handle = FALSE;
1079 VALUE eclass;
1080 va_list ap;
1081
1082 result = Qnil;
1083 /* reuses args when raised again after retrying in r_proc */
1084 va_copy(ap, args);
1085 while ((eclass = va_arg(ap, VALUE)) != 0) {
1086 if (rb_obj_is_kind_of(ec->errinfo, eclass)) {
1087 handle = TRUE;
1088 break;
1089 }
1090 }
1091 va_end(ap);
1092
1093 if (handle) {
1094 state = TAG_NONE;
1095 if (r_proc) {
1096 result = (*r_proc) (data2, ec->errinfo);
1097 }
1098 ec->errinfo = e_info;
1099 }
1100 }
1101 }
1102 EC_POP_TAG();
1103 if (state)
1104 EC_JUMP_TAG(ec, state);
1105
1106 return result;
1107}
1108
1109 VALUE
1110rb_rescue(VALUE (* b_proc)(VALUE), VALUE data1,
1111 VALUE (* r_proc)(VALUE, VALUE), VALUE data2)
1112{
1113 return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError,
1114 (VALUE)0);
1115}
1116
1117 VALUE
1118rb_protect(VALUE (* proc) (VALUE), VALUE data, int *pstate)
1119{
1120 volatile VALUE result = Qnil;
1121 volatile enum ruby_tag_type state;
1122 rb_execution_context_t * volatile ec = GET_EC();
1123 rb_control_frame_t *volatile cfp = ec->cfp;
1124
1125 EC_PUSH_TAG(ec);
1126 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1127 result = (*proc)(data);
1128 }
1129 else {
1130 rb_vm_rewind_cfp(ec, cfp);
1131 }
1132 EC_POP_TAG();
1133
1134 if (pstate != NULL) *pstate = state;
1135 return result;
1136}
1137
1138 VALUE
1139rb_ec_ensure(rb_execution_context_t *ec, VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2)
1140{
1141 enum ruby_tag_type state;
1142 volatile VALUE result = Qnil;
1143 VALUE errinfo;
1144 EC_PUSH_TAG(ec);
1145 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1146 result = (*b_proc) (data1);
1147 }
1148 EC_POP_TAG();
1149 errinfo = ec->errinfo;
1150 if (!NIL_P(errinfo) && !RB_TYPE_P(errinfo, T_OBJECT)) {
1151 ec->errinfo = Qnil;
1152 }
1153 (*e_proc)(data2);
1154 ec->errinfo = errinfo;
1155 if (state)
1156 EC_JUMP_TAG(ec, state);
1157 return result;
1158}
1159
1160 VALUE
1161rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2)
1162{
1163 return rb_ec_ensure(GET_EC(), b_proc, data1, e_proc, data2);
1164}
1165
1166static ID
1167frame_func_id(const rb_control_frame_t *cfp)
1168{
1169 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
1170
1171 if (me) {
1172 return me->def->original_id;
1173 }
1174 else {
1175 return 0;
1176 }
1177}
1178
1179static ID
1180frame_called_id(rb_control_frame_t *cfp)
1181{
1182 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
1183
1184 if (me) {
1185 return me->called_id;
1186 }
1187 else {
1188 return 0;
1189 }
1190}
1191
1192 ID
1193rb_frame_this_func(void)
1194{
1195 return frame_func_id(GET_EC()->cfp);
1196}
1197
1198 ID
1199rb_frame_callee(void)
1200{
1201 return frame_called_id(GET_EC()->cfp);
1202}
1203
1204static rb_control_frame_t *
1205previous_frame(const rb_execution_context_t *ec)
1206{
1207 rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp);
1208 /* check if prev_cfp can be accessible */
1209 if ((void *)(ec->vm_stack + ec->vm_stack_size) == (void *)(prev_cfp)) {
1210 return 0;
1211 }
1212 return prev_cfp;
1213}
1214
1215static ID
1216prev_frame_callee(void)
1217{
1218 rb_control_frame_t *prev_cfp = previous_frame(GET_EC());
1219 if (!prev_cfp) return 0;
1220 return frame_called_id(prev_cfp);
1221}
1222
1223static ID
1224prev_frame_func(void)
1225{
1226 rb_control_frame_t *prev_cfp = previous_frame(GET_EC());
1227 if (!prev_cfp) return 0;
1228 return frame_func_id(prev_cfp);
1229}
1230
1237 ID
1238rb_frame_last_func(void)
1239{
1240 const rb_execution_context_t *ec = GET_EC();
1241 const rb_control_frame_t *cfp = ec->cfp;
1242 ID mid;
1243
1244 while (!(mid = frame_func_id(cfp)) &&
1245 (cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp),
1246 !RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)));
1247 return mid;
1248}
1249
1250/*
1251 * call-seq:
1252 * append_features(mod) -> mod
1253 *
1254 * When this module is included in another, Ruby calls
1255 * #append_features in this module, passing it the receiving module
1256 * in _mod_. Ruby's default implementation is to add the constants,
1257 * methods, and module variables of this module to _mod_ if this
1258 * module has not already been added to _mod_ or one of its
1259 * ancestors. See also Module#include.
1260 */
1261
1262static VALUE
1263rb_mod_append_features(VALUE module, VALUE include)
1264{
1265 if (!CLASS_OR_MODULE_P(include)) {
1266 Check_Type(include, T_CLASS);
1267 }
1268 rb_include_module(include, module);
1269
1270 return module;
1271}
1272
1273static VALUE refinement_import_methods(int argc, VALUE *argv, VALUE refinement);
1274
1275/*
1276 * call-seq:
1277 * include(module, ...) -> self
1278 *
1279 * Invokes Module.append_features on each parameter in reverse order.
1280 */
1281
1282static VALUE
1283rb_mod_include(int argc, VALUE *argv, VALUE module)
1284{
1285 int i;
1286 ID id_append_features, id_included;
1287
1288 CONST_ID(id_append_features, "append_features");
1289 CONST_ID(id_included, "included");
1290
1291 if (BUILTIN_TYPE(module) == T_MODULE && FL_TEST(module, RMODULE_IS_REFINEMENT)) {
1292 rb_raise(rb_eTypeError, "Refinement#include has been removed");
1293 }
1294
1295 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
1296 for (i = 0; i < argc; i++) {
1297 Check_Type(argv[i], T_MODULE);
1298 if (FL_TEST(argv[i], RMODULE_IS_REFINEMENT)) {
1299 rb_raise(rb_eTypeError, "Cannot include refinement");
1300 }
1301 }
1302 while (argc--) {
1303 rb_funcall(argv[argc], id_append_features, 1, module);
1304 rb_funcall(argv[argc], id_included, 1, module);
1305 }
1306 return module;
1307}
1308
1309/*
1310 * call-seq:
1311 * prepend_features(mod) -> mod
1312 *
1313 * When this module is prepended in another, Ruby calls
1314 * #prepend_features in this module, passing it the receiving module
1315 * in _mod_. Ruby's default implementation is to overlay the
1316 * constants, methods, and module variables of this module to _mod_
1317 * if this module has not already been added to _mod_ or one of its
1318 * ancestors. See also Module#prepend.
1319 */
1320
1321static VALUE
1322rb_mod_prepend_features(VALUE module, VALUE prepend)
1323{
1324 if (!CLASS_OR_MODULE_P(prepend)) {
1325 Check_Type(prepend, T_CLASS);
1326 }
1327 rb_prepend_module(prepend, module);
1328
1329 return module;
1330}
1331
1332/*
1333 * call-seq:
1334 * prepend(module, ...) -> self
1335 *
1336 * Invokes Module.prepend_features on each parameter in reverse order.
1337 */
1338
1339static VALUE
1340rb_mod_prepend(int argc, VALUE *argv, VALUE module)
1341{
1342 int i;
1343 ID id_prepend_features, id_prepended;
1344
1345 if (BUILTIN_TYPE(module) == T_MODULE && FL_TEST(module, RMODULE_IS_REFINEMENT)) {
1346 rb_raise(rb_eTypeError, "Refinement#prepend has been removed");
1347 }
1348
1349 CONST_ID(id_prepend_features, "prepend_features");
1350 CONST_ID(id_prepended, "prepended");
1351
1352 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
1353 for (i = 0; i < argc; i++) {
1354 Check_Type(argv[i], T_MODULE);
1355 if (FL_TEST(argv[i], RMODULE_IS_REFINEMENT)) {
1356 rb_raise(rb_eTypeError, "Cannot prepend refinement");
1357 }
1358 }
1359 while (argc--) {
1360 rb_funcall(argv[argc], id_prepend_features, 1, module);
1361 rb_funcall(argv[argc], id_prepended, 1, module);
1362 }
1363 return module;
1364}
1365
1366static void
1367ensure_class_or_module(VALUE obj)
1368{
1369 if (!RB_TYPE_P(obj, T_CLASS) && !RB_TYPE_P(obj, T_MODULE)) {
1370 rb_raise(rb_eTypeError,
1371 "wrong argument type %"PRIsVALUE" (expected Class or Module)",
1372 rb_obj_class(obj));
1373 }
1374}
1375
1376static VALUE
1377hidden_identity_hash_new(void)
1378{
1379 VALUE hash = rb_ident_hash_new();
1380
1381 RBASIC_CLEAR_CLASS(hash); /* hide from ObjectSpace */
1382 return hash;
1383}
1384
1385static VALUE
1386refinement_superclass(VALUE superclass)
1387{
1388 if (RB_TYPE_P(superclass, T_MODULE)) {
1389 /* FIXME: Should ancestors of superclass be used here? */
1390 return rb_include_class_new(RCLASS_ORIGIN(superclass), rb_cBasicObject);
1391 }
1392 else {
1393 return superclass;
1394 }
1395}
1396
1400static void
1401rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module)
1402{
1403 VALUE iclass, c, superclass = klass;
1404
1405 ensure_class_or_module(klass);
1406 Check_Type(module, T_MODULE);
1407 if (NIL_P(CREF_REFINEMENTS(cref))) {
1408 CREF_REFINEMENTS_SET(cref, hidden_identity_hash_new());
1409 }
1410 else {
1411 if (CREF_OMOD_SHARED(cref)) {
1412 CREF_REFINEMENTS_SET(cref, rb_hash_dup(CREF_REFINEMENTS(cref)));
1413 CREF_OMOD_SHARED_UNSET(cref);
1414 }
1415 if (!NIL_P(c = rb_hash_lookup(CREF_REFINEMENTS(cref), klass))) {
1416 superclass = c;
1417 while (c && RB_TYPE_P(c, T_ICLASS)) {
1418 if (RBASIC(c)->klass == module) {
1419 /* already used refinement */
1420 return;
1421 }
1422 c = RCLASS_SUPER(c);
1423 }
1424 }
1425 }
1426 superclass = refinement_superclass(superclass);
1427 c = iclass = rb_include_class_new(module, superclass);
1428 RCLASS_SET_REFINED_CLASS(c, klass);
1429
1430 RCLASS_WRITE_M_TBL(c, RCLASS_M_TBL(module));
1431
1432 rb_class_subclass_add(klass, iclass);
1433
1434 rb_hash_aset(CREF_REFINEMENTS(cref), klass, iclass);
1435}
1436
1437static int
1438using_refinement(VALUE klass, VALUE module, VALUE arg)
1439{
1440 rb_cref_t *cref = (rb_cref_t *) arg;
1441
1442 rb_using_refinement(cref, klass, module);
1443 return ST_CONTINUE;
1444}
1445
1446static void
1447using_module_recursive(const rb_cref_t *cref, VALUE klass)
1448{
1449 ID id_refinements;
1450 VALUE super, module, refinements;
1451
1452 super = RCLASS_SUPER(klass);
1453 if (super) {
1454 using_module_recursive(cref, super);
1455 }
1456 switch (BUILTIN_TYPE(klass)) {
1457 case T_MODULE:
1458 module = klass;
1459 break;
1460
1461 case T_ICLASS:
1462 module = RBASIC(klass)->klass;
1463 break;
1464
1465 default:
1466 rb_raise(rb_eTypeError, "wrong argument type %s (expected Module)",
1467 rb_obj_classname(klass));
1468 break;
1469 }
1470 CONST_ID(id_refinements, "__refinements__");
1471 refinements = rb_attr_get(module, id_refinements);
1472 if (NIL_P(refinements)) return;
1473 rb_hash_foreach(refinements, using_refinement, (VALUE) cref);
1474}
1475
1479static void
1480rb_using_module(const rb_cref_t *cref, VALUE module)
1481{
1482 Check_Type(module, T_MODULE);
1483 using_module_recursive(cref, module);
1484 rb_clear_all_refinement_method_cache();
1485}
1486
1487void
1488rb_vm_using_module(VALUE module)
1489{
1490 rb_using_module(rb_vm_cref_replace_with_duplicated_cref(), module);
1491}
1492
1493/*
1494 * call-seq:
1495 * target -> class_or_module
1496 *
1497 * Return the class or module refined by the receiver.
1498 *
1499 * module M
1500 * refine String do
1501 * end
1502 * end
1503 *
1504 * M.refinements[0].target # => String
1505 */
1506 VALUE
1507rb_refinement_module_get_refined_class(VALUE module)
1508{
1509 ID id_refined_class;
1510
1511 CONST_ID(id_refined_class, "__refined_class__");
1512 return rb_attr_get(module, id_refined_class);
1513}
1514
1515static void
1516add_activated_refinement(VALUE activated_refinements,
1517 VALUE klass, VALUE refinement)
1518{
1519 VALUE iclass, c, superclass = klass;
1520
1521 if (!NIL_P(c = rb_hash_lookup(activated_refinements, klass))) {
1522 superclass = c;
1523 while (c && RB_TYPE_P(c, T_ICLASS)) {
1524 if (RBASIC(c)->klass == refinement) {
1525 /* already used refinement */
1526 return;
1527 }
1528 c = RCLASS_SUPER(c);
1529 }
1530 }
1531 superclass = refinement_superclass(superclass);
1532 c = iclass = rb_include_class_new(refinement, superclass);
1533 RCLASS_SET_REFINED_CLASS(c, klass);
1534 rb_class_subclass_add(klass, iclass);
1535 refinement = RCLASS_SUPER(refinement);
1536 while (refinement && refinement != klass) {
1537 c = rb_class_set_super(c, rb_include_class_new(refinement, RCLASS_SUPER(c)));
1538 RCLASS_SET_REFINED_CLASS(c, klass);
1539 rb_class_subclass_add(klass, c);
1540 refinement = RCLASS_SUPER(refinement);
1541 }
1542 rb_hash_aset(activated_refinements, klass, iclass);
1543}
1544
1545void
1546rb_refinement_setup(struct rb_refinements_data *data, VALUE module, VALUE klass)
1547{
1548 VALUE refinement;
1549 ID id_refinements, id_activated_refinements,
1550 id_refined_class, id_defined_at;
1551 VALUE refinements, activated_refinements;
1552
1553 CONST_ID(id_refinements, "__refinements__");
1554 refinements = rb_attr_get(module, id_refinements);
1555 if (NIL_P(refinements)) {
1556 refinements = hidden_identity_hash_new();
1557 rb_ivar_set(module, id_refinements, refinements);
1558 }
1559 CONST_ID(id_activated_refinements, "__activated_refinements__");
1560 activated_refinements = rb_attr_get(module, id_activated_refinements);
1561 if (NIL_P(activated_refinements)) {
1562 activated_refinements = hidden_identity_hash_new();
1563 rb_ivar_set(module, id_activated_refinements,
1564 activated_refinements);
1565 }
1566 refinement = rb_hash_lookup(refinements, klass);
1567 if (NIL_P(refinement)) {
1568 VALUE superclass = refinement_superclass(klass);
1569 refinement = rb_refinement_new();
1570 rb_class_set_super(refinement, superclass);
1571 RUBY_ASSERT(BUILTIN_TYPE(refinement) == T_MODULE);
1572 FL_SET(refinement, RMODULE_IS_REFINEMENT);
1573 CONST_ID(id_refined_class, "__refined_class__");
1574 rb_ivar_set(refinement, id_refined_class, klass);
1575 CONST_ID(id_defined_at, "__defined_at__");
1576 rb_ivar_set(refinement, id_defined_at, module);
1577 rb_hash_aset(refinements, klass, refinement);
1578 add_activated_refinement(activated_refinements, klass, refinement);
1579 }
1580
1581 data->refinement = refinement;
1582 data->refinements = activated_refinements;
1583}
1584
1585/*
1586 * call-seq:
1587 * refine(mod) { block } -> module
1588 *
1589 * Refine <i>mod</i> in the receiver.
1590 *
1591 * Returns a module, where refined methods are defined.
1592 */
1593
1594static VALUE
1595rb_mod_refine(VALUE module, VALUE klass)
1596{
1597 /* module is the receiver of #refine, klass is a module to be refined (`mod` in the doc) */
1598 rb_thread_t *th = GET_THREAD();
1599 VALUE block_handler = rb_vm_frame_block_handler(th->ec->cfp);
1600 struct rb_refinements_data data;
1601
1602 if (block_handler == VM_BLOCK_HANDLER_NONE) {
1603 rb_raise(rb_eArgError, "no block given");
1604 }
1605 if (vm_block_handler_type(block_handler) != block_handler_type_iseq) {
1606 rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine");
1607 }
1608
1609 ensure_class_or_module(klass);
1610
1611 rb_refinement_setup(&data, module, klass);
1612
1613 rb_yield_refine_block(data.refinement, data.refinements);
1614 return data.refinement;
1615}
1616
1617static void
1618ignored_block(VALUE module, const char *klass)
1619{
1620 const char *anon = "";
1621 Check_Type(module, T_MODULE);
1622 if (!RTEST(rb_search_class_path(module))) {
1623 anon = ", maybe for Module.new";
1624 }
1625 rb_warn("%s""using doesn't call the given block""%s.", klass, anon);
1626}
1627
1628/*
1629 * call-seq:
1630 * using(module) -> self
1631 *
1632 * Import class refinements from <i>module</i> into the current class or
1633 * module definition.
1634 */
1635
1636static VALUE
1637mod_using(VALUE self, VALUE module)
1638{
1639 rb_control_frame_t *prev_cfp = previous_frame(GET_EC());
1640
1641 if (prev_frame_func()) {
1642 rb_raise(rb_eRuntimeError,
1643 "Module#using is not permitted in methods");
1644 }
1645 if (prev_cfp && prev_cfp->self != self) {
1646 rb_raise(rb_eRuntimeError, "Module#using is not called on self");
1647 }
1648 if (rb_block_given_p()) {
1649 ignored_block(module, "Module#");
1650 }
1651 rb_using_module(rb_vm_cref_replace_with_duplicated_cref(), module);
1652 return self;
1653}
1654
1655
1656/*
1657 * call-seq:
1658 * refinements -> array
1659 *
1660 * Returns an array of +Refinement+ defined within the receiver.
1661 *
1662 * module A
1663 * refine Integer do
1664 * end
1665 *
1666 * refine String do
1667 * end
1668 * end
1669 *
1670 * p A.refinements
1671 *
1672 * <em>produces:</em>
1673 *
1674 * [#<refinement:Integer@A>, #<refinement:String@A>]
1675 */
1676static VALUE
1677mod_refinements(VALUE self)
1678{
1679 ID id_refinements;
1680 VALUE refinements;
1681
1682 CONST_ID(id_refinements, "__refinements__");
1683 refinements = rb_attr_get(self, id_refinements);
1684 if (NIL_P(refinements)) {
1685 return rb_ary_new();
1686 }
1687 return rb_hash_values(refinements);
1688}
1689
1690static int
1691used_modules_i(VALUE _, VALUE mod, VALUE ary)
1692{
1693 ID id_defined_at;
1694 CONST_ID(id_defined_at, "__defined_at__");
1695 while (BUILTIN_TYPE(rb_class_of(mod)) == T_MODULE && FL_TEST(rb_class_of(mod), RMODULE_IS_REFINEMENT)) {
1696 rb_ary_push(ary, rb_attr_get(rb_class_of(mod), id_defined_at));
1697 mod = RCLASS_SUPER(mod);
1698 }
1699 return ST_CONTINUE;
1700}
1701
1702/*
1703 * call-seq:
1704 * used_modules -> array
1705 *
1706 * Returns an array of all modules used in the current scope. The ordering
1707 * of modules in the resulting array is not defined.
1708 *
1709 * module A
1710 * refine Object do
1711 * end
1712 * end
1713 *
1714 * module B
1715 * refine Object do
1716 * end
1717 * end
1718 *
1719 * using A
1720 * using B
1721 * p Module.used_modules
1722 *
1723 * <em>produces:</em>
1724 *
1725 * [B, A]
1726 */
1727static VALUE
1728rb_mod_s_used_modules(VALUE _)
1729{
1730 const rb_cref_t *cref = rb_vm_cref();
1731 VALUE ary = rb_ary_new();
1732
1733 while (cref) {
1734 if (!NIL_P(CREF_REFINEMENTS(cref))) {
1735 rb_hash_foreach(CREF_REFINEMENTS(cref), used_modules_i, ary);
1736 }
1737 cref = CREF_NEXT(cref);
1738 }
1739
1740 return rb_funcall(ary, rb_intern("uniq"), 0);
1741}
1742
1743static int
1744used_refinements_i(VALUE _, VALUE mod, VALUE ary)
1745{
1746 while (BUILTIN_TYPE(rb_class_of(mod)) == T_MODULE && FL_TEST(rb_class_of(mod), RMODULE_IS_REFINEMENT)) {
1747 rb_ary_push(ary, rb_class_of(mod));
1748 mod = RCLASS_SUPER(mod);
1749 }
1750 return ST_CONTINUE;
1751}
1752
1753/*
1754 * call-seq:
1755 * used_refinements -> array
1756 *
1757 * Returns an array of all modules used in the current scope. The ordering
1758 * of modules in the resulting array is not defined.
1759 *
1760 * module A
1761 * refine Object do
1762 * end
1763 * end
1764 *
1765 * module B
1766 * refine Object do
1767 * end
1768 * end
1769 *
1770 * using A
1771 * using B
1772 * p Module.used_refinements
1773 *
1774 * <em>produces:</em>
1775 *
1776 * [#<refinement:Object@B>, #<refinement:Object@A>]
1777 */
1778static VALUE
1779rb_mod_s_used_refinements(VALUE _)
1780{
1781 const rb_cref_t *cref = rb_vm_cref();
1782 VALUE ary = rb_ary_new();
1783
1784 while (cref) {
1785 if (!NIL_P(CREF_REFINEMENTS(cref))) {
1786 rb_hash_foreach(CREF_REFINEMENTS(cref), used_refinements_i, ary);
1787 }
1788 cref = CREF_NEXT(cref);
1789 }
1790
1791 return ary;
1792}
1793
1794 struct refinement_import_methods_arg {
1795 rb_cref_t *cref;
1796 VALUE refinement;
1797 VALUE module;
1798};
1799
1800/* vm.c */
1801rb_cref_t *rb_vm_cref_dup_without_refinements(const rb_cref_t *cref);
1802
1803static enum rb_id_table_iterator_result
1804refinement_import_methods_i(ID key, VALUE value, void *data)
1805{
1806 const rb_method_entry_t *me = (const rb_method_entry_t *)value;
1807 struct refinement_import_methods_arg *arg = (struct refinement_import_methods_arg *)data;
1808
1809 if (me->def->type != VM_METHOD_TYPE_ISEQ) {
1810 rb_raise(rb_eArgError, "Can't import method which is not defined with Ruby code: %"PRIsVALUE"#%"PRIsVALUE, rb_class_path(arg->module), rb_id2str(key));
1811 }
1812 rb_cref_t *new_cref = rb_vm_cref_dup_without_refinements(me->def->body.iseq.cref);
1813 CREF_REFINEMENTS_SET(new_cref, CREF_REFINEMENTS(arg->cref));
1814 rb_add_method_iseq(arg->refinement, key, me->def->body.iseq.iseqptr, new_cref, METHOD_ENTRY_VISI(me));
1815 return ID_TABLE_CONTINUE;
1816}
1817
1818/*
1819 * Note: docs for the method are in class.c
1820 */
1821
1822static VALUE
1823refinement_import_methods(int argc, VALUE *argv, VALUE refinement)
1824{
1825 int i;
1826 struct refinement_import_methods_arg arg;
1827
1828 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
1829 for (i = 0; i < argc; i++) {
1830 Check_Type(argv[i], T_MODULE);
1831 if (RCLASS_SUPER(argv[i])) {
1832 rb_warn("%"PRIsVALUE" has ancestors, but Refinement#import_methods doesn't import their methods", rb_class_path(argv[i]));
1833 }
1834 }
1835 arg.cref = rb_vm_cref_replace_with_duplicated_cref();
1836 arg.refinement = refinement;
1837 for (i = 0; i < argc; i++) {
1838 arg.module = argv[i];
1839 struct rb_id_table *m_tbl = RCLASS_M_TBL(argv[i]);
1840 if (!m_tbl) continue;
1841 rb_id_table_foreach(m_tbl, refinement_import_methods_i, &arg);
1842 }
1843 return refinement;
1844}
1845
1846void
1847rb_obj_call_init(VALUE obj, int argc, const VALUE *argv)
1848{
1849 rb_obj_call_init_kw(obj, argc, argv, RB_NO_KEYWORDS);
1850}
1851
1852void
1853rb_obj_call_init_kw(VALUE obj, int argc, const VALUE *argv, int kw_splat)
1854{
1855 PASS_PASSED_BLOCK_HANDLER();
1856 rb_funcallv_kw(obj, idInitialize, argc, argv, kw_splat);
1857}
1858
1859void
1860rb_extend_object(VALUE obj, VALUE module)
1861{
1862 rb_include_module(rb_singleton_class(obj), module);
1863}
1864
1865/*
1866 * call-seq:
1867 * extend_object(obj) -> obj
1868 *
1869 * Extends the specified object by adding this module's constants and
1870 * methods (which are added as singleton methods). This is the callback
1871 * method used by Object#extend.
1872 *
1873 * module Picky
1874 * def Picky.extend_object(o)
1875 * if String === o
1876 * puts "Can't add Picky to a String"
1877 * else
1878 * puts "Picky added to #{o.class}"
1879 * super
1880 * end
1881 * end
1882 * end
1883 * (s = Array.new).extend Picky # Call Object.extend
1884 * (s = "quick brown fox").extend Picky
1885 *
1886 * <em>produces:</em>
1887 *
1888 * Picky added to Array
1889 * Can't add Picky to a String
1890 */
1891
1892static VALUE
1893rb_mod_extend_object(VALUE mod, VALUE obj)
1894{
1895 rb_extend_object(obj, mod);
1896 return obj;
1897}
1898
1899/*
1900 * call-seq:
1901 * obj.extend(module, ...) -> obj
1902 *
1903 * Adds to _obj_ the instance methods from each module given as a
1904 * parameter.
1905 *
1906 * module Mod
1907 * def hello
1908 * "Hello from Mod.\n"
1909 * end
1910 * end
1911 *
1912 * class Klass
1913 * def hello
1914 * "Hello from Klass.\n"
1915 * end
1916 * end
1917 *
1918 * k = Klass.new
1919 * k.hello #=> "Hello from Klass.\n"
1920 * k.extend(Mod) #=> #<Klass:0x401b3bc8>
1921 * k.hello #=> "Hello from Mod.\n"
1922 */
1923
1924static VALUE
1925rb_obj_extend(int argc, VALUE *argv, VALUE obj)
1926{
1927 int i;
1928 ID id_extend_object, id_extended;
1929
1930 CONST_ID(id_extend_object, "extend_object");
1931 CONST_ID(id_extended, "extended");
1932
1933 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
1934 for (i = 0; i < argc; i++) {
1935 Check_Type(argv[i], T_MODULE);
1936 if (FL_TEST(argv[i], RMODULE_IS_REFINEMENT)) {
1937 rb_raise(rb_eTypeError, "Cannot extend object with refinement");
1938 }
1939 }
1940 while (argc--) {
1941 rb_funcall(argv[argc], id_extend_object, 1, obj);
1942 rb_funcall(argv[argc], id_extended, 1, obj);
1943 }
1944 return obj;
1945}
1946
1947 VALUE
1948rb_top_main_class(const char *method)
1949{
1950 VALUE klass = GET_THREAD()->top_wrapper;
1951
1952 if (!klass) return rb_cObject;
1953 rb_warning("main.%s in the wrapped load is effective only in wrapper module", method);
1954 return klass;
1955}
1956
1957/*
1958 * call-seq:
1959 * include(module, ...) -> self
1960 *
1961 * Invokes Module.append_features on each parameter in turn.
1962 * Effectively adds the methods and constants in each module to the
1963 * receiver.
1964 */
1965
1966static VALUE
1967top_include(int argc, VALUE *argv, VALUE self)
1968{
1969 return rb_mod_include(argc, argv, rb_top_main_class("include"));
1970}
1971
1972/*
1973 * call-seq:
1974 * using(module) -> self
1975 *
1976 * Import class refinements from <i>module</i> into the scope where
1977 * #using is called.
1978 */
1979
1980static VALUE
1981top_using(VALUE self, VALUE module)
1982{
1983 const rb_cref_t *cref = CREF_NEXT(rb_vm_cref());
1984 rb_control_frame_t *prev_cfp = previous_frame(GET_EC());
1985 rb_thread_t *th = GET_THREAD();
1986
1987 if ((th->top_wrapper ? CREF_NEXT(cref) : cref) ||
1988 (prev_cfp && rb_vm_frame_method_entry(prev_cfp))) {
1989 rb_raise(rb_eRuntimeError, "main.using is permitted only at toplevel");
1990 }
1991 if (rb_block_given_p()) {
1992 ignored_block(module, "main.");
1993 }
1994 rb_using_module(rb_vm_cref_replace_with_duplicated_cref(), module);
1995 return self;
1996}
1997
1998static const VALUE *
1999errinfo_place(const rb_execution_context_t *ec)
2000{
2001 const rb_control_frame_t *cfp = ec->cfp;
2002 const rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(ec);
2003
2004 while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
2005 if (VM_FRAME_RUBYFRAME_P(cfp)) {
2006 if (ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_RESCUE) {
2007 return &cfp->ep[VM_ENV_INDEX_LAST_LVAR];
2008 }
2009 else if (ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_ENSURE &&
2010 !THROW_DATA_P(cfp->ep[VM_ENV_INDEX_LAST_LVAR]) &&
2011 !FIXNUM_P(cfp->ep[VM_ENV_INDEX_LAST_LVAR])) {
2012 return &cfp->ep[VM_ENV_INDEX_LAST_LVAR];
2013 }
2014 }
2015 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
2016 }
2017 return 0;
2018}
2019
2020 VALUE
2021rb_ec_get_errinfo(const rb_execution_context_t *ec)
2022{
2023 const VALUE *ptr = errinfo_place(ec);
2024 if (ptr) {
2025 return *ptr;
2026 }
2027 else {
2028 return ec->errinfo;
2029 }
2030}
2031
2032static VALUE
2033get_errinfo(void)
2034{
2035 return get_ec_errinfo(GET_EC());
2036}
2037
2038static VALUE
2039errinfo_getter(ID id, VALUE *_)
2040{
2041 return get_errinfo();
2042}
2043
2044 VALUE
2045rb_errinfo(void)
2046{
2047 return GET_EC()->errinfo;
2048}
2049
2050void
2051rb_set_errinfo(VALUE err)
2052{
2053 if (!NIL_P(err) && !rb_obj_is_kind_of(err, rb_eException)) {
2054 rb_raise(rb_eTypeError, "assigning non-exception to $!");
2055 }
2056 GET_EC()->errinfo = err;
2057}
2058
2059static VALUE
2060errat_getter(ID id, VALUE *_)
2061{
2062 VALUE err = get_errinfo();
2063 if (!NIL_P(err)) {
2064 return rb_get_backtrace(err);
2065 }
2066 else {
2067 return Qnil;
2068 }
2069}
2070
2071static void
2072errat_setter(VALUE val, ID id, VALUE *var)
2073{
2074 VALUE err = get_errinfo();
2075 if (NIL_P(err)) {
2076 rb_raise(rb_eArgError, "$! not set");
2077 }
2078 set_backtrace(err, val);
2079}
2080
2081/*
2082 * call-seq:
2083 * __method__ -> symbol
2084 *
2085 * Returns the name at the definition of the current method as a
2086 * Symbol.
2087 * If called outside of a method, it returns <code>nil</code>.
2088 *
2089 */
2090
2091static VALUE
2092rb_f_method_name(VALUE _)
2093{
2094 ID fname = prev_frame_func(); /* need *method* ID */
2095
2096 if (fname) {
2097 return ID2SYM(fname);
2098 }
2099 else {
2100 return Qnil;
2101 }
2102}
2103
2104/*
2105 * call-seq:
2106 * __callee__ -> symbol
2107 *
2108 * Returns the called name of the current method as a Symbol.
2109 * If called outside of a method, it returns <code>nil</code>.
2110 *
2111 */
2112
2113static VALUE
2114rb_f_callee_name(VALUE _)
2115{
2116 ID fname = prev_frame_callee(); /* need *callee* ID */
2117
2118 if (fname) {
2119 return ID2SYM(fname);
2120 }
2121 else {
2122 return Qnil;
2123 }
2124}
2125
2126/*
2127 * call-seq:
2128 * __dir__ -> string
2129 *
2130 * Returns the canonicalized absolute path of the directory of the file from
2131 * which this method is called. It means symlinks in the path is resolved.
2132 * If <code>__FILE__</code> is <code>nil</code>, it returns <code>nil</code>.
2133 * The return value equals to <code>File.dirname(File.realpath(__FILE__))</code>.
2134 *
2135 */
2136static VALUE
2137f_current_dirname(VALUE _)
2138{
2139 VALUE base = rb_current_realfilepath();
2140 if (NIL_P(base)) {
2141 return Qnil;
2142 }
2143 base = rb_file_dirname(base);
2144 return base;
2145}
2146
2147/*
2148 * call-seq:
2149 * global_variables -> array
2150 *
2151 * Returns an array of the names of global variables. This includes
2152 * special regexp global variables such as <tt>$~</tt> and <tt>$+</tt>,
2153 * but does not include the numbered regexp global variables (<tt>$1</tt>,
2154 * <tt>$2</tt>, etc.).
2155 *
2156 * global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr]
2157 */
2158
2159static VALUE
2160f_global_variables(VALUE _)
2161{
2162 return rb_f_global_variables();
2163}
2164
2165/*
2166 * call-seq:
2167 * trace_var(symbol, cmd ) -> nil
2168 * trace_var(symbol) {|val| block } -> nil
2169 *
2170 * Controls tracing of assignments to global variables. The parameter
2171 * +symbol+ identifies the variable (as either a string name or a
2172 * symbol identifier). _cmd_ (which may be a string or a
2173 * +Proc+ object) or block is executed whenever the variable
2174 * is assigned. The block or +Proc+ object receives the
2175 * variable's new value as a parameter. Also see
2176 * #untrace_var.
2177 *
2178 * trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
2179 * $_ = "hello"
2180 * $_ = ' there'
2181 *
2182 * <em>produces:</em>
2183 *
2184 * $_ is now 'hello'
2185 * $_ is now ' there'
2186 */
2187
2188static VALUE
2189f_trace_var(int c, const VALUE *a, VALUE _)
2190{
2191 return rb_f_trace_var(c, a);
2192}
2193
2194/*
2195 * call-seq:
2196 * untrace_var(symbol [, cmd] ) -> array or nil
2197 *
2198 * Removes tracing for the specified command on the given global
2199 * variable and returns +nil+. If no command is specified,
2200 * removes all tracing for that variable and returns an array
2201 * containing the commands actually removed.
2202 */
2203
2204static VALUE
2205f_untrace_var(int c, const VALUE *a, VALUE _)
2206{
2207 return rb_f_untrace_var(c, a);
2208}
2209
2210void
2211Init_eval(void)
2212{
2213 rb_define_virtual_variable("$@", errat_getter, errat_setter);
2214 rb_define_virtual_variable("$!", errinfo_getter, 0);
2215
2216 rb_gvar_ractor_local("$@");
2217 rb_gvar_ractor_local("$!");
2218
2219 rb_define_global_function("raise", f_raise, -1);
2220 rb_define_global_function("fail", f_raise, -1);
2221
2222 rb_define_global_function("global_variables", f_global_variables, 0);
2223
2224 rb_define_global_function("__method__", rb_f_method_name, 0);
2225 rb_define_global_function("__callee__", rb_f_callee_name, 0);
2226 rb_define_global_function("__dir__", f_current_dirname, 0);
2227
2228 rb_define_method(rb_cModule, "include", rb_mod_include, -1);
2229 rb_define_method(rb_cModule, "prepend", rb_mod_prepend, -1);
2230
2231 rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
2232 rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
2233 rb_define_private_method(rb_cModule, "prepend_features", rb_mod_prepend_features, 1);
2234 rb_define_private_method(rb_cModule, "refine", rb_mod_refine, 1);
2235 rb_define_private_method(rb_cModule, "using", mod_using, 1);
2236 rb_define_method(rb_cModule, "refinements", mod_refinements, 0);
2237 rb_define_singleton_method(rb_cModule, "used_modules",
2238 rb_mod_s_used_modules, 0);
2239 rb_define_singleton_method(rb_cModule, "used_refinements",
2240 rb_mod_s_used_refinements, 0);
2241 rb_undef_method(rb_cClass, "refine");
2242 rb_define_private_method(rb_cRefinement, "import_methods", refinement_import_methods, -1);
2243 rb_define_method(rb_cRefinement, "target", rb_refinement_module_get_refined_class, 0);
2244 rb_undef_method(rb_cRefinement, "append_features");
2245 rb_undef_method(rb_cRefinement, "prepend_features");
2246 rb_undef_method(rb_cRefinement, "extend_object");
2247
2248 rb_undef_method(rb_cClass, "module_function");
2249
2250 Init_vm_eval();
2251 Init_eval_method();
2252
2253 rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
2254 rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, -1);
2255
2256 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
2257 "include", top_include, -1);
2258 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
2259 "using", top_using, 1);
2260
2261 rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
2262
2263 rb_define_global_function("trace_var", f_trace_var, -1);
2264 rb_define_global_function("untrace_var", f_untrace_var, -1);
2265
2266 rb_vm_register_special_exception(ruby_error_reenter, rb_eFatal, "exception reentered");
2267 rb_vm_register_special_exception(ruby_error_stackfatal, rb_eFatal, "machine stack overflow in critical region");
2268
2269 id_signo = rb_intern_const("signo");
2270 id_status = rb_intern_const("status");
2271}
2272
2273int
2274rb_errno(void)
2275{
2276 return *rb_orig_errno_ptr();
2277}
2278
2279void
2280rb_errno_set(int e)
2281{
2282 *rb_orig_errno_ptr() = e;
2283}
2284
2285int *
2286rb_errno_ptr(void)
2287{
2288 return rb_orig_errno_ptr();
2289}
RUBY_ASSERT
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:219
rb_define_method
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition cxxanyargs.hpp:670
rb_define_singleton_method
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
Definition cxxanyargs.hpp:685
rb_define_private_method
#define rb_define_private_method(klass, mid, func, arity)
Defines klass#mid and makes it private.
Definition cxxanyargs.hpp:677
rb_define_global_function
#define rb_define_global_function(mid, func, arity)
Defines rb_mKernel #mid.
Definition cxxanyargs.hpp:695
RUBY_EVENT_RAISE
#define RUBY_EVENT_RAISE
Encountered a raise statement.
Definition event.h:45
RUBY_EVENT_C_RETURN
#define RUBY_EVENT_C_RETURN
Return from a method, written in C.
Definition event.h:44
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Includes a module to a class.
Definition class.c:1685
rb_refinement_new
VALUE rb_refinement_new(void)
Creates a new, anonymous refinement.
Definition class.c:1578
rb_extend_object
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
Definition eval.c:1860
rb_prepend_module
void rb_prepend_module(VALUE klass, VALUE module)
Identical to rb_include_module(), except it "prepends" the passed module to the klass,...
Definition class.c:1935
rb_singleton_class
VALUE rb_singleton_class(VALUE obj)
Finds or creates the singleton class of the passed object.
Definition class.c:2800
rb_class_modify_check
void rb_class_modify_check(VALUE klass)
Asserts that klass is not a frozen class.
Definition eval.c:421
rb_need_block
void rb_need_block(void)
Declares that the current method needs a block.
Definition eval.c:1031
rb_frame_last_func
ID rb_frame_last_func(void)
Returns the ID of the last method in the call stack.
Definition eval.c:1238
rb_undef_method
void rb_undef_method(VALUE klass, const char *name)
Defines an undef of a method.
Definition class.c:2655
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
Definition class.c:3133
rb_keyword_given_p
int rb_keyword_given_p(void)
Determines if the current method is given a keyword argument.
Definition eval.c:1023
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition eval.c:1010
rb_get_kwargs
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Keyword argument deconstructor.
Definition class.c:2922
Qundef
#define Qundef
Old name of RUBY_Qundef.
Definition special_consts.h:62
INT2FIX
#define INT2FIX
Old name of RB_INT2FIX.
Definition long.h:48
OBJ_FROZEN
#define OBJ_FROZEN
Old name of RB_OBJ_FROZEN.
Definition fl_type.h:136
ID2SYM
#define ID2SYM
Old name of RB_ID2SYM.
Definition symbol.h:44
SPECIAL_CONST_P
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
Definition special_consts.h:56
OBJ_FREEZE
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
Definition fl_type.h:134
UNREACHABLE_RETURN
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
Definition assume.h:29
FIX2INT
#define FIX2INT
Old name of RB_FIX2INT.
Definition int.h:41
T_MODULE
#define T_MODULE
Old name of RUBY_T_MODULE.
Definition value_type.h:70
T_ICLASS
#define T_ICLASS
Old name of RUBY_T_ICLASS.
Definition value_type.h:66
FL_SET
#define FL_SET
Old name of RB_FL_SET.
Definition fl_type.h:128
rb_exc_new3
#define rb_exc_new3
Old name of rb_exc_new_str.
Definition error.h:38
Qtrue
#define Qtrue
Old name of RUBY_Qtrue.
Definition special_consts.h:61
Qnil
#define Qnil
Old name of RUBY_Qnil.
Definition special_consts.h:60
Qfalse
#define Qfalse
Old name of RUBY_Qfalse.
Definition special_consts.h:59
T_OBJECT
#define T_OBJECT
Old name of RUBY_T_OBJECT.
Definition value_type.h:75
NIL_P
#define NIL_P
Old name of RB_NIL_P.
Definition special_consts.h:55
T_CLASS
#define T_CLASS
Old name of RUBY_T_CLASS.
Definition value_type.h:58
BUILTIN_TYPE
#define BUILTIN_TYPE
Old name of RB_BUILTIN_TYPE.
Definition value_type.h:85
FL_TEST
#define FL_TEST
Old name of RB_FL_TEST.
Definition fl_type.h:130
FIXNUM_P
#define FIXNUM_P
Old name of RB_FIXNUM_P.
Definition special_consts.h:53
CONST_ID
#define CONST_ID
Old name of RUBY_CONST_ID.
Definition symbol.h:47
ruby_stop
void ruby_stop(int ex)
Calls ruby_cleanup() and exits the process.
Definition eval.c:290
ruby_exec_node
int ruby_exec_node(void *n)
Identical to ruby_run_node(), except it returns an opaque execution status.
Definition eval.c:325
ruby_setup
int ruby_setup(void)
Initializes the VM and builtin libraries.
Definition eval.c:65
ruby_finalize
void ruby_finalize(void)
Runs the VM finalization processes.
Definition eval.c:170
ruby_cleanup
int ruby_cleanup(int ex)
Destructs the VM.
Definition eval.c:178
ruby_process_options
void * ruby_process_options(int argc, char **argv)
Identical to ruby_options(), except it raises ruby-level exceptions on failure.
Definition ruby.c:3182
ruby_prog_init
void ruby_prog_init(void)
Defines built-in variables.
Definition ruby.c:3135
ruby_sig_finalize
void ruby_sig_finalize(void)
Clear signal handlers.
Definition signal.c:1471
ruby_debug
#define ruby_debug
This variable controls whether the interpreter is in debug mode.
Definition error.h:486
rb_eLocalJumpError
VALUE rb_eLocalJumpError
LocalJumpError exception.
Definition eval.c:48
rb_rescue2
VALUE rb_rescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2,...)
An equivalent of rescue clause.
Definition eval.c:1039
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition eval.c:653
rb_eSystemExit
VALUE rb_eSystemExit
SystemExit exception.
Definition error.c:1424
rb_eStandardError
VALUE rb_eStandardError
StandardError exception.
Definition error.c:1428
rb_set_errinfo
void rb_set_errinfo(VALUE err)
Sets the current exception ($!) to the given value.
Definition eval.c:2051
rb_eTypeError
VALUE rb_eTypeError
TypeError exception.
Definition error.c:1431
rb_vrescue2
VALUE rb_vrescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2, va_list args)
Identical to rb_rescue2(), except it takes va_list instead of variadic number of arguments.
Definition eval.c:1050
rb_eFatal
VALUE rb_eFatal
fatal exception.
Definition error.c:1427
rb_eInterrupt
VALUE rb_eInterrupt
Interrupt exception.
Definition error.c:1425
rb_exc_fatal
void rb_exc_fatal(VALUE mesg)
Raises a fatal error in the current thread.
Definition eval.c:666
rb_eRuntimeError
VALUE rb_eRuntimeError
RuntimeError exception.
Definition error.c:1429
rb_warn
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
Definition error.c:466
rb_exc_new
VALUE rb_exc_new(VALUE etype, const char *ptr, long len)
Creates an instance of the passed exception class.
Definition error.c:1469
rb_error_frozen_object
void rb_error_frozen_object(VALUE frozen_obj)
Identical to rb_error_frozen(), except it takes arbitrary Ruby object instead of C's string.
Definition error.c:4161
rb_eException
VALUE rb_eException
Mother of all exceptions.
Definition error.c:1423
rb_rescue
VALUE rb_rescue(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2)
Identical to rb_rescue2(), except it does not take a list of exception classes.
Definition eval.c:1110
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition eval.c:1161
rb_errinfo
VALUE rb_errinfo(void)
This is the same as $! in Ruby.
Definition eval.c:2045
rb_eSysStackError
VALUE rb_eSysStackError
SystemStackError exception.
Definition eval.c:49
rb_eThreadError
VALUE rb_eThreadError
ThreadError exception.
Definition eval.c:1028
rb_warning
void rb_warning(const char *fmt,...)
Issues a warning.
Definition error.c:497
rb_cClass
VALUE rb_cClass
Class class.
Definition object.c:63
rb_mKernel
VALUE rb_mKernel
Kernel module.
Definition object.c:60
rb_cRefinement
VALUE rb_cRefinement
Refinement class.
Definition object.c:64
rb_class_of
static VALUE rb_class_of(VALUE obj)
Object to class mapping function.
Definition globals.h:174
rb_obj_class
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition object.c:264
rb_obj_dup
VALUE rb_obj_dup(VALUE obj)
Duplicates the given object.
Definition object.c:582
rb_cBasicObject
VALUE rb_cBasicObject
BasicObject class.
Definition object.c:59
rb_cModule
VALUE rb_cModule
Module class.
Definition object.c:62
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
Definition object.c:923
ruby_init
void ruby_init(void)
Calls ruby_setup() and check error.
Definition eval.c:98
ruby_executable_node
int ruby_executable_node(void *n, int *status)
Checks the return value of ruby_options().
Definition eval.c:296
rb_funcall
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition vm_eval.c:1117
rb_funcallv_kw
VALUE rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
Identical to rb_funcallv(), except you can specify how to handle the last element of the given array.
Definition vm_eval.c:1084
rb_ary_new
VALUE rb_ary_new(void)
Allocates a new, empty array.
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
UNLIMITED_ARGUMENTS
#define UNLIMITED_ARGUMENTS
This macro is used in conjunction with rb_check_arity().
Definition error.h:35
rb_check_arity
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition error.h:284
rb_frame_callee
ID rb_frame_callee(void)
Identical to rb_frame_this_func(), except it returns the named used to call the method.
Definition eval.c:1199
rb_frame_this_func
ID rb_frame_this_func(void)
Queries the name of the Ruby level method that is calling this function.
Definition eval.c:1193
rb_interrupt
void rb_interrupt(void)
Raises an instance of rb_eInterrupt.
Definition eval.c:672
ruby_default_signal
void ruby_default_signal(int sig)
Pretends as if there was no custom signal handler.
Definition signal.c:411
rb_str_new
#define rb_str_new(str, len)
Allocates an instance of rb_cString.
Definition string.h:1499
rb_exc_new_cstr
#define rb_exc_new_cstr(exc, str)
Identical to rb_exc_new(), except it assumes the passed pointer is a pointer to a C string.
Definition string.h:1671
rb_check_string_type
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition string.c:2952
rb_obj_as_string
VALUE rb_obj_as_string(VALUE obj)
Try converting an object to its stringised representation using its to_s method, if any.
Definition string.c:1850
rb_f_untrace_var
VALUE rb_f_untrace_var(int argc, const VALUE *argv)
Deletes the passed tracer from the passed global variable, or if omitted, deletes everything.
Definition variable.c:924
rb_const_list
VALUE rb_const_list(void *)
This is another mysterious API that comes with no documents at all.
Definition variable.c:3705
rb_ivar_set
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
Definition variable.c:2030
rb_f_trace_var
VALUE rb_f_trace_var(int argc, const VALUE *argv)
Traces a global variable.
Definition variable.c:878
rb_mod_constants
VALUE rb_mod_constants(int argc, const VALUE *argv, VALUE recv)
Resembles Module#constants.
Definition variable.c:3737
rb_mod_const_of
void * rb_mod_const_of(VALUE, void *)
This is a variant of rb_mod_const_at().
Definition variable.c:3683
rb_mod_const_at
void * rb_mod_const_at(VALUE, void *)
This API is mysterious.
Definition variable.c:3668
rb_ivar_defined
VALUE rb_ivar_defined(VALUE obj, ID name)
Queries if the instance variable is defined at the object.
Definition variable.c:2109
rb_f_global_variables
VALUE rb_f_global_variables(void)
Queries the list of global variables.
Definition variable.c:1133
rb_class_path
VALUE rb_class_path(VALUE mod)
Identical to rb_mod_name(), except it returns #<Class: ...> style inspection for anonymous modules.
Definition variable.c:380
rb_check_funcall
VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it returns RUBY_Qundef instead of raising rb_eNoMethodError.
Definition vm_eval.c:686
rb_intern_const
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
Definition symbol.h:285
vm.h
ruby_vm_destruct
int ruby_vm_destruct(ruby_vm_t *vm)
Destructs the passed VM.
Definition vm.c:3367
ruby::backward::cxxanyargs::rb_hash_foreach
void rb_hash_foreach(VALUE q, int_type *w, VALUE e)
Iteration over the given hash.
Definition cxxanyargs.hpp:482
ruby::backward::cxxanyargs::rb_define_virtual_variable
void rb_define_virtual_variable(const char *q, type *w, void_type *e)
Define a function-backended global variable.
Definition cxxanyargs.hpp:73
RBASIC
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
RCLASS_SUPER
#define RCLASS_SUPER
Just another name of rb_class_get_superclass.
Definition rclass.h:44
RHASH_EMPTY_P
#define RHASH_EMPTY_P(h)
Checks if the hash is empty.
Definition rhash.h:79
rb_obj_classname
const char * rb_obj_classname(VALUE obj)
Queries the name of the class of the passed object.
Definition variable.c:515
rb_errno_ptr
int * rb_errno_ptr(void)
The location of errno.
Definition eval.c:2286
rb_orig_errno_ptr
static int * rb_orig_errno_ptr(void)
Not sure if it is necessary for extension libraries but this is where the "bare" errno is located.
Definition ruby.h:381
rb_errno
int rb_errno(void)
Identical to system errno.
Definition eval.c:2274
RB_NO_KEYWORDS
#define RB_NO_KEYWORDS
Do not pass keywords.
Definition scan_args.h:69
scheduler.h
Scheduler APIs.
rb_fiber_scheduler_set
VALUE rb_fiber_scheduler_set(VALUE scheduler)
Destructively assigns the passed scheduler to that of the current thread that is calling this functio...
Definition scheduler.c:433
RTEST
#define RTEST
This is an old name of RB_TEST.
Definition special_consts.h:51
_
#define _(args)
This was a transition path from K&R to ANSI.
Definition stdarg.h:35
rb_id_table
Definition id_table.c:41
rb_method_iseq_struct::cref
rb_cref_t * cref
class reference, should be marked
Definition method.h:144
rb_method_iseq_struct::iseqptr
const rb_iseq_t * iseqptr
iseq pointer, should be separated from iseqval
Definition method.h:143
rb_refinements_data
Definition eval.h:20
refinement_import_methods_arg
Definition eval.c:1794
ID
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition value.h:52
VALUE
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
Check_Type
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
Definition value_type.h:433
RB_TYPE_P
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition value_type.h:376