Ruby 4.1.0dev (2026-01-08 revision dcfbbdc38c2c0502f2eeb9172d1a82721b5ca45b)
eval.c (dcfbbdc38c2c0502f2eeb9172d1a82721b5ca45b)
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 * +cause+ can not be given as an only argument.
927 *
928 */
929
930static VALUE
931f_raise(int c, VALUE *v, VALUE _)
932{
933 return rb_f_raise(c, v);
934}
935
936static VALUE
937make_exception(int argc, const VALUE *argv, int isstr)
938{
939 VALUE mesg, exc;
940
941 mesg = Qnil;
942 switch (argc) {
943 case 0:
944 return Qnil;
945 case 1:
946 exc = argv[0];
947 if (isstr &&! NIL_P(exc)) {
948 mesg = rb_check_string_type(exc);
949 if (!NIL_P(mesg)) {
950 return rb_exc_new3(rb_eRuntimeError, mesg);
951 }
952 }
953
954 case 2:
955 case 3:
956 break;
957 default:
958 rb_error_arity(argc, 0, 3);
959 }
960 if (NIL_P(mesg)) {
961 mesg = rb_check_funcall(argv[0], idException, argc != 1, &argv[1]);
962 }
963 if (UNDEF_P(mesg)) {
964 rb_raise(rb_eTypeError, "exception class/object expected");
965 }
966 if (!rb_obj_is_kind_of(mesg, rb_eException)) {
967 rb_raise(rb_eTypeError, "exception object expected");
968 }
969 if (argc == 3) {
970 set_backtrace(mesg, argv[2]);
971 }
972
973 return mesg;
974}
975
976VALUE
977rb_make_exception(int argc, const VALUE *argv)
978{
979 return make_exception(argc, argv, TRUE);
980}
981
984static void
985rb_raise_jump(VALUE mesg, VALUE cause)
986{
987 rb_execution_context_t *ec = GET_EC();
988 const rb_control_frame_t *cfp = ec->cfp;
989 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
990 VALUE klass = me->owner;
991 VALUE self = cfp->self;
992 ID mid = me->called_id;
993
994 rb_vm_pop_frame(ec);
995 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, self, me->def->original_id, mid, klass, Qnil);
996
997 rb_longjmp(ec, TAG_RAISE, mesg, cause);
998}
999
1000void
1001rb_jump_tag(int tag)
1002{
1003 if (UNLIKELY(tag < TAG_RETURN || tag > TAG_FATAL)) {
1004 unknown_longjmp_status(tag);
1005 }
1006 EC_JUMP_TAG(GET_EC(), tag);
1007}
1008
1009int
1011{
1012 if (rb_vm_frame_block_handler(GET_EC()->cfp) == VM_BLOCK_HANDLER_NONE) {
1013 return FALSE;
1014 }
1015 else {
1016 return TRUE;
1017 }
1018}
1019
1020int rb_vm_cframe_keyword_p(const rb_control_frame_t *cfp);
1021
1022int
1024{
1025 return rb_vm_cframe_keyword_p(GET_EC()->cfp);
1026}
1027
1029
1030void
1032{
1033 if (!rb_block_given_p()) {
1034 rb_vm_localjump_error("no block given", Qnil, 0);
1035 }
1036}
1037
1038VALUE
1039rb_rescue2(VALUE (* b_proc) (VALUE), VALUE data1,
1040 VALUE (* r_proc) (VALUE, VALUE), VALUE data2, ...)
1041{
1042 va_list ap;
1043 va_start(ap, data2);
1044 VALUE ret = rb_vrescue2(b_proc, data1, r_proc, data2, ap);
1045 va_end(ap);
1046 return ret;
1047}
1048
1049VALUE
1050rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1,
1051 VALUE (* r_proc) (VALUE, VALUE), VALUE data2,
1052 va_list args)
1053{
1054 enum ruby_tag_type state;
1055 rb_execution_context_t * volatile ec = GET_EC();
1056 rb_control_frame_t *volatile cfp = ec->cfp;
1057 volatile VALUE result = Qfalse;
1058 volatile VALUE e_info = ec->errinfo;
1059
1060 EC_PUSH_TAG(ec);
1061 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1062 retry_entry:
1063 result = (*b_proc) (data1);
1064 }
1065 else if (result) {
1066 /* escape from r_proc */
1067 if (state == TAG_RETRY) {
1068 state = TAG_NONE;
1069 ec->errinfo = Qnil;
1070 result = Qfalse;
1071 goto retry_entry;
1072 }
1073 }
1074 else {
1075 rb_vm_rewind_cfp(ec, cfp);
1076
1077 if (state == TAG_RAISE) {
1078 int handle = FALSE;
1079 VALUE eclass;
1080 va_list ap;
1081
1082 result = Qnil;
1083 /* reuses args when raised again after retrying in r_proc */
1084 va_copy(ap, args);
1085 while ((eclass = va_arg(ap, VALUE)) != 0) {
1086 if (rb_obj_is_kind_of(ec->errinfo, eclass)) {
1087 handle = TRUE;
1088 break;
1089 }
1090 }
1091 va_end(ap);
1092
1093 if (handle) {
1094 state = TAG_NONE;
1095 if (r_proc) {
1096 result = (*r_proc) (data2, ec->errinfo);
1097 }
1098 ec->errinfo = e_info;
1099 }
1100 }
1101 }
1102 EC_POP_TAG();
1103 if (state)
1104 EC_JUMP_TAG(ec, state);
1105
1106 return result;
1107}
1108
1109VALUE
1110rb_rescue(VALUE (* b_proc)(VALUE), VALUE data1,
1111 VALUE (* r_proc)(VALUE, VALUE), VALUE data2)
1112{
1113 return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError,
1114 (VALUE)0);
1115}
1116
1117VALUE
1118rb_protect(VALUE (* proc) (VALUE), VALUE data, int *pstate)
1119{
1120 volatile VALUE result = Qnil;
1121 volatile enum ruby_tag_type state;
1122 rb_execution_context_t * volatile ec = GET_EC();
1123 rb_control_frame_t *volatile cfp = ec->cfp;
1124
1125 EC_PUSH_TAG(ec);
1126 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1127 result = (*proc)(data);
1128 }
1129 else {
1130 rb_vm_rewind_cfp(ec, cfp);
1131 }
1132 EC_POP_TAG();
1133
1134 if (pstate != NULL) *pstate = state;
1135 return result;
1136}
1137
1138VALUE
1139rb_ec_ensure(rb_execution_context_t *ec, VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2)
1140{
1141 enum ruby_tag_type state;
1142 volatile VALUE result = Qnil;
1143 VALUE errinfo;
1144 EC_PUSH_TAG(ec);
1145 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1146 result = (*b_proc) (data1);
1147 }
1148 EC_POP_TAG();
1149 errinfo = ec->errinfo;
1150 if (!NIL_P(errinfo) && !RB_TYPE_P(errinfo, T_OBJECT)) {
1151 ec->errinfo = Qnil;
1152 }
1153 (*e_proc)(data2);
1154 ec->errinfo = errinfo;
1155 if (state)
1156 EC_JUMP_TAG(ec, state);
1157 return result;
1158}
1159
1160VALUE
1161rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2)
1162{
1163 return rb_ec_ensure(GET_EC(), b_proc, data1, e_proc, data2);
1164}
1165
1166static ID
1167frame_func_id(const rb_control_frame_t *cfp)
1168{
1169 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
1170
1171 if (me) {
1172 return me->def->original_id;
1173 }
1174 else {
1175 return 0;
1176 }
1177}
1178
1179static ID
1180frame_called_id(rb_control_frame_t *cfp)
1181{
1182 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
1183
1184 if (me) {
1185 return me->called_id;
1186 }
1187 else {
1188 return 0;
1189 }
1190}
1191
1192ID
1193rb_frame_this_func(void)
1194{
1195 return frame_func_id(GET_EC()->cfp);
1196}
1197
1198ID
1199rb_frame_callee(void)
1200{
1201 return frame_called_id(GET_EC()->cfp);
1202}
1203
1204static rb_control_frame_t *
1205previous_frame(const rb_execution_context_t *ec)
1206{
1207 rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp);
1208 /* check if prev_cfp can be accessible */
1209 if ((void *)(ec->vm_stack + ec->vm_stack_size) == (void *)(prev_cfp)) {
1210 return 0;
1211 }
1212 return prev_cfp;
1213}
1214
1215static ID
1216prev_frame_callee(void)
1217{
1218 rb_control_frame_t *prev_cfp = previous_frame(GET_EC());
1219 if (!prev_cfp) return 0;
1220 return frame_called_id(prev_cfp);
1221}
1222
1223static ID
1224prev_frame_func(void)
1225{
1226 rb_control_frame_t *prev_cfp = previous_frame(GET_EC());
1227 if (!prev_cfp) return 0;
1228 return frame_func_id(prev_cfp);
1229}
1230
1237ID
1238rb_frame_last_func(void)
1239{
1240 const rb_execution_context_t *ec = GET_EC();
1241 const rb_control_frame_t *cfp = ec->cfp;
1242 ID mid;
1243
1244 while (!(mid = frame_func_id(cfp)) &&
1245 (cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp),
1246 !RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)));
1247 return mid;
1248}
1249
1250/*
1251 * call-seq:
1252 * append_features(mod) -> mod
1253 *
1254 * When this module is included in another, Ruby calls
1255 * #append_features in this module, passing it the receiving module
1256 * in _mod_. Ruby's default implementation is to add the constants,
1257 * methods, and module variables of this module to _mod_ if this
1258 * module has not already been added to _mod_ or one of its
1259 * ancestors. See also Module#include.
1260 */
1261
1262static VALUE
1263rb_mod_append_features(VALUE module, VALUE include)
1264{
1265 if (!CLASS_OR_MODULE_P(include)) {
1266 Check_Type(include, T_CLASS);
1267 }
1268 rb_include_module(include, module);
1269
1270 return module;
1271}
1272
1273static VALUE refinement_import_methods(int argc, VALUE *argv, VALUE refinement);
1274
1275/*
1276 * call-seq:
1277 * include(module, ...) -> self
1278 *
1279 * Invokes Module.append_features on each parameter in reverse order.
1280 */
1281
1282static VALUE
1283rb_mod_include(int argc, VALUE *argv, VALUE module)
1284{
1285 int i;
1286 ID id_append_features, id_included;
1287
1288 CONST_ID(id_append_features, "append_features");
1289 CONST_ID(id_included, "included");
1290
1291 if (BUILTIN_TYPE(module) == T_MODULE && FL_TEST(module, RMODULE_IS_REFINEMENT)) {
1292 rb_raise(rb_eTypeError, "Refinement#include has been removed");
1293 }
1294
1296 for (i = 0; i < argc; i++) {
1297 Check_Type(argv[i], T_MODULE);
1298 if (FL_TEST(argv[i], RMODULE_IS_REFINEMENT)) {
1299 rb_raise(rb_eTypeError, "Cannot include refinement");
1300 }
1301 }
1302 while (argc--) {
1303 rb_funcall(argv[argc], id_append_features, 1, module);
1304 rb_funcall(argv[argc], id_included, 1, module);
1305 }
1306 return module;
1307}
1308
1309/*
1310 * call-seq:
1311 * prepend_features(mod) -> mod
1312 *
1313 * When this module is prepended in another, Ruby calls
1314 * #prepend_features in this module, passing it the receiving module
1315 * in _mod_. Ruby's default implementation is to overlay the
1316 * constants, methods, and module variables of this module to _mod_
1317 * if this module has not already been added to _mod_ or one of its
1318 * ancestors. See also Module#prepend.
1319 */
1320
1321static VALUE
1322rb_mod_prepend_features(VALUE module, VALUE prepend)
1323{
1324 if (!CLASS_OR_MODULE_P(prepend)) {
1325 Check_Type(prepend, T_CLASS);
1326 }
1327 rb_prepend_module(prepend, module);
1328
1329 return module;
1330}
1331
1332/*
1333 * call-seq:
1334 * prepend(module, ...) -> self
1335 *
1336 * Invokes Module.prepend_features on each parameter in reverse order.
1337 */
1338
1339static VALUE
1340rb_mod_prepend(int argc, VALUE *argv, VALUE module)
1341{
1342 int i;
1343 ID id_prepend_features, id_prepended;
1344
1345 if (BUILTIN_TYPE(module) == T_MODULE && FL_TEST(module, RMODULE_IS_REFINEMENT)) {
1346 rb_raise(rb_eTypeError, "Refinement#prepend has been removed");
1347 }
1348
1349 CONST_ID(id_prepend_features, "prepend_features");
1350 CONST_ID(id_prepended, "prepended");
1351
1353 for (i = 0; i < argc; i++) {
1354 Check_Type(argv[i], T_MODULE);
1355 if (FL_TEST(argv[i], RMODULE_IS_REFINEMENT)) {
1356 rb_raise(rb_eTypeError, "Cannot prepend refinement");
1357 }
1358 }
1359 while (argc--) {
1360 rb_funcall(argv[argc], id_prepend_features, 1, module);
1361 rb_funcall(argv[argc], id_prepended, 1, module);
1362 }
1363 return module;
1364}
1365
1366static void
1367ensure_class_or_module(VALUE obj)
1368{
1369 if (!RB_TYPE_P(obj, T_CLASS) && !RB_TYPE_P(obj, T_MODULE)) {
1370 rb_raise(rb_eTypeError,
1371 "wrong argument type %"PRIsVALUE" (expected Class or Module)",
1372 rb_obj_class(obj));
1373 }
1374}
1375
1376static VALUE
1377hidden_identity_hash_new(void)
1378{
1379 VALUE hash = rb_ident_hash_new();
1380
1381 RBASIC_CLEAR_CLASS(hash); /* hide from ObjectSpace */
1382 return hash;
1383}
1384
1385static VALUE
1386refinement_superclass(VALUE superclass)
1387{
1388 if (RB_TYPE_P(superclass, T_MODULE)) {
1389 /* FIXME: Should ancestors of superclass be used here? */
1390 return rb_include_class_new(RCLASS_ORIGIN(superclass), rb_cBasicObject);
1391 }
1392 else {
1393 return superclass;
1394 }
1395}
1396
1400static void
1401rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module)
1402{
1403 VALUE iclass, c, superclass = klass;
1404
1405 ensure_class_or_module(klass);
1406 Check_Type(module, T_MODULE);
1407 if (NIL_P(CREF_REFINEMENTS(cref))) {
1408 CREF_REFINEMENTS_SET(cref, hidden_identity_hash_new());
1409 }
1410 else {
1411 if (CREF_OMOD_SHARED(cref)) {
1412 CREF_REFINEMENTS_SET(cref, rb_hash_dup(CREF_REFINEMENTS(cref)));
1413 CREF_OMOD_SHARED_UNSET(cref);
1414 }
1415 if (!NIL_P(c = rb_hash_lookup(CREF_REFINEMENTS(cref), klass))) {
1416 superclass = c;
1417 while (c && RB_TYPE_P(c, T_ICLASS)) {
1418 if (RBASIC(c)->klass == module) {
1419 /* already used refinement */
1420 return;
1421 }
1422 c = RCLASS_SUPER(c);
1423 }
1424 }
1425 }
1426 superclass = refinement_superclass(superclass);
1427 c = iclass = rb_include_class_new(module, superclass);
1428 RCLASS_SET_REFINED_CLASS(c, klass);
1429
1430 RCLASS_WRITE_M_TBL(c, RCLASS_M_TBL(module));
1431
1432 rb_hash_aset(CREF_REFINEMENTS(cref), klass, iclass);
1433}
1434
1435static int
1436using_refinement(VALUE klass, VALUE module, VALUE arg)
1437{
1438 rb_cref_t *cref = (rb_cref_t *) arg;
1439
1440 rb_using_refinement(cref, klass, module);
1441 return ST_CONTINUE;
1442}
1443
1444static void
1445using_module_recursive(const rb_cref_t *cref, VALUE klass)
1446{
1447 ID id_refinements;
1448 VALUE super, module, refinements;
1449
1450 super = RCLASS_SUPER(klass);
1451 if (super) {
1452 using_module_recursive(cref, super);
1453 }
1454 switch (BUILTIN_TYPE(klass)) {
1455 case T_MODULE:
1456 module = klass;
1457 break;
1458
1459 case T_ICLASS:
1460 module = RBASIC(klass)->klass;
1461 break;
1462
1463 default:
1464 rb_raise(rb_eTypeError, "wrong argument type %s (expected Module)",
1465 rb_obj_classname(klass));
1466 break;
1467 }
1468 CONST_ID(id_refinements, "__refinements__");
1469 refinements = rb_attr_get(module, id_refinements);
1470 if (NIL_P(refinements)) return;
1471 rb_hash_foreach(refinements, using_refinement, (VALUE) cref);
1472}
1473
1477static void
1478rb_using_module(const rb_cref_t *cref, VALUE module)
1479{
1480 Check_Type(module, T_MODULE);
1481 using_module_recursive(cref, module);
1482 rb_clear_all_refinement_method_cache();
1483}
1484
1485void
1486rb_vm_using_module(VALUE module)
1487{
1488 rb_using_module(rb_vm_cref_replace_with_duplicated_cref(), module);
1489}
1490
1491/*
1492 * call-seq:
1493 * target -> class_or_module
1494 *
1495 * Return the class or module refined by the receiver.
1496 *
1497 * module M
1498 * refine String do
1499 * end
1500 * end
1501 *
1502 * M.refinements[0].target # => String
1503 */
1504VALUE
1505rb_refinement_module_get_refined_class(VALUE module)
1506{
1507 ID id_refined_class;
1508
1509 CONST_ID(id_refined_class, "__refined_class__");
1510 return rb_attr_get(module, id_refined_class);
1511}
1512
1513static void
1514add_activated_refinement(VALUE activated_refinements,
1515 VALUE klass, VALUE refinement)
1516{
1517 VALUE iclass, c, superclass = klass;
1518
1519 if (!NIL_P(c = rb_hash_lookup(activated_refinements, klass))) {
1520 superclass = c;
1521 while (c && RB_TYPE_P(c, T_ICLASS)) {
1522 if (RBASIC(c)->klass == refinement) {
1523 /* already used refinement */
1524 return;
1525 }
1526 c = RCLASS_SUPER(c);
1527 }
1528 }
1529 superclass = refinement_superclass(superclass);
1530 c = iclass = rb_include_class_new(refinement, superclass);
1531 RCLASS_SET_REFINED_CLASS(c, klass);
1532 refinement = RCLASS_SUPER(refinement);
1533 while (refinement && refinement != klass) {
1534 c = rb_class_set_super(c, rb_include_class_new(refinement, RCLASS_SUPER(c)));
1535 RCLASS_SET_REFINED_CLASS(c, klass);
1536 refinement = RCLASS_SUPER(refinement);
1537 }
1538 rb_hash_aset(activated_refinements, klass, iclass);
1539}
1540
1541void
1542rb_refinement_setup(struct rb_refinements_data *data, VALUE module, VALUE klass)
1543{
1544 VALUE refinement;
1545 ID id_refinements, id_activated_refinements,
1546 id_refined_class, id_defined_at;
1547 VALUE refinements, activated_refinements;
1548
1549 CONST_ID(id_refinements, "__refinements__");
1550 refinements = rb_attr_get(module, id_refinements);
1551 if (NIL_P(refinements)) {
1552 refinements = hidden_identity_hash_new();
1553 rb_ivar_set(module, id_refinements, refinements);
1554 }
1555 CONST_ID(id_activated_refinements, "__activated_refinements__");
1556 activated_refinements = rb_attr_get(module, id_activated_refinements);
1557 if (NIL_P(activated_refinements)) {
1558 activated_refinements = hidden_identity_hash_new();
1559 rb_ivar_set(module, id_activated_refinements,
1560 activated_refinements);
1561 }
1562 refinement = rb_hash_lookup(refinements, klass);
1563 if (NIL_P(refinement)) {
1564 VALUE superclass = refinement_superclass(klass);
1565 refinement = rb_refinement_new();
1566 rb_class_set_super(refinement, superclass);
1567 RUBY_ASSERT(BUILTIN_TYPE(refinement) == T_MODULE);
1568 FL_SET(refinement, RMODULE_IS_REFINEMENT);
1569 CONST_ID(id_refined_class, "__refined_class__");
1570 rb_ivar_set(refinement, id_refined_class, klass);
1571 CONST_ID(id_defined_at, "__defined_at__");
1572 rb_ivar_set(refinement, id_defined_at, module);
1573 rb_hash_aset(refinements, klass, refinement);
1574 add_activated_refinement(activated_refinements, klass, refinement);
1575 }
1576
1577 data->refinement = refinement;
1578 data->refinements = activated_refinements;
1579}
1580
1581/*
1582 * call-seq:
1583 * refine(mod) { block } -> module
1584 *
1585 * Refine <i>mod</i> in the receiver.
1586 *
1587 * Returns a module, where refined methods are defined.
1588 */
1589
1590static VALUE
1591rb_mod_refine(VALUE module, VALUE klass)
1592{
1593 /* module is the receiver of #refine, klass is a module to be refined (`mod` in the doc) */
1594 rb_thread_t *th = GET_THREAD();
1595 VALUE block_handler = rb_vm_frame_block_handler(th->ec->cfp);
1596 struct rb_refinements_data data;
1597
1598 if (block_handler == VM_BLOCK_HANDLER_NONE) {
1599 rb_raise(rb_eArgError, "no block given");
1600 }
1601 if (vm_block_handler_type(block_handler) != block_handler_type_iseq) {
1602 rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine");
1603 }
1604
1605 ensure_class_or_module(klass);
1606
1607 rb_refinement_setup(&data, module, klass);
1608
1609 rb_yield_refine_block(data.refinement, data.refinements);
1610 return data.refinement;
1611}
1612
1613static void
1614ignored_block(VALUE module, const char *klass)
1615{
1616 const char *anon = "";
1617 Check_Type(module, T_MODULE);
1618 if (!RTEST(rb_search_class_path(module))) {
1619 anon = ", maybe for Module.new";
1620 }
1621 rb_warn("%s""using doesn't call the given block""%s.", klass, anon);
1622}
1623
1624/*
1625 * call-seq:
1626 * using(module) -> self
1627 *
1628 * Import class refinements from <i>module</i> into the current class or
1629 * module definition.
1630 */
1631
1632static VALUE
1633mod_using(VALUE self, VALUE module)
1634{
1635 rb_control_frame_t *prev_cfp = previous_frame(GET_EC());
1636
1637 if (prev_frame_func()) {
1638 rb_raise(rb_eRuntimeError,
1639 "Module#using is not permitted in methods");
1640 }
1641 if (prev_cfp && prev_cfp->self != self) {
1642 rb_raise(rb_eRuntimeError, "Module#using is not called on self");
1643 }
1644 if (rb_block_given_p()) {
1645 ignored_block(module, "Module#");
1646 }
1647 rb_using_module(rb_vm_cref_replace_with_duplicated_cref(), module);
1648 return self;
1649}
1650
1651
1652/*
1653 * call-seq:
1654 * refinements -> array
1655 *
1656 * Returns an array of +Refinement+ defined within the receiver.
1657 *
1658 * module A
1659 * refine Integer do
1660 * end
1661 *
1662 * refine String do
1663 * end
1664 * end
1665 *
1666 * p A.refinements
1667 *
1668 * <em>produces:</em>
1669 *
1670 * [#<refinement:Integer@A>, #<refinement:String@A>]
1671 */
1672static VALUE
1673mod_refinements(VALUE self)
1674{
1675 ID id_refinements;
1676 VALUE refinements;
1677
1678 CONST_ID(id_refinements, "__refinements__");
1679 refinements = rb_attr_get(self, id_refinements);
1680 if (NIL_P(refinements)) {
1681 return rb_ary_new();
1682 }
1683 return rb_hash_values(refinements);
1684}
1685
1686static int
1687used_modules_i(VALUE _, VALUE mod, VALUE ary)
1688{
1689 ID id_defined_at;
1690 CONST_ID(id_defined_at, "__defined_at__");
1691 while (BUILTIN_TYPE(rb_class_of(mod)) == T_MODULE && FL_TEST(rb_class_of(mod), RMODULE_IS_REFINEMENT)) {
1692 rb_ary_push(ary, rb_attr_get(rb_class_of(mod), id_defined_at));
1693 mod = RCLASS_SUPER(mod);
1694 }
1695 return ST_CONTINUE;
1696}
1697
1698/*
1699 * call-seq:
1700 * used_modules -> array
1701 *
1702 * Returns an array of all modules used in the current scope. The ordering
1703 * of modules in the resulting array is not defined.
1704 *
1705 * module A
1706 * refine Object do
1707 * end
1708 * end
1709 *
1710 * module B
1711 * refine Object do
1712 * end
1713 * end
1714 *
1715 * using A
1716 * using B
1717 * p Module.used_modules
1718 *
1719 * <em>produces:</em>
1720 *
1721 * [B, A]
1722 */
1723static VALUE
1724rb_mod_s_used_modules(VALUE _)
1725{
1726 const rb_cref_t *cref = rb_vm_cref();
1727 VALUE ary = rb_ary_new();
1728
1729 while (cref) {
1730 if (!NIL_P(CREF_REFINEMENTS(cref))) {
1731 rb_hash_foreach(CREF_REFINEMENTS(cref), used_modules_i, ary);
1732 }
1733 cref = CREF_NEXT(cref);
1734 }
1735
1736 return rb_funcall(ary, rb_intern("uniq"), 0);
1737}
1738
1739static int
1740used_refinements_i(VALUE _, VALUE mod, VALUE ary)
1741{
1742 while (BUILTIN_TYPE(rb_class_of(mod)) == T_MODULE && FL_TEST(rb_class_of(mod), RMODULE_IS_REFINEMENT)) {
1743 rb_ary_push(ary, rb_class_of(mod));
1744 mod = RCLASS_SUPER(mod);
1745 }
1746 return ST_CONTINUE;
1747}
1748
1749/*
1750 * call-seq:
1751 * used_refinements -> array
1752 *
1753 * Returns an array of all modules used in the current scope. The ordering
1754 * of modules in the resulting array is not defined.
1755 *
1756 * module A
1757 * refine Object do
1758 * end
1759 * end
1760 *
1761 * module B
1762 * refine Object do
1763 * end
1764 * end
1765 *
1766 * using A
1767 * using B
1768 * p Module.used_refinements
1769 *
1770 * <em>produces:</em>
1771 *
1772 * [#<refinement:Object@B>, #<refinement:Object@A>]
1773 */
1774static VALUE
1775rb_mod_s_used_refinements(VALUE _)
1776{
1777 const rb_cref_t *cref = rb_vm_cref();
1778 VALUE ary = rb_ary_new();
1779
1780 while (cref) {
1781 if (!NIL_P(CREF_REFINEMENTS(cref))) {
1782 rb_hash_foreach(CREF_REFINEMENTS(cref), used_refinements_i, ary);
1783 }
1784 cref = CREF_NEXT(cref);
1785 }
1786
1787 return ary;
1788}
1789
1791 rb_cref_t *cref;
1792 VALUE refinement;
1793 VALUE module;
1794};
1795
1796/* vm.c */
1797rb_cref_t *rb_vm_cref_dup_without_refinements(const rb_cref_t *cref);
1798
1799static enum rb_id_table_iterator_result
1800refinement_import_methods_i(ID key, VALUE value, void *data)
1801{
1802 const rb_method_entry_t *me = (const rb_method_entry_t *)value;
1804
1805 if (me->def->type != VM_METHOD_TYPE_ISEQ) {
1806 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));
1807 }
1808 rb_cref_t *new_cref = rb_vm_cref_dup_without_refinements(me->def->body.iseq.cref);
1809 CREF_REFINEMENTS_SET(new_cref, CREF_REFINEMENTS(arg->cref));
1810 rb_add_method_iseq(arg->refinement, key, me->def->body.iseq.iseqptr, new_cref, METHOD_ENTRY_VISI(me));
1811 return ID_TABLE_CONTINUE;
1812}
1813
1814/*
1815 * Note: docs for the method are in class.c
1816 */
1817
1818static VALUE
1819refinement_import_methods(int argc, VALUE *argv, VALUE refinement)
1820{
1821 int i;
1823
1825 for (i = 0; i < argc; i++) {
1826 Check_Type(argv[i], T_MODULE);
1827 if (RCLASS_SUPER(argv[i])) {
1828 rb_warn("%"PRIsVALUE" has ancestors, but Refinement#import_methods doesn't import their methods", rb_class_path(argv[i]));
1829 }
1830 }
1831 arg.cref = rb_vm_cref_replace_with_duplicated_cref();
1832 arg.refinement = refinement;
1833 for (i = 0; i < argc; i++) {
1834 arg.module = argv[i];
1835 struct rb_id_table *m_tbl = RCLASS_M_TBL(argv[i]);
1836 if (!m_tbl) continue;
1837 rb_id_table_foreach(m_tbl, refinement_import_methods_i, &arg);
1838 }
1839 return refinement;
1840}
1841
1842void
1843rb_obj_call_init(VALUE obj, int argc, const VALUE *argv)
1844{
1845 rb_obj_call_init_kw(obj, argc, argv, RB_NO_KEYWORDS);
1846}
1847
1848void
1849rb_obj_call_init_kw(VALUE obj, int argc, const VALUE *argv, int kw_splat)
1850{
1851 PASS_PASSED_BLOCK_HANDLER();
1852 rb_funcallv_kw(obj, idInitialize, argc, argv, kw_splat);
1853}
1854
1855void
1857{
1859}
1860
1861/*
1862 * call-seq:
1863 * extend_object(obj) -> obj
1864 *
1865 * Extends the specified object by adding this module's constants and
1866 * methods (which are added as singleton methods). This is the callback
1867 * method used by Object#extend.
1868 *
1869 * module Picky
1870 * def Picky.extend_object(o)
1871 * if String === o
1872 * puts "Can't add Picky to a String"
1873 * else
1874 * puts "Picky added to #{o.class}"
1875 * super
1876 * end
1877 * end
1878 * end
1879 * (s = Array.new).extend Picky # Call Object.extend
1880 * (s = "quick brown fox").extend Picky
1881 *
1882 * <em>produces:</em>
1883 *
1884 * Picky added to Array
1885 * Can't add Picky to a String
1886 */
1887
1888static VALUE
1889rb_mod_extend_object(VALUE mod, VALUE obj)
1890{
1891 rb_extend_object(obj, mod);
1892 return obj;
1893}
1894
1895/*
1896 * call-seq:
1897 * obj.extend(module, ...) -> obj
1898 *
1899 * Adds to _obj_ the instance methods from each module given as a
1900 * parameter.
1901 *
1902 * module Mod
1903 * def hello
1904 * "Hello from Mod.\n"
1905 * end
1906 * end
1907 *
1908 * class Klass
1909 * def hello
1910 * "Hello from Klass.\n"
1911 * end
1912 * end
1913 *
1914 * k = Klass.new
1915 * k.hello #=> "Hello from Klass.\n"
1916 * k.extend(Mod) #=> #<Klass:0x401b3bc8>
1917 * k.hello #=> "Hello from Mod.\n"
1918 */
1919
1920static VALUE
1921rb_obj_extend(int argc, VALUE *argv, VALUE obj)
1922{
1923 int i;
1924 ID id_extend_object, id_extended;
1925
1926 CONST_ID(id_extend_object, "extend_object");
1927 CONST_ID(id_extended, "extended");
1928
1930 for (i = 0; i < argc; i++) {
1931 Check_Type(argv[i], T_MODULE);
1932 if (FL_TEST(argv[i], RMODULE_IS_REFINEMENT)) {
1933 rb_raise(rb_eTypeError, "Cannot extend object with refinement");
1934 }
1935 }
1936 while (argc--) {
1937 rb_funcall(argv[argc], id_extend_object, 1, obj);
1938 rb_funcall(argv[argc], id_extended, 1, obj);
1939 }
1940 return obj;
1941}
1942
1943VALUE
1944rb_top_main_class(const char *method)
1945{
1946 VALUE klass = GET_THREAD()->top_wrapper;
1947
1948 if (!klass) return rb_cObject;
1949 rb_warning("main.%s in the wrapped load is effective only in wrapper module", method);
1950 return klass;
1951}
1952
1953/*
1954 * call-seq:
1955 * include(module, ...) -> self
1956 *
1957 * Invokes Module.append_features on each parameter in turn.
1958 * Effectively adds the methods and constants in each module to the
1959 * receiver.
1960 */
1961
1962static VALUE
1963top_include(int argc, VALUE *argv, VALUE self)
1964{
1965 return rb_mod_include(argc, argv, rb_top_main_class("include"));
1966}
1967
1968/*
1969 * call-seq:
1970 * using(module) -> self
1971 *
1972 * Import class refinements from <i>module</i> into the scope where
1973 * #using is called.
1974 */
1975
1976static VALUE
1977top_using(VALUE self, VALUE module)
1978{
1979 const rb_cref_t *cref = CREF_NEXT(rb_vm_cref());
1980 rb_control_frame_t *prev_cfp = previous_frame(GET_EC());
1981 rb_thread_t *th = GET_THREAD();
1982
1983 if ((th->top_wrapper ? CREF_NEXT(cref) : cref) ||
1984 (prev_cfp && rb_vm_frame_method_entry(prev_cfp))) {
1985 rb_raise(rb_eRuntimeError, "main.using is permitted only at toplevel");
1986 }
1987 if (rb_block_given_p()) {
1988 ignored_block(module, "main.");
1989 }
1990 rb_using_module(rb_vm_cref_replace_with_duplicated_cref(), module);
1991 return self;
1992}
1993
1994static const VALUE *
1995errinfo_place(const rb_execution_context_t *ec)
1996{
1997 const rb_control_frame_t *cfp = ec->cfp;
1998 const rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(ec);
1999
2000 while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
2001 if (VM_FRAME_RUBYFRAME_P(cfp)) {
2002 if (ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_RESCUE) {
2003 return &cfp->ep[VM_ENV_INDEX_LAST_LVAR];
2004 }
2005 else if (ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_ENSURE &&
2006 !THROW_DATA_P(cfp->ep[VM_ENV_INDEX_LAST_LVAR]) &&
2007 !FIXNUM_P(cfp->ep[VM_ENV_INDEX_LAST_LVAR])) {
2008 return &cfp->ep[VM_ENV_INDEX_LAST_LVAR];
2009 }
2010 }
2011 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
2012 }
2013 return 0;
2014}
2015
2016VALUE
2017rb_ec_get_errinfo(const rb_execution_context_t *ec)
2018{
2019 const VALUE *ptr = errinfo_place(ec);
2020 if (ptr) {
2021 return *ptr;
2022 }
2023 else {
2024 return ec->errinfo;
2025 }
2026}
2027
2028static VALUE
2029get_errinfo(void)
2030{
2031 return get_ec_errinfo(GET_EC());
2032}
2033
2034static VALUE
2035errinfo_getter(ID id, VALUE *_)
2036{
2037 return get_errinfo();
2038}
2039
2040VALUE
2042{
2043 return GET_EC()->errinfo;
2044}
2045
2046void
2047rb_set_errinfo(VALUE err)
2048{
2049 if (!NIL_P(err) && !rb_obj_is_kind_of(err, rb_eException)) {
2050 rb_raise(rb_eTypeError, "assigning non-exception to $!");
2051 }
2052 GET_EC()->errinfo = err;
2053}
2054
2055static VALUE
2056errat_getter(ID id, VALUE *_)
2057{
2058 VALUE err = get_errinfo();
2059 if (!NIL_P(err)) {
2060 return rb_get_backtrace(err);
2061 }
2062 else {
2063 return Qnil;
2064 }
2065}
2066
2067static void
2068errat_setter(VALUE val, ID id, VALUE *var)
2069{
2070 VALUE err = get_errinfo();
2071 if (NIL_P(err)) {
2072 rb_raise(rb_eArgError, "$! not set");
2073 }
2074 set_backtrace(err, val);
2075}
2076
2077/*
2078 * call-seq:
2079 * __method__ -> symbol
2080 *
2081 * Returns the name at the definition of the current method as a
2082 * Symbol.
2083 * If called outside of a method, it returns <code>nil</code>.
2084 *
2085 */
2086
2087static VALUE
2088rb_f_method_name(VALUE _)
2089{
2090 ID fname = prev_frame_func(); /* need *method* ID */
2091
2092 if (fname) {
2093 return ID2SYM(fname);
2094 }
2095 else {
2096 return Qnil;
2097 }
2098}
2099
2100/*
2101 * call-seq:
2102 * __callee__ -> symbol
2103 *
2104 * Returns the called name of the current method as a Symbol.
2105 * If called outside of a method, it returns <code>nil</code>.
2106 *
2107 */
2108
2109static VALUE
2110rb_f_callee_name(VALUE _)
2111{
2112 ID fname = prev_frame_callee(); /* need *callee* ID */
2113
2114 if (fname) {
2115 return ID2SYM(fname);
2116 }
2117 else {
2118 return Qnil;
2119 }
2120}
2121
2122/*
2123 * call-seq:
2124 * __dir__ -> string
2125 *
2126 * Returns the canonicalized absolute path of the directory of the file from
2127 * which this method is called. It means symlinks in the path is resolved.
2128 * If <code>__FILE__</code> is <code>nil</code>, it returns <code>nil</code>.
2129 * The return value equals to <code>File.dirname(File.realpath(__FILE__))</code>.
2130 *
2131 */
2132static VALUE
2133f_current_dirname(VALUE _)
2134{
2135 VALUE base = rb_current_realfilepath();
2136 if (NIL_P(base)) {
2137 return Qnil;
2138 }
2139 base = rb_file_dirname(base);
2140 return base;
2141}
2142
2143/*
2144 * call-seq:
2145 * global_variables -> array
2146 *
2147 * Returns an array of the names of global variables. This includes
2148 * special regexp global variables such as <tt>$~</tt> and <tt>$+</tt>,
2149 * but does not include the numbered regexp global variables (<tt>$1</tt>,
2150 * <tt>$2</tt>, etc.).
2151 *
2152 * global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr]
2153 */
2154
2155static VALUE
2156f_global_variables(VALUE _)
2157{
2158 return rb_f_global_variables();
2159}
2160
2161/*
2162 * call-seq:
2163 * trace_var(symbol, cmd ) -> nil
2164 * trace_var(symbol) {|val| block } -> nil
2165 *
2166 * Controls tracing of assignments to global variables. The parameter
2167 * +symbol+ identifies the variable (as either a string name or a
2168 * symbol identifier). _cmd_ (which may be a string or a
2169 * +Proc+ object) or block is executed whenever the variable
2170 * is assigned. The block or +Proc+ object receives the
2171 * variable's new value as a parameter. Also see
2172 * #untrace_var.
2173 *
2174 * trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
2175 * $_ = "hello"
2176 * $_ = ' there'
2177 *
2178 * <em>produces:</em>
2179 *
2180 * $_ is now 'hello'
2181 * $_ is now ' there'
2182 */
2183
2184static VALUE
2185f_trace_var(int c, const VALUE *a, VALUE _)
2186{
2187 return rb_f_trace_var(c, a);
2188}
2189
2190/*
2191 * call-seq:
2192 * untrace_var(symbol [, cmd] ) -> array or nil
2193 *
2194 * Removes tracing for the specified command on the given global
2195 * variable and returns +nil+. If no command is specified,
2196 * removes all tracing for that variable and returns an array
2197 * containing the commands actually removed.
2198 */
2199
2200static VALUE
2201f_untrace_var(int c, const VALUE *a, VALUE _)
2202{
2203 return rb_f_untrace_var(c, a);
2204}
2205
2206void
2207Init_eval(void)
2208{
2209 rb_define_virtual_variable("$@", errat_getter, errat_setter);
2210 rb_define_virtual_variable("$!", errinfo_getter, 0);
2211
2212 rb_gvar_ractor_local("$@");
2213 rb_gvar_ractor_local("$!");
2214
2215 rb_define_global_function("raise", f_raise, -1);
2216 rb_define_global_function("fail", f_raise, -1);
2217
2218 rb_define_global_function("global_variables", f_global_variables, 0);
2219
2220 rb_define_global_function("__method__", rb_f_method_name, 0);
2221 rb_define_global_function("__callee__", rb_f_callee_name, 0);
2222 rb_define_global_function("__dir__", f_current_dirname, 0);
2223
2224 rb_define_method(rb_cModule, "include", rb_mod_include, -1);
2225 rb_define_method(rb_cModule, "prepend", rb_mod_prepend, -1);
2226
2227 rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
2228 rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
2229 rb_define_private_method(rb_cModule, "prepend_features", rb_mod_prepend_features, 1);
2230 rb_define_private_method(rb_cModule, "refine", rb_mod_refine, 1);
2231 rb_define_private_method(rb_cModule, "using", mod_using, 1);
2232 rb_define_method(rb_cModule, "refinements", mod_refinements, 0);
2233 rb_define_singleton_method(rb_cModule, "used_modules",
2234 rb_mod_s_used_modules, 0);
2235 rb_define_singleton_method(rb_cModule, "used_refinements",
2236 rb_mod_s_used_refinements, 0);
2237 rb_undef_method(rb_cClass, "refine");
2238 rb_define_private_method(rb_cRefinement, "import_methods", refinement_import_methods, -1);
2239 rb_define_method(rb_cRefinement, "target", rb_refinement_module_get_refined_class, 0);
2240 rb_undef_method(rb_cRefinement, "append_features");
2241 rb_undef_method(rb_cRefinement, "prepend_features");
2242 rb_undef_method(rb_cRefinement, "extend_object");
2243
2244 rb_undef_method(rb_cClass, "module_function");
2245
2246 Init_vm_eval();
2247 Init_eval_method();
2248
2249 rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
2250 rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, -1);
2251
2253 "include", top_include, -1);
2255 "using", top_using, 1);
2256
2257 rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
2258
2259 rb_define_global_function("trace_var", f_trace_var, -1);
2260 rb_define_global_function("untrace_var", f_untrace_var, -1);
2261
2262 rb_vm_register_special_exception(ruby_error_reenter, rb_eFatal, "exception reentered");
2263 rb_vm_register_special_exception(ruby_error_stackfatal, rb_eFatal, "machine stack overflow in critical region");
2264
2265 id_signo = rb_intern_const("signo");
2266 id_status = rb_intern_const("status");
2267}
2268
2269int
2270rb_errno(void)
2271{
2272 return *rb_orig_errno_ptr();
2273}
2274
2275void
2276rb_errno_set(int e)
2277{
2278 *rb_orig_errno_ptr() = e;
2279}
2280
2281int *
2282rb_errno_ptr(void)
2283{
2284 return rb_orig_errno_ptr();
2285}
#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:1798
VALUE rb_refinement_new(void)
Creates a new, anonymous refinement.
Definition class.c:1691
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
Definition eval.c:1856
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:2048
VALUE rb_singleton_class(VALUE obj)
Finds or creates the singleton class of the passed object.
Definition class.c:2915
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:1031
void rb_undef_method(VALUE klass, const char *name)
Defines an undef of a method.
Definition class.c:2770
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:3248
int rb_keyword_given_p(void)
Determines if the current method is given a keyword argument.
Definition eval.c:1023
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition eval.c:1010
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Keyword argument deconstructor.
Definition class.c:3037
#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:135
#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:133
#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:127
#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:129
#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:3175
void ruby_prog_init(void)
Defines built-in variables.
Definition ruby.c:3128
void ruby_sig_finalize(void)
Clear signal handlers.
Definition signal.c:1471
#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: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:1039
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:1411
VALUE rb_eStandardError
StandardError exception.
Definition error.c:1415
VALUE rb_eTypeError
TypeError exception.
Definition error.c:1418
VALUE rb_vrescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2, va_list args)
Identical to rb_rescue2(), except it takes va_list instead of variadic number of arguments.
Definition eval.c:1050
VALUE rb_eFatal
fatal exception.
Definition error.c:1414
VALUE rb_eInterrupt
Interrupt exception.
Definition error.c:1412
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:1416
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:1456
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:4148
VALUE rb_eException
Mother of all exceptions.
Definition error.c:1410
VALUE rb_rescue(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2)
Identical to rb_rescue2(), except it does not take a list of exception classes.
Definition eval.c:1110
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition eval.c:1161
VALUE rb_errinfo(void)
This is the same as $! in Ruby.
Definition eval.c:2041
VALUE rb_eSysStackError
SystemStackError exception.
Definition eval.c:49
VALUE rb_eThreadError
ThreadError exception.
Definition eval.c:1028
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_cObject
Object class.
Definition object.c:61
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:2951
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:1851
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:3692
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:2017
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:3724
void * rb_mod_const_of(VALUE, void *)
This is a variant of rb_mod_const_at().
Definition variable.c:3670
void * rb_mod_const_at(VALUE, void *)
This API is mysterious.
Definition variable.c:3655
VALUE rb_ivar_defined(VALUE obj, ID name)
Queries if the instance variable is defined at the object.
Definition variable.c:2096
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:285
int ruby_vm_destruct(ruby_vm_t *vm)
Destructs the passed VM.
Definition vm.c:3367
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:433
#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