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