Coverage Report

Created: 2026-06-03 06:22

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