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