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