2000-05-01 13:42:38 +04:00
|
|
|
/**********************************************************************
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
eval.c -
|
|
|
|
|
|
|
|
$Author$
|
|
|
|
created at: Thu Jun 10 14:22:17 JST 1993
|
|
|
|
|
* encoding.c: provide basic features for M17N.
* parse.y: encoding aware parsing.
* parse.y (pragma_encoding): encoding specification pragma.
* parse.y (rb_intern3): encoding specified symbols.
* string.c (rb_str_length): length based on characters.
for older behavior, bytesize method added.
* string.c (rb_str_index_m): index based on characters. rindex as
well.
* string.c (succ_char): encoding aware succeeding string.
* string.c (rb_str_reverse): reverse based on characters.
* string.c (rb_str_inspect): encoding aware string description.
* string.c (rb_str_upcase_bang): encoding aware case conversion.
downcase, capitalize, swapcase as well.
* string.c (rb_str_tr_bang): tr based on characters. delete,
squeeze, tr_s, count as well.
* string.c (rb_str_split_m): split based on characters.
* string.c (rb_str_each_line): encoding aware each_line.
* string.c (rb_str_each_char): added. iteration based on
characters.
* string.c (rb_str_strip_bang): encoding aware whitespace
stripping. lstrip, rstrip as well.
* string.c (rb_str_justify): encoding aware justifying (ljust,
rjust, center).
* string.c (str_encoding): get encoding attribute from a string.
* re.c (rb_reg_initialize): encoding aware regular expression
* sprintf.c (rb_str_format): formatting (i.e. length count) based
on characters.
* io.c (rb_io_getc): getc to return one-character string.
for older behavior, getbyte method added.
* ext/stringio/stringio.c (strio_getc): ditto.
* io.c (rb_io_ungetc): allow pushing arbitrary string at the
current reading point.
* ext/stringio/stringio.c (strio_ungetc): ditto.
* ext/strscan/strscan.c: encoding support.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-08-25 07:29:39 +04:00
|
|
|
Copyright (C) 1993-2007 Yukihiro Matsumoto
|
2000-05-01 13:42:38 +04:00
|
|
|
Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
|
2000-05-09 08:53:16 +04:00
|
|
|
Copyright (C) 2000 Information-technology Promotion Agency, Japan
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2000-05-01 13:42:38 +04:00
|
|
|
**********************************************************************/
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2020-05-08 12:31:09 +03:00
|
|
|
#include "ruby/internal/config.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
|
|
|
|
#ifdef HAVE_SYS_PRCTL_H
|
|
|
|
#include <sys/prctl.h>
|
|
|
|
#endif
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
#include "eval_intern.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "internal.h"
|
|
|
|
#include "internal/class.h"
|
2022-10-17 19:27:59 +03:00
|
|
|
#include "internal/cont.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "internal/error.h"
|
|
|
|
#include "internal/eval.h"
|
2023-02-08 14:56:53 +03:00
|
|
|
#include "internal/gc.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "internal/hash.h"
|
|
|
|
#include "internal/inits.h"
|
|
|
|
#include "internal/io.h"
|
|
|
|
#include "internal/object.h"
|
2020-09-20 02:34:02 +03:00
|
|
|
#include "internal/thread.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "internal/variable.h"
|
2021-02-09 09:39:56 +03:00
|
|
|
#include "ruby/fiber/scheduler.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "iseq.h"
|
2023-03-07 10:17:25 +03:00
|
|
|
#include "rjit.h"
|
2018-02-20 06:15:33 +03:00
|
|
|
#include "probes.h"
|
2012-11-29 21:55:54 +04:00
|
|
|
#include "probes_helper.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "ruby/vm.h"
|
|
|
|
#include "vm_core.h"
|
2020-11-17 10:40:47 +03:00
|
|
|
#include "ractor_core.h"
|
2003-12-13 03:01:28 +03:00
|
|
|
|
2021-03-18 20:03:56 +03:00
|
|
|
NORETURN(static void rb_raise_jump(VALUE, VALUE));
|
2019-08-12 11:44:30 +03:00
|
|
|
void rb_ec_clear_current_thread_trace_func(const rb_execution_context_t *ec);
|
2020-03-11 17:37:14 +03:00
|
|
|
void rb_ec_clear_all_trace_func(const rb_execution_context_t *ec);
|
1998-01-16 15:19:22 +03:00
|
|
|
|
2022-11-18 12:19:11 +03:00
|
|
|
static int rb_ec_cleanup(rb_execution_context_t *ec, enum ruby_tag_type ex);
|
2019-08-13 09:39:49 +03:00
|
|
|
static int rb_ec_exec_node(rb_execution_context_t *ec, void *n);
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
VALUE rb_eLocalJumpError;
|
|
|
|
VALUE rb_eSysStackError;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2015-02-23 10:05:30 +03:00
|
|
|
ID ruby_static_id_signo, ruby_static_id_status;
|
2018-05-15 10:45:24 +03:00
|
|
|
extern ID ruby_static_id_cause;
|
|
|
|
#define id_cause ruby_static_id_cause
|
2015-02-23 10:05:30 +03:00
|
|
|
|
2008-06-15 13:17:06 +04:00
|
|
|
#define exception_error GET_VM()->special_exceptions[ruby_error_reenter]
|
2007-08-14 14:53:53 +04:00
|
|
|
|
2007-12-20 12:29:46 +03:00
|
|
|
#include "eval_error.c"
|
|
|
|
#include "eval_jump.c"
|
1999-12-14 09:50:43 +03:00
|
|
|
|
2013-04-04 12:23:10 +04:00
|
|
|
#define CLASS_OR_MODULE_P(obj) \
|
|
|
|
(!SPECIAL_CONST_P(obj) && \
|
|
|
|
(BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE))
|
|
|
|
|
2012-06-14 06:22:08 +04:00
|
|
|
int
|
|
|
|
ruby_setup(void)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2017-06-23 10:25:52 +03:00
|
|
|
enum ruby_tag_type state;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2015-08-09 08:15:57 +03:00
|
|
|
if (GET_VM())
|
2012-06-14 06:22:08 +04:00
|
|
|
return 0;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2024-01-12 09:32:16 +03:00
|
|
|
ruby_init_stack((void *)&state);
|
2018-04-24 23:31:59 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Disable THP early before mallocs happen because we want this to
|
|
|
|
* affect as many future pages as possible for CoW-friendliness
|
|
|
|
*/
|
|
|
|
#if defined(__linux__) && defined(PR_SET_THP_DISABLE)
|
|
|
|
prctl(PR_SET_THP_DISABLE, 1, 0, 0, 0);
|
|
|
|
#endif
|
2024-01-12 09:32:16 +03:00
|
|
|
Init_BareVM();
|
2006-12-31 18:02:22 +03:00
|
|
|
Init_heap();
|
2018-08-23 11:32:30 +03:00
|
|
|
rb_vm_encoded_insn_data_table_init();
|
2014-05-04 17:04:37 +04:00
|
|
|
Init_vm_objects();
|
2006-12-31 18:02:22 +03:00
|
|
|
|
2017-12-06 06:16:08 +03:00
|
|
|
EC_PUSH_TAG(GET_EC());
|
|
|
|
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
|
2006-12-31 18:02:22 +03:00
|
|
|
rb_call_inits();
|
|
|
|
ruby_prog_init();
|
2012-06-16 13:31:50 +04:00
|
|
|
GET_VM()->running = 1;
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
2017-12-06 06:16:08 +03:00
|
|
|
EC_POP_TAG();
|
1998-01-16 15:19:22 +03:00
|
|
|
|
2012-06-14 06:22:08 +04:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ruby_init(void)
|
|
|
|
{
|
|
|
|
int state = ruby_setup();
|
2006-12-31 18:02:22 +03:00
|
|
|
if (state) {
|
2022-11-11 04:37:34 +03:00
|
|
|
if (RTEST(ruby_debug)) {
|
|
|
|
rb_execution_context_t *ec = GET_EC();
|
|
|
|
rb_ec_error_print(ec, ec->errinfo);
|
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
exit(EXIT_FAILURE);
|
2003-07-15 14:50:54 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-11 07:25:16 +04:00
|
|
|
void *
|
2006-12-31 18:02:22 +03:00
|
|
|
ruby_options(int argc, char **argv)
|
2002-05-14 10:22:31 +04:00
|
|
|
{
|
2019-08-12 11:44:30 +03:00
|
|
|
rb_execution_context_t *ec = GET_EC();
|
2017-06-23 10:25:52 +03:00
|
|
|
enum ruby_tag_type state;
|
2009-04-19 09:43:20 +04:00
|
|
|
void *volatile iseq = 0;
|
2006-12-31 18:02:22 +03:00
|
|
|
|
2009-04-19 09:43:20 +04:00
|
|
|
ruby_init_stack((void *)&iseq);
|
2019-08-12 11:44:30 +03:00
|
|
|
EC_PUSH_TAG(ec);
|
2017-12-06 06:16:08 +03:00
|
|
|
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
|
2009-02-22 07:04:31 +03:00
|
|
|
SAVE_ROOT_JMPBUF(GET_THREAD(), iseq = ruby_process_options(argc, argv));
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
|
|
|
else {
|
2019-08-13 03:50:34 +03:00
|
|
|
rb_ec_clear_current_thread_trace_func(ec);
|
2022-11-11 04:37:34 +03:00
|
|
|
int exitcode = error_handle(ec, ec->errinfo, state);
|
2022-11-18 12:22:12 +03:00
|
|
|
ec->errinfo = Qnil; /* just been handled */
|
2022-11-11 04:37:34 +03:00
|
|
|
iseq = (void *)INT2FIX(exitcode);
|
2002-05-14 10:22:31 +04:00
|
|
|
}
|
2017-12-06 06:16:08 +03:00
|
|
|
EC_POP_TAG();
|
2009-02-22 07:04:31 +03:00
|
|
|
return iseq;
|
2002-05-14 10:22:31 +04:00
|
|
|
}
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
static void
|
2021-02-09 09:39:56 +03:00
|
|
|
rb_ec_fiber_scheduler_finalize(rb_execution_context_t *ec)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2020-10-01 04:20:26 +03:00
|
|
|
enum ruby_tag_type state;
|
|
|
|
|
2019-08-12 11:44:30 +03:00
|
|
|
EC_PUSH_TAG(ec);
|
2020-10-01 04:20:26 +03:00
|
|
|
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
|
2021-02-09 09:39:56 +03:00
|
|
|
rb_fiber_scheduler_set(Qnil);
|
2020-10-01 04:20:26 +03:00
|
|
|
}
|
|
|
|
else {
|
2022-11-11 04:37:34 +03:00
|
|
|
state = error_handle(ec, ec->errinfo, state);
|
2003-05-02 10:41:33 +04:00
|
|
|
}
|
2017-12-06 06:16:08 +03:00
|
|
|
EC_POP_TAG();
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2020-09-20 02:34:02 +03:00
|
|
|
static void
|
2020-10-01 04:20:26 +03:00
|
|
|
rb_ec_teardown(rb_execution_context_t *ec)
|
2020-09-20 02:34:02 +03:00
|
|
|
{
|
2020-10-01 04:20:26 +03:00
|
|
|
// If the user code defined a scheduler for the top level thread, run it:
|
2021-02-09 09:39:56 +03:00
|
|
|
rb_ec_fiber_scheduler_finalize(ec);
|
2020-10-01 04:20:26 +03:00
|
|
|
|
2020-09-30 05:24:36 +03:00
|
|
|
EC_PUSH_TAG(ec);
|
|
|
|
if (EC_EXEC_TAG() == TAG_NONE) {
|
2020-10-01 04:20:26 +03:00
|
|
|
rb_vm_trap_exit(rb_ec_vm_ptr(ec));
|
2020-09-30 05:24:36 +03:00
|
|
|
}
|
|
|
|
EC_POP_TAG();
|
2020-10-01 04:20:26 +03:00
|
|
|
rb_ec_exec_end_proc(ec);
|
|
|
|
rb_ec_clear_all_trace_func(ec);
|
2020-09-20 02:34:02 +03:00
|
|
|
}
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
static void
|
2019-08-12 11:44:30 +03:00
|
|
|
rb_ec_finalize(rb_execution_context_t *ec)
|
2002-12-20 11:33:17 +03:00
|
|
|
{
|
2007-11-30 17:08:58 +03:00
|
|
|
ruby_sig_finalize();
|
2019-08-12 11:44:30 +03:00
|
|
|
ec->errinfo = Qnil;
|
|
|
|
rb_objspace_call_finalizer(rb_ec_vm_ptr(ec)->objspace);
|
2002-12-20 11:33:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-12-31 18:02:22 +03:00
|
|
|
ruby_finalize(void)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2019-08-12 11:44:30 +03:00
|
|
|
rb_execution_context_t *ec = GET_EC();
|
|
|
|
rb_ec_teardown(ec);
|
|
|
|
rb_ec_finalize(ec);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
int
|
2021-08-08 11:23:56 +03:00
|
|
|
ruby_cleanup(int ex)
|
2019-08-13 09:39:49 +03:00
|
|
|
{
|
2022-11-18 12:19:11 +03:00
|
|
|
return rb_ec_cleanup(GET_EC(), (enum ruby_tag_type)ex);
|
2019-08-13 09:39:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2022-11-11 04:37:34 +03:00
|
|
|
rb_ec_cleanup(rb_execution_context_t *ec, enum ruby_tag_type ex)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2007-04-20 10:48:23 +04:00
|
|
|
int state;
|
2022-11-11 04:37:34 +03:00
|
|
|
volatile VALUE save_error = Qundef;
|
|
|
|
volatile int sysex = EXIT_SUCCESS;
|
|
|
|
volatile int signaled = 0;
|
2019-08-13 09:39:49 +03:00
|
|
|
rb_thread_t *th = rb_ec_thread_ptr(ec);
|
2019-10-12 12:14:15 +03:00
|
|
|
rb_thread_t *const volatile th0 = th;
|
2016-04-23 06:23:51 +03:00
|
|
|
volatile int step = 0;
|
2022-11-11 04:37:34 +03:00
|
|
|
volatile VALUE message = Qnil;
|
|
|
|
VALUE buf;
|
2010-04-27 16:27:13 +04:00
|
|
|
|
|
|
|
rb_threadptr_interrupt(th);
|
|
|
|
rb_threadptr_check_signal(th);
|
2020-09-30 05:24:36 +03:00
|
|
|
|
2019-08-13 09:39:49 +03:00
|
|
|
EC_PUSH_TAG(ec);
|
2019-09-20 19:57:15 +03:00
|
|
|
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
|
2019-08-13 09:39:49 +03:00
|
|
|
SAVE_ROOT_JMPBUF(th, { RUBY_VM_CHECK_INTS(ec); });
|
2007-04-20 07:20:44 +04:00
|
|
|
|
2016-04-23 06:23:51 +03:00
|
|
|
step_0: step++;
|
2022-11-11 04:37:34 +03:00
|
|
|
save_error = ec->errinfo;
|
2019-08-13 09:39:49 +03:00
|
|
|
if (THROW_DATA_P(ec->errinfo)) ec->errinfo = Qnil;
|
2022-11-11 04:37:34 +03:00
|
|
|
ruby_init_stack(&message);
|
2008-05-05 12:19:35 +04:00
|
|
|
|
2022-11-11 04:37:34 +03:00
|
|
|
/* exits with failure but silently when an exception raised
|
|
|
|
* here */
|
2019-08-13 09:39:49 +03:00
|
|
|
SAVE_ROOT_JMPBUF(th, rb_ec_teardown(ec));
|
2008-05-05 12:19:35 +04:00
|
|
|
|
2016-04-23 06:23:51 +03:00
|
|
|
step_1: step++;
|
2022-11-11 04:37:34 +03:00
|
|
|
VALUE err = ec->errinfo;
|
2022-11-25 07:49:06 +03:00
|
|
|
volatile int mode0 = 0, mode1 = 0;
|
2022-11-11 04:37:34 +03:00
|
|
|
if (err != save_error && !NIL_P(err)) {
|
|
|
|
mode0 = exiting_split(err, &sysex, &signaled);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* exceptions after here will be ignored */
|
|
|
|
|
|
|
|
/* build error message including causes */
|
|
|
|
err = ATOMIC_VALUE_EXCHANGE(save_error, Qnil);
|
|
|
|
|
|
|
|
if (!NIL_P(err) && !THROW_DATA_P(err)) {
|
|
|
|
mode1 = exiting_split(err, (mode0 & EXITING_WITH_STATUS) ? NULL : &sysex, &signaled);
|
|
|
|
if (mode1 & EXITING_WITH_MESSAGE) {
|
|
|
|
buf = rb_str_new(NULL, 0);
|
|
|
|
SAVE_ROOT_JMPBUF(th, rb_ec_error_print_detailed(ec, err, buf, Qundef));
|
|
|
|
message = buf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
step_2: step++;
|
2016-04-23 06:23:51 +03:00
|
|
|
/* protect from Thread#raise */
|
|
|
|
th->status = THREAD_KILLED;
|
2012-11-29 04:48:16 +04:00
|
|
|
|
2020-03-09 20:22:11 +03:00
|
|
|
SAVE_ROOT_JMPBUF(th, rb_ractor_terminate_all());
|
2022-11-11 04:37:34 +03:00
|
|
|
|
|
|
|
step_3: step++;
|
|
|
|
if (!NIL_P(buf = message)) {
|
|
|
|
warn_print_str(buf);
|
|
|
|
}
|
|
|
|
else if (!NIL_OR_UNDEF_P(err = save_error) ||
|
|
|
|
(ex != TAG_NONE && !((mode0|mode1) & EXITING_WITH_STATUS))) {
|
|
|
|
sysex = error_handle(ec, err, ex);
|
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2016-04-23 06:23:51 +03:00
|
|
|
else {
|
2021-08-08 15:20:44 +03:00
|
|
|
th = th0;
|
2016-04-23 06:23:51 +03:00
|
|
|
switch (step) {
|
|
|
|
case 0: goto step_0;
|
|
|
|
case 1: goto step_1;
|
2022-11-11 04:37:34 +03:00
|
|
|
case 2: goto step_2;
|
|
|
|
case 3: goto step_3;
|
2020-04-14 19:25:04 +03:00
|
|
|
}
|
2007-06-18 08:52:59 +04:00
|
|
|
}
|
2013-11-30 12:46:41 +04:00
|
|
|
|
2019-08-13 09:39:49 +03:00
|
|
|
rb_ec_finalize(ec);
|
2013-11-30 12:46:41 +04:00
|
|
|
|
|
|
|
/* unlock again if finalizer took mutexes. */
|
2019-08-12 11:44:30 +03:00
|
|
|
rb_threadptr_unlock_all_locking_mutexes(th);
|
2021-08-08 15:20:44 +03:00
|
|
|
th = th0;
|
2017-10-26 14:02:13 +03:00
|
|
|
EC_POP_TAG();
|
2021-08-08 15:20:44 +03:00
|
|
|
th = th0;
|
2015-08-14 12:44:10 +03:00
|
|
|
rb_thread_stop_timer_thread();
|
2019-08-12 11:44:30 +03:00
|
|
|
ruby_vm_destruct(th->vm);
|
2022-10-20 03:18:59 +03:00
|
|
|
// For YJIT, call this after ruby_vm_destruct() frees jit_cont for the root fiber.
|
|
|
|
rb_jit_cont_finish();
|
2022-11-11 04:37:34 +03:00
|
|
|
|
|
|
|
if (signaled) ruby_default_signal(signaled);
|
2007-06-18 08:52:59 +04:00
|
|
|
|
2015-07-18 12:45:25 +03:00
|
|
|
return sysex;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2012-07-11 07:25:16 +04:00
|
|
|
static int
|
2019-08-13 09:39:49 +03:00
|
|
|
rb_ec_exec_node(rb_execution_context_t *ec, void *n)
|
2012-07-11 07:25:16 +04:00
|
|
|
{
|
|
|
|
volatile int state;
|
2015-07-22 01:52:59 +03:00
|
|
|
rb_iseq_t *iseq = (rb_iseq_t *)n;
|
2012-07-11 07:25:16 +04:00
|
|
|
if (!n) return 0;
|
|
|
|
|
2019-08-13 09:39:49 +03:00
|
|
|
EC_PUSH_TAG(ec);
|
2017-12-06 06:16:08 +03:00
|
|
|
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
|
2019-08-13 09:39:49 +03:00
|
|
|
rb_thread_t *const th = rb_ec_thread_ptr(ec);
|
2012-07-11 07:25:16 +04:00
|
|
|
SAVE_ROOT_JMPBUF(th, {
|
|
|
|
rb_iseq_eval_main(iseq);
|
|
|
|
});
|
|
|
|
}
|
2017-10-26 14:02:13 +03:00
|
|
|
EC_POP_TAG();
|
2012-07-11 07:25:16 +04:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
void
|
2007-02-07 16:34:18 +03:00
|
|
|
ruby_stop(int ex)
|
1999-01-20 07:59:39 +03:00
|
|
|
{
|
2006-12-31 18:02:22 +03:00
|
|
|
exit(ruby_cleanup(ex));
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
|
|
|
|
2009-10-12 14:48:35 +04:00
|
|
|
int
|
2012-07-11 07:25:16 +04:00
|
|
|
ruby_executable_node(void *n, int *status)
|
2009-10-12 14:48:35 +04:00
|
|
|
{
|
|
|
|
VALUE v = (VALUE)n;
|
|
|
|
int s;
|
|
|
|
|
|
|
|
switch (v) {
|
|
|
|
case Qtrue: s = EXIT_SUCCESS; break;
|
|
|
|
case Qfalse: s = EXIT_FAILURE; break;
|
|
|
|
default:
|
|
|
|
if (!FIXNUM_P(v)) return TRUE;
|
|
|
|
s = FIX2INT(v);
|
|
|
|
}
|
|
|
|
if (status) *status = s;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
* include/ruby/{intern,ruby}.h, compile.[ch], error.c, eval.c,
eval_load.c, gc.c, iseq.c, main.c, parse.y, re.c, ruby.c,
yarvcore.[ch] (ruby_eval_tree, ruby_sourcefile, ruby_sourceline,
ruby_nerrs): purge global variables.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12700 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-07-05 12:12:18 +04:00
|
|
|
int
|
2012-07-11 07:25:16 +04:00
|
|
|
ruby_run_node(void *n)
|
2009-10-10 12:03:24 +04:00
|
|
|
{
|
2019-08-13 09:39:49 +03:00
|
|
|
rb_execution_context_t *ec = GET_EC();
|
2009-10-12 14:48:35 +04:00
|
|
|
int status;
|
2009-10-14 04:06:42 +04:00
|
|
|
if (!ruby_executable_node(n, &status)) {
|
2022-11-18 12:22:12 +03:00
|
|
|
rb_ec_cleanup(ec, (NIL_P(ec->errinfo) ? TAG_NONE : TAG_RAISE));
|
2009-10-14 04:06:42 +04:00
|
|
|
return status;
|
|
|
|
}
|
2019-08-13 09:39:49 +03:00
|
|
|
ruby_init_stack((void *)&status);
|
|
|
|
return rb_ec_cleanup(ec, rb_ec_exec_node(ec, n));
|
2009-10-10 12:03:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-07-11 07:25:16 +04:00
|
|
|
ruby_exec_node(void *n)
|
1999-12-14 09:50:43 +03:00
|
|
|
{
|
2009-04-19 09:43:20 +04:00
|
|
|
ruby_init_stack((void *)&n);
|
2019-08-13 09:39:49 +03:00
|
|
|
return rb_ec_exec_node(GET_EC(), n);
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* Module.nesting -> array
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2006-12-31 18:02:22 +03:00
|
|
|
* Returns the list of +Modules+ nested at the point of call.
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2006-12-31 18:02:22 +03:00
|
|
|
* module M1
|
|
|
|
* module M2
|
|
|
|
* $a = Module.nesting
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
* $a #=> [M1::M2, M1]
|
|
|
|
* $a[0].name #=> "M1::M2"
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
2019-08-29 05:47:20 +03:00
|
|
|
rb_mod_nesting(VALUE _)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2006-12-31 18:02:22 +03:00
|
|
|
VALUE ary = rb_ary_new();
|
2015-03-09 00:22:43 +03:00
|
|
|
const rb_cref_t *cref = rb_vm_cref();
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2015-03-08 22:50:37 +03:00
|
|
|
while (cref && CREF_NEXT(cref)) {
|
|
|
|
VALUE klass = CREF_CLASS(cref);
|
|
|
|
if (!CREF_PUSHED_BY_EVAL(cref) &&
|
2009-12-03 21:25:57 +03:00
|
|
|
!NIL_P(klass)) {
|
2006-12-31 18:02:22 +03:00
|
|
|
rb_ary_push(ary, klass);
|
|
|
|
}
|
2015-03-08 22:50:37 +03:00
|
|
|
cref = CREF_NEXT(cref);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
return ary;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* Module.constants -> array
|
2012-01-12 20:37:03 +04:00
|
|
|
* Module.constants(inherited) -> array
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2012-01-12 20:37:03 +04:00
|
|
|
* In the first form, returns an array of the names of all
|
|
|
|
* constants accessible from the point of call.
|
|
|
|
* This list includes the names of all modules and classes
|
|
|
|
* defined in the global scope.
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2012-01-12 20:37:03 +04:00
|
|
|
* Module.constants.first(4)
|
|
|
|
* # => [:ARGF, :ARGV, :ArgumentError, :Array]
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2012-01-12 20:37:03 +04:00
|
|
|
* Module.constants.include?(:SEEK_SET) # => false
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2012-01-12 20:37:03 +04:00
|
|
|
* class IO
|
|
|
|
* Module.constants.include?(:SEEK_SET) # => true
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* The second form calls the instance method +constants+.
|
2006-12-31 18:02:22 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
|
2000-02-01 06:12:21 +03:00
|
|
|
{
|
2015-03-09 00:22:43 +03:00
|
|
|
const rb_cref_t *cref = rb_vm_cref();
|
2006-12-31 18:02:22 +03:00
|
|
|
VALUE klass;
|
|
|
|
VALUE cbase = 0;
|
|
|
|
void *data = 0;
|
2000-02-01 06:12:21 +03:00
|
|
|
|
2014-01-17 12:58:05 +04:00
|
|
|
if (argc > 0 || mod != rb_cModule) {
|
|
|
|
return rb_mod_constants(argc, argv, mod);
|
2000-02-01 06:12:21 +03:00
|
|
|
}
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
while (cref) {
|
2015-03-08 22:50:37 +03:00
|
|
|
klass = CREF_CLASS(cref);
|
|
|
|
if (!CREF_PUSHED_BY_EVAL(cref) &&
|
2011-03-31 09:54:34 +04:00
|
|
|
!NIL_P(klass)) {
|
2015-03-08 22:50:37 +03:00
|
|
|
data = rb_mod_const_at(CREF_CLASS(cref), data);
|
2006-12-31 18:02:22 +03:00
|
|
|
if (!cbase) {
|
|
|
|
cbase = klass;
|
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2015-03-08 22:50:37 +03:00
|
|
|
cref = CREF_NEXT(cref);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
|
|
|
|
if (cbase) {
|
|
|
|
data = rb_mod_const_of(cbase, data);
|
|
|
|
}
|
|
|
|
return rb_const_list(data);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2017-07-22 15:26:19 +03:00
|
|
|
/*!
|
|
|
|
* Asserts that \a klass is not a frozen class.
|
|
|
|
* \param[in] klass a \c Module object
|
|
|
|
* \exception RuntimeError if \a klass is not a class or frozen.
|
|
|
|
* \ingroup class
|
|
|
|
*/
|
1999-01-20 07:59:39 +03:00
|
|
|
void
|
2018-07-27 16:57:14 +03:00
|
|
|
rb_class_modify_check(VALUE klass)
|
1999-01-20 07:59:39 +03:00
|
|
|
{
|
2013-04-04 12:23:10 +04:00
|
|
|
if (SPECIAL_CONST_P(klass)) {
|
|
|
|
Check_Type(klass, T_CLASS);
|
|
|
|
}
|
2021-09-23 18:55:11 +03:00
|
|
|
if (RB_TYPE_P(klass, T_MODULE)) {
|
|
|
|
rb_module_set_initialized(klass);
|
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
if (OBJ_FROZEN(klass)) {
|
2013-04-04 12:23:10 +04:00
|
|
|
const char *desc;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2014-09-13 05:22:01 +04:00
|
|
|
if (FL_TEST(klass, FL_SINGLETON)) {
|
2006-12-31 18:02:22 +03:00
|
|
|
desc = "object";
|
2023-02-15 12:42:52 +03:00
|
|
|
klass = RCLASS_ATTACHED_OBJECT(klass);
|
2014-09-13 05:22:01 +04:00
|
|
|
if (!SPECIAL_CONST_P(klass)) {
|
|
|
|
switch (BUILTIN_TYPE(klass)) {
|
|
|
|
case T_MODULE:
|
|
|
|
case T_ICLASS:
|
|
|
|
desc = "Module";
|
|
|
|
break;
|
|
|
|
case T_CLASS:
|
|
|
|
desc = "Class";
|
|
|
|
break;
|
2020-04-08 09:13:37 +03:00
|
|
|
default:
|
|
|
|
break;
|
2014-09-13 05:22:01 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
else {
|
2013-04-04 12:23:10 +04:00
|
|
|
switch (BUILTIN_TYPE(klass)) {
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
case T_MODULE:
|
|
|
|
case T_ICLASS:
|
2006-12-31 18:02:22 +03:00
|
|
|
desc = "module";
|
|
|
|
break;
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
case T_CLASS:
|
2006-12-31 18:02:22 +03:00
|
|
|
desc = "class";
|
|
|
|
break;
|
2013-04-04 12:23:10 +04:00
|
|
|
default:
|
2020-06-15 05:58:30 +03:00
|
|
|
Check_Type(klass, T_CLASS);
|
2020-06-29 05:43:48 +03:00
|
|
|
UNREACHABLE;
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2019-05-28 03:52:35 +03:00
|
|
|
rb_frozen_error_raise(klass, "can't modify frozen %s: %"PRIsVALUE, desc, klass);
|
2000-02-01 06:12:21 +03:00
|
|
|
}
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
|
|
|
|
2017-10-28 14:41:08 +03:00
|
|
|
NORETURN(static void rb_longjmp(rb_execution_context_t *, int, volatile VALUE, VALUE));
|
2013-11-15 18:08:49 +04:00
|
|
|
static VALUE get_errinfo(void);
|
2019-12-16 03:44:01 +03:00
|
|
|
#define get_ec_errinfo(ec) rb_ec_get_errinfo(ec)
|
2013-11-15 18:08:49 +04:00
|
|
|
|
|
|
|
static VALUE
|
|
|
|
exc_setup_cause(VALUE exc, VALUE cause)
|
|
|
|
{
|
2019-09-03 15:08:07 +03:00
|
|
|
#if OPT_SUPPORT_JOKE
|
2013-11-15 18:08:49 +04:00
|
|
|
if (NIL_P(cause)) {
|
|
|
|
ID id_true_cause;
|
|
|
|
CONST_ID(id_true_cause, "true_cause");
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2013-11-15 18:08:49 +04:00
|
|
|
cause = rb_attr_get(rb_eFatal, id_true_cause);
|
|
|
|
if (NIL_P(cause)) {
|
|
|
|
cause = rb_exc_new_cstr(rb_eFatal, "because using such Ruby");
|
|
|
|
rb_ivar_set(cause, id_cause, INT2FIX(42)); /* the answer */
|
|
|
|
OBJ_FREEZE(cause);
|
|
|
|
rb_ivar_set(rb_eFatal, id_true_cause, cause);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (!NIL_P(cause) && cause != exc) {
|
|
|
|
rb_ivar_set(exc, id_cause, cause);
|
2016-12-21 14:12:39 +03:00
|
|
|
if (!rb_ivar_defined(cause, id_cause)) {
|
|
|
|
rb_ivar_set(cause, id_cause, Qnil);
|
|
|
|
}
|
2013-11-15 18:08:49 +04:00
|
|
|
}
|
|
|
|
return exc;
|
|
|
|
}
|
2001-11-19 08:03:03 +03:00
|
|
|
|
2017-08-02 05:40:29 +03:00
|
|
|
static inline VALUE
|
2017-10-28 14:41:08 +03:00
|
|
|
exc_setup_message(const rb_execution_context_t *ec, VALUE mesg, VALUE *cause)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2013-12-31 18:49:16 +04:00
|
|
|
int nocause = 0;
|
2018-12-23 14:11:36 +03:00
|
|
|
int nocircular = 0;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2011-05-18 17:36:46 +04:00
|
|
|
if (NIL_P(mesg)) {
|
2017-10-28 14:41:08 +03:00
|
|
|
mesg = ec->errinfo;
|
|
|
|
if (INTERNAL_EXCEPTION_P(mesg)) EC_JUMP_TAG(ec, TAG_FATAL);
|
2013-12-31 18:49:16 +04:00
|
|
|
nocause = 1;
|
2011-05-18 17:36:46 +04:00
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
if (NIL_P(mesg)) {
|
|
|
|
mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
|
2013-12-31 18:49:16 +04:00
|
|
|
nocause = 0;
|
2018-12-23 14:11:36 +03:00
|
|
|
nocircular = 1;
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
2022-11-15 07:24:08 +03:00
|
|
|
if (UNDEF_P(*cause)) {
|
2017-04-17 05:41:00 +03:00
|
|
|
if (nocause) {
|
2017-08-02 05:40:29 +03:00
|
|
|
*cause = Qnil;
|
2018-12-23 14:11:36 +03:00
|
|
|
nocircular = 1;
|
2017-04-17 05:41:00 +03:00
|
|
|
}
|
|
|
|
else if (!rb_ivar_defined(mesg, id_cause)) {
|
2017-10-28 14:41:08 +03:00
|
|
|
*cause = get_ec_errinfo(ec);
|
2017-04-17 05:41:00 +03:00
|
|
|
}
|
2018-12-23 14:11:36 +03:00
|
|
|
else {
|
|
|
|
nocircular = 1;
|
|
|
|
}
|
2013-12-31 18:49:16 +04:00
|
|
|
}
|
2018-12-23 08:49:43 +03:00
|
|
|
else if (!NIL_P(*cause) && !rb_obj_is_kind_of(*cause, rb_eException)) {
|
|
|
|
rb_raise(rb_eTypeError, "exception object expected");
|
|
|
|
}
|
2018-12-23 14:11:36 +03:00
|
|
|
|
2022-11-15 07:24:08 +03:00
|
|
|
if (!nocircular && !NIL_P(*cause) && !UNDEF_P(*cause) && *cause != mesg) {
|
2022-12-19 08:10:58 +03:00
|
|
|
#if 0 /* maybe critical for some cases */
|
|
|
|
rb_exc_check_circular_cause(*cause);
|
|
|
|
#else
|
2018-12-23 14:11:36 +03:00
|
|
|
VALUE c = *cause;
|
|
|
|
while (!NIL_P(c = rb_attr_get(c, id_cause))) {
|
|
|
|
if (c == mesg) {
|
|
|
|
rb_raise(rb_eArgError, "circular causes");
|
|
|
|
}
|
|
|
|
}
|
2022-12-19 08:10:58 +03:00
|
|
|
#endif
|
2018-12-23 14:11:36 +03:00
|
|
|
}
|
2017-08-02 05:40:29 +03:00
|
|
|
return mesg;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-10-28 14:41:08 +03:00
|
|
|
setup_exception(rb_execution_context_t *ec, int tag, volatile VALUE mesg, VALUE cause)
|
2017-08-02 05:40:29 +03:00
|
|
|
{
|
|
|
|
VALUE e;
|
|
|
|
int line;
|
2019-10-12 12:14:15 +03:00
|
|
|
const char *file = rb_source_location_cstr(&line);
|
|
|
|
const char *const volatile file0 = file;
|
2005-12-27 08:40:04 +03:00
|
|
|
|
2022-11-15 07:24:08 +03:00
|
|
|
if ((file && !NIL_P(mesg)) || !UNDEF_P(cause)) {
|
2017-08-02 05:40:29 +03:00
|
|
|
volatile int state = 0;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2017-10-28 14:41:08 +03:00
|
|
|
EC_PUSH_TAG(ec);
|
2017-12-06 06:16:08 +03:00
|
|
|
if (EC_EXEC_TAG() == TAG_NONE && !(state = rb_ec_set_raised(ec))) {
|
2017-04-18 11:34:40 +03:00
|
|
|
VALUE bt = rb_get_backtrace(mesg);
|
2022-11-15 07:24:08 +03:00
|
|
|
if (!NIL_P(bt) || UNDEF_P(cause)) {
|
2017-04-17 05:31:35 +03:00
|
|
|
if (OBJ_FROZEN(mesg)) {
|
|
|
|
mesg = rb_obj_dup(mesg);
|
2016-11-13 08:25:54 +03:00
|
|
|
}
|
2017-04-17 05:41:00 +03:00
|
|
|
}
|
2022-11-15 07:24:08 +03:00
|
|
|
if (!UNDEF_P(cause) && !THROW_DATA_P(cause)) {
|
2017-04-17 05:41:00 +03:00
|
|
|
exc_setup_cause(mesg, cause);
|
|
|
|
}
|
|
|
|
if (NIL_P(bt)) {
|
2017-10-28 16:22:04 +03:00
|
|
|
VALUE at = rb_ec_backtrace_object(ec);
|
2017-04-17 05:31:35 +03:00
|
|
|
rb_ivar_set(mesg, idBt_locations, at);
|
|
|
|
set_backtrace(mesg, at);
|
2008-06-15 13:17:06 +04:00
|
|
|
}
|
2017-11-07 07:01:13 +03:00
|
|
|
rb_ec_reset_raised(ec);
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
2017-10-26 14:02:13 +03:00
|
|
|
EC_POP_TAG();
|
2019-10-12 12:14:15 +03:00
|
|
|
file = file0;
|
2017-06-23 10:25:52 +03:00
|
|
|
if (state) goto fatal;
|
2005-12-27 08:40:04 +03:00
|
|
|
}
|
2013-12-13 08:31:06 +04:00
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
if (!NIL_P(mesg)) {
|
2017-10-28 14:41:08 +03:00
|
|
|
ec->errinfo = mesg;
|
2005-12-27 08:40:04 +03:00
|
|
|
}
|
|
|
|
|
2017-10-28 14:41:08 +03:00
|
|
|
if (RTEST(ruby_debug) && !NIL_P(e = ec->errinfo) &&
|
2007-08-13 12:23:12 +04:00
|
|
|
!rb_obj_is_kind_of(e, rb_eSystemExit)) {
|
2017-06-23 10:25:52 +03:00
|
|
|
enum ruby_tag_type state;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2014-02-26 08:26:23 +04:00
|
|
|
mesg = e;
|
2017-10-28 14:41:08 +03:00
|
|
|
EC_PUSH_TAG(ec);
|
2017-12-06 06:16:08 +03:00
|
|
|
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
|
2017-10-28 14:41:08 +03:00
|
|
|
ec->errinfo = Qnil;
|
2014-02-26 18:43:43 +04:00
|
|
|
e = rb_obj_as_string(mesg);
|
2017-10-28 14:41:08 +03:00
|
|
|
ec->errinfo = mesg;
|
2010-03-04 16:54:13 +03:00
|
|
|
if (file && line) {
|
2016-02-25 15:36:24 +03:00
|
|
|
e = rb_sprintf("Exception `%"PRIsVALUE"' at %s:%d - %"PRIsVALUE"\n",
|
|
|
|
rb_obj_class(mesg), file, line, e);
|
2007-09-25 16:40:17 +04:00
|
|
|
}
|
2010-03-04 16:54:13 +03:00
|
|
|
else if (file) {
|
2016-02-25 15:36:24 +03:00
|
|
|
e = rb_sprintf("Exception `%"PRIsVALUE"' at %s - %"PRIsVALUE"\n",
|
|
|
|
rb_obj_class(mesg), file, e);
|
2010-03-04 16:54:13 +03:00
|
|
|
}
|
2007-09-25 16:40:17 +04:00
|
|
|
else {
|
2016-02-25 15:36:24 +03:00
|
|
|
e = rb_sprintf("Exception `%"PRIsVALUE"' - %"PRIsVALUE"\n",
|
|
|
|
rb_obj_class(mesg), e);
|
2007-09-25 16:40:17 +04:00
|
|
|
}
|
2016-02-25 15:36:24 +03:00
|
|
|
warn_print_str(e);
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
2017-10-26 14:02:13 +03:00
|
|
|
EC_POP_TAG();
|
2017-10-28 14:41:08 +03:00
|
|
|
if (state == TAG_FATAL && ec->errinfo == exception_error) {
|
|
|
|
ec->errinfo = mesg;
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
2017-06-23 10:25:52 +03:00
|
|
|
else if (state) {
|
2017-11-07 07:01:13 +03:00
|
|
|
rb_ec_reset_raised(ec);
|
2017-10-28 14:41:08 +03:00
|
|
|
EC_JUMP_TAG(ec, state);
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
2002-03-25 09:18:07 +03:00
|
|
|
}
|
2000-11-27 12:23:38 +03:00
|
|
|
|
2017-11-07 08:12:39 +03:00
|
|
|
if (rb_ec_set_raised(ec)) {
|
2020-06-15 06:01:50 +03:00
|
|
|
goto fatal;
|
2009-11-07 05:45:08 +03:00
|
|
|
}
|
|
|
|
|
2010-01-05 08:59:23 +03:00
|
|
|
if (tag != TAG_FATAL) {
|
2017-10-28 14:41:08 +03:00
|
|
|
RUBY_DTRACE_HOOK(RAISE, rb_obj_classname(ec->errinfo));
|
2017-10-29 16:19:14 +03:00
|
|
|
EXEC_EVENT_HOOK(ec, RUBY_EVENT_RAISE, ec->cfp->self, 0, 0, 0, mesg);
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
2020-06-15 06:01:50 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
fatal:
|
|
|
|
ec->errinfo = exception_error;
|
|
|
|
rb_ec_reset_raised(ec);
|
|
|
|
EC_JUMP_TAG(ec, TAG_FATAL);
|
2010-01-24 16:52:32 +03:00
|
|
|
}
|
2007-06-15 07:22:51 +04:00
|
|
|
|
2017-07-22 15:26:19 +03:00
|
|
|
/*! \private */
|
2016-09-09 11:59:48 +03:00
|
|
|
void
|
2017-11-07 09:09:47 +03:00
|
|
|
rb_ec_setup_exception(const rb_execution_context_t *ec, VALUE mesg, VALUE cause)
|
2016-09-09 11:59:48 +03:00
|
|
|
{
|
2022-11-15 07:24:08 +03:00
|
|
|
if (UNDEF_P(cause)) {
|
2017-11-07 09:09:47 +03:00
|
|
|
cause = get_ec_errinfo(ec);
|
2016-09-09 11:59:48 +03:00
|
|
|
}
|
|
|
|
if (cause != mesg) {
|
Ensure throw data is not set as cause
[Bug #19593]
rb_ec_setup_exception did not check if errinfo is a throw_data. This can
cause crashes in code since it is assumed that id_cause is an object.
We saw a crash in show_cause due to id_cause of errinfo being a
throw_data. It crashes on rb_obj_is_kind_of since it cannot be called on
T_IMEMO objects.
Unfortunately, we couldn't find a reproduction script, however we
debugged the core dump and rb_ec_setup_exception is the only place where
id_cause is assigned from errinfo without checking if it is a
throw_data.
```
0x0000556c5708e6dd in sigsegv (sig=11, info=0x7f301befa3f0, ctx=0x7f301befa2c0) at signal.c:964
0x00007f301d046420 in <signal handler called> () at /lib/x86_64-linux-gnu/libpthread.so.0
class_search_class_ancestor (c=139844586301760, cl=<optimized out>) at object.c:810
rb_obj_is_kind_of (obj=obj@entry=139839221734880, c=139844586301760) at object.c:861
0x0000556c56f2f00f in show_cause
(errinfo=errinfo@entry=139838840645160, str=str@entry=139839221730520, opt=139839221730480, highlight=0, reverse=reverse@entry=0, backtrace_limit=backtrace_limit@entry=-1, shown_causes=0x7ffe9d1a2d68) at ./include/ruby/internal/special_consts.h:175
```
Co-Authored-By: Jean Boussier <byroot@ruby-lang.org>
2023-04-12 18:40:34 +03:00
|
|
|
if (THROW_DATA_P(cause)) {
|
|
|
|
cause = Qnil;
|
|
|
|
}
|
|
|
|
|
2016-09-09 11:59:48 +03:00
|
|
|
rb_ivar_set(mesg, id_cause, cause);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-24 16:52:32 +03:00
|
|
|
static void
|
2017-10-28 14:41:08 +03:00
|
|
|
rb_longjmp(rb_execution_context_t *ec, int tag, volatile VALUE mesg, VALUE cause)
|
2010-01-24 16:52:32 +03:00
|
|
|
{
|
2017-10-28 14:41:08 +03:00
|
|
|
mesg = exc_setup_message(ec, mesg, &cause);
|
|
|
|
setup_exception(ec, tag, mesg, cause);
|
2017-11-07 08:22:09 +03:00
|
|
|
rb_ec_raised_clear(ec);
|
2017-10-28 14:41:08 +03:00
|
|
|
EC_JUMP_TAG(ec, tag);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2014-06-18 10:16:39 +04:00
|
|
|
static VALUE make_exception(int argc, const VALUE *argv, int isstr);
|
2009-10-29 07:55:10 +03:00
|
|
|
|
2021-03-27 10:39:01 +03:00
|
|
|
NORETURN(static void rb_exc_exception(VALUE mesg, int tag, VALUE cause));
|
|
|
|
|
|
|
|
static void
|
|
|
|
rb_exc_exception(VALUE mesg, int tag, VALUE cause)
|
|
|
|
{
|
|
|
|
if (!NIL_P(mesg)) {
|
|
|
|
mesg = make_exception(1, &mesg, FALSE);
|
|
|
|
}
|
|
|
|
rb_longjmp(GET_EC(), tag, mesg, cause);
|
|
|
|
}
|
|
|
|
|
2017-07-22 15:26:19 +03:00
|
|
|
/*!
|
|
|
|
* Raises an exception in the current thread.
|
|
|
|
* \param[in] mesg an Exception class or an \c Exception object.
|
|
|
|
* \exception always raises an instance of the given exception class or
|
|
|
|
* the given \c Exception object.
|
|
|
|
* \ingroup exception
|
|
|
|
*/
|
2006-12-31 18:02:22 +03:00
|
|
|
void
|
2007-12-24 12:25:27 +03:00
|
|
|
rb_exc_raise(VALUE mesg)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2021-03-27 10:39:01 +03:00
|
|
|
rb_exc_exception(mesg, TAG_RAISE, Qundef);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2017-07-22 15:26:19 +03:00
|
|
|
/*!
|
|
|
|
* Raises a fatal error in the current thread.
|
|
|
|
*
|
|
|
|
* Same as rb_exc_raise() but raises a fatal error, which Ruby codes
|
|
|
|
* cannot rescue.
|
|
|
|
* \ingroup exception
|
|
|
|
*/
|
1999-08-13 09:45:20 +04:00
|
|
|
void
|
2007-12-24 12:25:27 +03:00
|
|
|
rb_exc_fatal(VALUE mesg)
|
1999-08-13 09:45:20 +04:00
|
|
|
{
|
2021-03-27 10:39:01 +03:00
|
|
|
rb_exc_exception(mesg, TAG_FATAL, Qnil);
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
void
|
2007-07-06 10:21:27 +04:00
|
|
|
rb_interrupt(void)
|
2003-09-01 11:59:18 +04:00
|
|
|
{
|
2018-02-03 02:25:42 +03:00
|
|
|
rb_exc_raise(rb_exc_new(rb_eInterrupt, 0, 0));
|
2003-09-01 11:59:18 +04:00
|
|
|
}
|
|
|
|
|
2017-07-22 15:26:19 +03:00
|
|
|
enum {raise_opt_cause, raise_max_opt}; /*< \private */
|
2013-12-31 18:49:16 +04:00
|
|
|
|
|
|
|
static int
|
2022-03-17 18:35:02 +03:00
|
|
|
extract_raise_opts(int argc, VALUE *argv, VALUE *opts)
|
2013-12-31 18:49:16 +04:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
if (argc > 0) {
|
2022-03-17 18:35:02 +03:00
|
|
|
VALUE opt;
|
|
|
|
argc = rb_scan_args(argc, argv, "*:", NULL, &opt);
|
|
|
|
if (!NIL_P(opt)) {
|
2014-06-17 07:37:47 +04:00
|
|
|
if (!RHASH_EMPTY_P(opt)) {
|
2013-12-31 18:49:16 +04:00
|
|
|
ID keywords[1];
|
|
|
|
CONST_ID(keywords[0], "cause");
|
2014-06-17 07:37:47 +04:00
|
|
|
rb_get_kwargs(opt, keywords, 0, -1-raise_max_opt, opts);
|
2022-03-17 18:35:02 +03:00
|
|
|
if (!RHASH_EMPTY_P(opt)) argv[argc++] = opt;
|
2013-12-31 18:49:16 +04:00
|
|
|
return argc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; i < raise_max_opt; ++i) {
|
|
|
|
opts[i] = Qundef;
|
|
|
|
}
|
|
|
|
return argc;
|
|
|
|
}
|
|
|
|
|
2019-08-29 04:23:14 +03:00
|
|
|
VALUE
|
|
|
|
rb_f_raise(int argc, VALUE *argv)
|
|
|
|
{
|
|
|
|
VALUE err;
|
|
|
|
VALUE opts[raise_max_opt], *const cause = &opts[raise_opt_cause];
|
|
|
|
|
|
|
|
argc = extract_raise_opts(argc, argv, opts);
|
|
|
|
if (argc == 0) {
|
2022-11-15 07:24:08 +03:00
|
|
|
if (!UNDEF_P(*cause)) {
|
2019-08-29 04:23:14 +03:00
|
|
|
rb_raise(rb_eArgError, "only cause is given with no arguments");
|
|
|
|
}
|
|
|
|
err = get_errinfo();
|
|
|
|
if (!NIL_P(err)) {
|
|
|
|
argc = 1;
|
|
|
|
argv = &err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rb_raise_jump(rb_make_exception(argc, argv), *cause);
|
|
|
|
|
|
|
|
UNREACHABLE_RETURN(Qnil);
|
|
|
|
}
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* raise
|
2018-12-24 11:11:49 +03:00
|
|
|
* raise(string, cause: $!)
|
|
|
|
* raise(exception [, string [, array]], cause: $!)
|
2006-12-31 18:02:22 +03:00
|
|
|
* fail
|
2018-12-24 11:11:49 +03:00
|
|
|
* fail(string, cause: $!)
|
|
|
|
* fail(exception [, string [, array]], cause: $!)
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2006-12-31 18:02:22 +03:00
|
|
|
* With no arguments, raises the exception in <code>$!</code> or raises
|
2019-07-23 00:02:39 +03:00
|
|
|
* a RuntimeError if <code>$!</code> is +nil+. With a single +String+
|
|
|
|
* argument, raises a +RuntimeError+ with the string as a message. Otherwise,
|
|
|
|
* the first parameter should be an +Exception+ class (or another
|
|
|
|
* object that returns an +Exception+ object when sent an +exception+
|
|
|
|
* message). The optional second parameter sets the message associated with
|
|
|
|
* the exception (accessible via Exception#message), and the third parameter
|
|
|
|
* is an array of callback information (accessible via Exception#backtrace).
|
|
|
|
* The +cause+ of the generated exception (accessible via Exception#cause)
|
|
|
|
* is automatically set to the "current" exception (<code>$!</code>), if any.
|
|
|
|
* An alternative value, either an +Exception+ object or +nil+, can be
|
|
|
|
* specified via the +:cause+ argument.
|
|
|
|
*
|
|
|
|
* Exceptions are caught by the +rescue+ clause of
|
|
|
|
* <code>begin...end</code> blocks.
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2006-12-31 18:02:22 +03:00
|
|
|
* raise "Failed to create socket"
|
|
|
|
* raise ArgumentError, "No parameters", caller
|
|
|
|
*/
|
2002-09-27 13:42:24 +04:00
|
|
|
|
2019-08-28 12:19:11 +03:00
|
|
|
static VALUE
|
|
|
|
f_raise(int c, VALUE *v, VALUE _)
|
|
|
|
{
|
|
|
|
return rb_f_raise(c, v);
|
|
|
|
}
|
|
|
|
|
2009-10-29 07:55:10 +03:00
|
|
|
static VALUE
|
2014-06-18 10:16:39 +04:00
|
|
|
make_exception(int argc, const VALUE *argv, int isstr)
|
2000-05-16 06:46:57 +04:00
|
|
|
{
|
2013-06-13 09:44:31 +04:00
|
|
|
VALUE mesg, exc;
|
2000-05-16 06:46:57 +04:00
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
mesg = Qnil;
|
|
|
|
switch (argc) {
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
case 0:
|
2020-06-15 06:38:19 +03:00
|
|
|
return Qnil;
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
case 1:
|
2013-06-13 09:44:31 +04:00
|
|
|
exc = argv[0];
|
2020-06-15 06:38:19 +03:00
|
|
|
if (isstr &&! NIL_P(exc)) {
|
2013-06-13 09:44:31 +04:00
|
|
|
mesg = rb_check_string_type(exc);
|
2009-10-29 07:55:10 +03:00
|
|
|
if (!NIL_P(mesg)) {
|
2020-06-24 05:04:19 +03:00
|
|
|
return rb_exc_new3(rb_eRuntimeError, mesg);
|
2009-10-29 07:55:10 +03:00
|
|
|
}
|
2000-05-16 06:46:57 +04:00
|
|
|
}
|
|
|
|
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
case 2:
|
|
|
|
case 3:
|
2006-12-31 18:02:22 +03:00
|
|
|
break;
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
default:
|
2019-07-14 11:16:35 +03:00
|
|
|
rb_error_arity(argc, 0, 3);
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
2020-06-15 06:38:19 +03:00
|
|
|
if (NIL_P(mesg)) {
|
|
|
|
mesg = rb_check_funcall(argv[0], idException, argc != 1, &argv[1]);
|
|
|
|
}
|
2022-11-15 07:24:08 +03:00
|
|
|
if (UNDEF_P(mesg)) {
|
2020-06-15 06:38:19 +03:00
|
|
|
rb_raise(rb_eTypeError, "exception class/object expected");
|
|
|
|
}
|
|
|
|
if (!rb_obj_is_kind_of(mesg, rb_eException)) {
|
|
|
|
rb_raise(rb_eTypeError, "exception object expected");
|
|
|
|
}
|
|
|
|
if (argc == 3) {
|
|
|
|
set_backtrace(mesg, argv[2]);
|
2000-05-16 06:46:57 +04:00
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
|
|
|
|
return mesg;
|
2000-05-16 06:46:57 +04:00
|
|
|
}
|
|
|
|
|
2009-10-29 07:55:10 +03:00
|
|
|
VALUE
|
2014-06-18 10:16:39 +04:00
|
|
|
rb_make_exception(int argc, const VALUE *argv)
|
2009-10-29 07:55:10 +03:00
|
|
|
{
|
2009-11-02 08:52:55 +03:00
|
|
|
return make_exception(argc, argv, TRUE);
|
2009-10-29 07:55:10 +03:00
|
|
|
}
|
|
|
|
|
2017-07-22 15:26:19 +03:00
|
|
|
/*! \private
|
|
|
|
*/
|
2021-03-18 20:03:56 +03:00
|
|
|
static void
|
2013-12-31 18:49:16 +04:00
|
|
|
rb_raise_jump(VALUE mesg, VALUE cause)
|
2000-05-18 08:32:13 +04:00
|
|
|
{
|
2017-10-29 16:19:14 +03:00
|
|
|
rb_execution_context_t *ec = GET_EC();
|
|
|
|
const rb_control_frame_t *cfp = ec->cfp;
|
* method.h: introduce rb_callable_method_entry_t to remove
rb_control_frame_t::klass.
[Bug #11278], [Bug #11279]
rb_method_entry_t data belong to modules/classes.
rb_method_entry_t::owner points defined module or class.
module M
def foo; end
end
In this case, owner is M.
rb_callable_method_entry_t data belong to only classes.
For modules, MRI creates corresponding T_ICLASS internally.
rb_callable_method_entry_t can also belong to T_ICLASS.
rb_callable_method_entry_t::defined_class points T_CLASS or
T_ICLASS.
rb_method_entry_t data for classes (not for modules) are also
rb_callable_method_entry_t data because it is completely same data.
In this case, rb_method_entry_t::owner == rb_method_entry_t::defined_class.
For example, there are classes C and D, and incldues M,
class C; include M; end
class D; include M; end
then, two T_ICLASS objects for C's super class and D's super class
will be created.
When C.new.foo is called, then M#foo is searcheed and
rb_callable_method_t data is used by VM to invoke M#foo.
rb_method_entry_t data is only one for M#foo.
However, rb_callable_method_entry_t data are two (and can be more).
It is proportional to the number of including (and prepending)
classes (the number of T_ICLASS which point to the module).
Now, created rb_callable_method_entry_t are collected when
the original module M was modified. We can think it is a cache.
We need to select what kind of method entry data is needed.
To operate definition, then you need to use rb_method_entry_t.
You can access them by the following functions.
* rb_method_entry(VALUE klass, ID id);
* rb_method_entry_with_refinements(VALUE klass, ID id);
* rb_method_entry_without_refinements(VALUE klass, ID id);
* rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me);
To invoke methods, then you need to use rb_callable_method_entry_t
which you can get by the following APIs corresponding to the
above listed functions.
* rb_callable_method_entry(VALUE klass, ID id);
* rb_callable_method_entry_with_refinements(VALUE klass, ID id);
* rb_callable_method_entry_without_refinements(VALUE klass, ID id);
* rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me);
VM pushes rb_callable_method_entry_t, so that rb_vm_frame_method_entry()
returns rb_callable_method_entry_t.
You can check a super class of current method by
rb_callable_method_entry_t::defined_class.
* method.h: renamed from rb_method_entry_t::klass to
rb_method_entry_t::owner.
* internal.h: add rb_classext_struct::callable_m_tbl to cache
rb_callable_method_entry_t data.
We need to consider abotu this field again because it is only
active for T_ICLASS.
* class.c (method_entry_i): ditto.
* class.c (rb_define_attr): rb_method_entry() does not takes
defiend_class_ptr.
* gc.c (mark_method_entry): mark RCLASS_CALLABLE_M_TBL() for T_ICLASS.
* cont.c (fiber_init): rb_control_frame_t::klass is removed.
* proc.c: fix `struct METHOD' data structure because
rb_callable_method_t has all information.
* vm_core.h: remove several fields.
* rb_control_frame_t::klass.
* rb_block_t::klass.
And catch up changes.
* eval.c: catch up changes.
* gc.c: ditto.
* insns.def: ditto.
* vm.c: ditto.
* vm_args.c: ditto.
* vm_backtrace.c: ditto.
* vm_dump.c: ditto.
* vm_eval.c: ditto.
* vm_insnhelper.c: ditto.
* vm_method.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-07-03 14:24:50 +03:00
|
|
|
const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
|
|
|
|
VALUE klass = me->owner;
|
2010-01-24 16:52:32 +03:00
|
|
|
VALUE self = cfp->self;
|
2015-06-02 07:20:30 +03:00
|
|
|
ID mid = me->called_id;
|
2010-01-24 16:52:32 +03:00
|
|
|
|
2017-10-29 16:19:14 +03:00
|
|
|
rb_vm_pop_frame(ec);
|
|
|
|
EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, self, me->def->original_id, mid, klass, Qnil);
|
2013-12-11 07:39:52 +04:00
|
|
|
|
2017-10-29 16:19:14 +03:00
|
|
|
rb_longjmp(ec, TAG_RAISE, mesg, cause);
|
2000-05-18 08:32:13 +04:00
|
|
|
}
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
void
|
2007-12-24 12:25:27 +03:00
|
|
|
rb_jump_tag(int tag)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2015-07-19 03:25:45 +03:00
|
|
|
if (UNLIKELY(tag < TAG_RETURN || tag > TAG_FATAL)) {
|
|
|
|
unknown_longjmp_status(tag);
|
|
|
|
}
|
2017-12-06 06:16:08 +03:00
|
|
|
EC_JUMP_TAG(GET_EC(), tag);
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
int
|
2007-12-24 12:25:27 +03:00
|
|
|
rb_block_given_p(void)
|
2006-12-31 18:02:22 +03:00
|
|
|
{
|
2017-10-29 18:13:49 +03:00
|
|
|
if (rb_vm_frame_block_handler(GET_EC()->cfp) == VM_BLOCK_HANDLER_NONE) {
|
2016-07-28 14:02:30 +03:00
|
|
|
return FALSE;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
else {
|
2016-07-28 14:02:30 +03:00
|
|
|
return TRUE;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
2003-10-10 02:50:57 +04:00
|
|
|
|
2019-09-03 21:32:02 +03:00
|
|
|
int rb_vm_cframe_keyword_p(const rb_control_frame_t *cfp);
|
|
|
|
|
|
|
|
int
|
|
|
|
rb_keyword_given_p(void)
|
|
|
|
{
|
|
|
|
return rb_vm_cframe_keyword_p(GET_EC()->cfp);
|
|
|
|
}
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
VALUE rb_eThreadError;
|
|
|
|
|
|
|
|
void
|
* cont.c (rb_fiber_current), dln.c (dln_print_undef, dln_undefined),
eval.c (rb_iterator_p, rb_need_block), load.c: (Init_load), ruby.c
(uscore_get, rb_f_chop), st.c (stat_col), signal.c
(rb_signal_buff_size, ruby_sig_finalize), thread.c
(rb_thread_sleep_forever, rb_thread_sleep_deadly, rb_thread_alone):
protoized.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21929 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-02-01 15:51:44 +03:00
|
|
|
rb_need_block(void)
|
2006-12-31 18:02:22 +03:00
|
|
|
{
|
|
|
|
if (!rb_block_given_p()) {
|
* vm.c: add a prefix "rb_" to exposed functions
vm_get_ruby_level_next_cfp(), rb_vm_make_env_object(),
vm_stack_to_heap(), vm_make_proc(), vm_invoke_proc(),
vm_get_sourceline(), vm_cref(), vm_localjump_error(),
vm_make_jump_tag_but_local_jump(), vm_jump_tag_but_local_jump().
This changes may affect only core because most of renamed functions
require a pointer of not-exposed struct such as rb_thread_t or NODE.
In short, they are core functions.
* cont.c, eval.c, eval_intern.h, load.c, proc.c, thread.c,
vm_core.h, vm_dump.c, vm_eval.c, vm_exec.c, vm_insnhelper.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21659 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-01-19 05:38:11 +03:00
|
|
|
rb_vm_localjump_error("no block given", Qnil, 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2000-01-05 07:41:21 +03:00
|
|
|
VALUE
|
2019-08-26 08:51:00 +03:00
|
|
|
rb_rescue2(VALUE (* b_proc) (VALUE), VALUE data1,
|
|
|
|
VALUE (* r_proc) (VALUE, VALUE), VALUE data2, ...)
|
2019-09-05 17:50:45 +03:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, data2);
|
2019-09-07 03:18:38 +03:00
|
|
|
VALUE ret = rb_vrescue2(b_proc, data1, r_proc, data2, ap);
|
2019-09-05 17:50:45 +03:00
|
|
|
va_end(ap);
|
2019-09-07 03:18:38 +03:00
|
|
|
return ret;
|
2019-09-05 17:50:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1,
|
|
|
|
VALUE (* r_proc) (VALUE, VALUE), VALUE data2,
|
|
|
|
va_list args)
|
2000-01-05 07:41:21 +03:00
|
|
|
{
|
2017-06-23 10:25:52 +03:00
|
|
|
enum ruby_tag_type state;
|
2017-10-28 13:43:30 +03:00
|
|
|
rb_execution_context_t * volatile ec = GET_EC();
|
|
|
|
rb_control_frame_t *volatile cfp = ec->cfp;
|
2013-12-13 20:32:00 +04:00
|
|
|
volatile VALUE result = Qfalse;
|
2017-10-28 13:43:30 +03:00
|
|
|
volatile VALUE e_info = ec->errinfo;
|
2000-01-05 07:41:21 +03:00
|
|
|
|
2017-10-28 13:43:30 +03:00
|
|
|
EC_PUSH_TAG(ec);
|
2017-10-26 14:02:13 +03:00
|
|
|
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
|
2006-12-31 18:02:22 +03:00
|
|
|
retry_entry:
|
|
|
|
result = (*b_proc) (data1);
|
2000-01-05 07:41:21 +03:00
|
|
|
}
|
2013-12-13 20:32:00 +04:00
|
|
|
else if (result) {
|
|
|
|
/* escape from r_proc */
|
|
|
|
if (state == TAG_RETRY) {
|
2021-02-08 18:39:58 +03:00
|
|
|
state = TAG_NONE;
|
2017-10-28 13:43:30 +03:00
|
|
|
ec->errinfo = Qnil;
|
2013-12-13 20:32:00 +04:00
|
|
|
result = Qfalse;
|
|
|
|
goto retry_entry;
|
|
|
|
}
|
|
|
|
}
|
2007-04-12 12:13:20 +04:00
|
|
|
else {
|
2017-10-28 13:43:30 +03:00
|
|
|
rb_vm_rewind_cfp(ec, cfp);
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2007-04-12 12:13:20 +04:00
|
|
|
if (state == TAG_RAISE) {
|
2009-07-18 12:05:32 +04:00
|
|
|
int handle = FALSE;
|
2007-04-12 12:13:20 +04:00
|
|
|
VALUE eclass;
|
2021-02-08 18:42:12 +03:00
|
|
|
va_list ap;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2021-02-09 04:08:30 +03:00
|
|
|
result = Qnil;
|
2021-02-08 18:42:12 +03:00
|
|
|
/* reuses args when raised again after retrying in r_proc */
|
|
|
|
va_copy(ap, args);
|
|
|
|
while ((eclass = va_arg(ap, VALUE)) != 0) {
|
2017-10-28 13:43:30 +03:00
|
|
|
if (rb_obj_is_kind_of(ec->errinfo, eclass)) {
|
2009-07-18 12:05:32 +04:00
|
|
|
handle = TRUE;
|
2007-04-12 12:13:20 +04:00
|
|
|
break;
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
2007-04-12 12:13:20 +04:00
|
|
|
}
|
2021-02-08 18:42:12 +03:00
|
|
|
va_end(ap);
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2007-04-12 12:13:20 +04:00
|
|
|
if (handle) {
|
2021-02-08 18:39:58 +03:00
|
|
|
state = TAG_NONE;
|
2007-04-12 12:13:20 +04:00
|
|
|
if (r_proc) {
|
2017-10-28 13:43:30 +03:00
|
|
|
result = (*r_proc) (data2, ec->errinfo);
|
2007-04-12 12:13:20 +04:00
|
|
|
}
|
2017-10-28 13:43:30 +03:00
|
|
|
ec->errinfo = e_info;
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-10-26 14:02:13 +03:00
|
|
|
EC_POP_TAG();
|
2006-12-31 18:02:22 +03:00
|
|
|
if (state)
|
2017-10-28 13:43:30 +03:00
|
|
|
EC_JUMP_TAG(ec, state);
|
2003-12-28 03:02:59 +03:00
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
return result;
|
|
|
|
}
|
2003-12-28 03:02:59 +03:00
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
VALUE
|
2019-08-26 08:51:00 +03:00
|
|
|
rb_rescue(VALUE (* b_proc)(VALUE), VALUE data1,
|
|
|
|
VALUE (* r_proc)(VALUE, VALUE), VALUE data2)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2006-12-31 18:02:22 +03:00
|
|
|
return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError,
|
|
|
|
(VALUE)0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
VALUE
|
2017-06-23 10:25:52 +03:00
|
|
|
rb_protect(VALUE (* proc) (VALUE), VALUE data, int *pstate)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2009-04-19 09:43:20 +04:00
|
|
|
volatile VALUE result = Qnil;
|
2017-06-23 10:25:52 +03:00
|
|
|
volatile enum ruby_tag_type state;
|
2017-10-28 13:43:30 +03:00
|
|
|
rb_execution_context_t * volatile ec = GET_EC();
|
|
|
|
rb_control_frame_t *volatile cfp = ec->cfp;
|
2007-07-20 11:11:35 +04:00
|
|
|
|
2017-10-28 13:43:30 +03:00
|
|
|
EC_PUSH_TAG(ec);
|
2017-10-26 14:02:13 +03:00
|
|
|
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
|
2017-10-28 13:43:30 +03:00
|
|
|
SAVE_ROOT_JMPBUF(rb_ec_thread_ptr(ec), result = (*proc) (data));
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
2013-11-05 11:56:49 +04:00
|
|
|
else {
|
2017-10-28 13:43:30 +03:00
|
|
|
rb_vm_rewind_cfp(ec, cfp);
|
2013-11-05 11:56:49 +04:00
|
|
|
}
|
2017-10-26 14:02:13 +03:00
|
|
|
EC_POP_TAG();
|
2007-04-12 11:08:28 +04:00
|
|
|
|
2017-06-23 10:25:52 +03:00
|
|
|
if (pstate != NULL) *pstate = state;
|
2006-12-31 18:02:22 +03:00
|
|
|
return result;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
VALUE
|
2019-08-26 09:20:15 +03:00
|
|
|
rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2)
|
2006-09-24 01:29:47 +04:00
|
|
|
{
|
2006-12-31 18:02:22 +03:00
|
|
|
int state;
|
|
|
|
volatile VALUE result = Qnil;
|
2017-02-03 09:23:34 +03:00
|
|
|
VALUE errinfo;
|
2017-10-29 18:13:49 +03:00
|
|
|
rb_execution_context_t * volatile ec = GET_EC();
|
2013-11-15 21:15:31 +04:00
|
|
|
rb_ensure_list_t ensure_list;
|
|
|
|
ensure_list.entry.marker = 0;
|
|
|
|
ensure_list.entry.e_proc = e_proc;
|
|
|
|
ensure_list.entry.data2 = data2;
|
2017-10-29 18:13:49 +03:00
|
|
|
ensure_list.next = ec->ensure_list;
|
|
|
|
ec->ensure_list = &ensure_list;
|
|
|
|
EC_PUSH_TAG(ec);
|
2017-12-06 06:16:08 +03:00
|
|
|
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
|
2006-12-31 18:02:22 +03:00
|
|
|
result = (*b_proc) (data1);
|
|
|
|
}
|
2017-10-26 14:02:13 +03:00
|
|
|
EC_POP_TAG();
|
2017-10-29 18:13:49 +03:00
|
|
|
errinfo = ec->errinfo;
|
2017-02-03 09:23:34 +03:00
|
|
|
if (!NIL_P(errinfo) && !RB_TYPE_P(errinfo, T_OBJECT)) {
|
2017-10-29 18:13:49 +03:00
|
|
|
ec->errinfo = Qnil;
|
2017-02-03 09:23:34 +03:00
|
|
|
}
|
2017-10-29 18:13:49 +03:00
|
|
|
ec->ensure_list=ensure_list.next;
|
2013-11-15 21:15:31 +04:00
|
|
|
(*ensure_list.entry.e_proc)(ensure_list.entry.data2);
|
2017-10-29 18:13:49 +03:00
|
|
|
ec->errinfo = errinfo;
|
2006-12-31 18:02:22 +03:00
|
|
|
if (state)
|
2017-10-29 18:13:49 +03:00
|
|
|
EC_JUMP_TAG(ec, state);
|
2006-12-31 18:02:22 +03:00
|
|
|
return result;
|
2006-09-24 01:29:47 +04:00
|
|
|
}
|
|
|
|
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 21:50:17 +04:00
|
|
|
static ID
|
2017-10-26 11:41:34 +03:00
|
|
|
frame_func_id(const rb_control_frame_t *cfp)
|
2006-09-24 01:29:47 +04:00
|
|
|
{
|
* method.h: introduce rb_callable_method_entry_t to remove
rb_control_frame_t::klass.
[Bug #11278], [Bug #11279]
rb_method_entry_t data belong to modules/classes.
rb_method_entry_t::owner points defined module or class.
module M
def foo; end
end
In this case, owner is M.
rb_callable_method_entry_t data belong to only classes.
For modules, MRI creates corresponding T_ICLASS internally.
rb_callable_method_entry_t can also belong to T_ICLASS.
rb_callable_method_entry_t::defined_class points T_CLASS or
T_ICLASS.
rb_method_entry_t data for classes (not for modules) are also
rb_callable_method_entry_t data because it is completely same data.
In this case, rb_method_entry_t::owner == rb_method_entry_t::defined_class.
For example, there are classes C and D, and incldues M,
class C; include M; end
class D; include M; end
then, two T_ICLASS objects for C's super class and D's super class
will be created.
When C.new.foo is called, then M#foo is searcheed and
rb_callable_method_t data is used by VM to invoke M#foo.
rb_method_entry_t data is only one for M#foo.
However, rb_callable_method_entry_t data are two (and can be more).
It is proportional to the number of including (and prepending)
classes (the number of T_ICLASS which point to the module).
Now, created rb_callable_method_entry_t are collected when
the original module M was modified. We can think it is a cache.
We need to select what kind of method entry data is needed.
To operate definition, then you need to use rb_method_entry_t.
You can access them by the following functions.
* rb_method_entry(VALUE klass, ID id);
* rb_method_entry_with_refinements(VALUE klass, ID id);
* rb_method_entry_without_refinements(VALUE klass, ID id);
* rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me);
To invoke methods, then you need to use rb_callable_method_entry_t
which you can get by the following APIs corresponding to the
above listed functions.
* rb_callable_method_entry(VALUE klass, ID id);
* rb_callable_method_entry_with_refinements(VALUE klass, ID id);
* rb_callable_method_entry_without_refinements(VALUE klass, ID id);
* rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me);
VM pushes rb_callable_method_entry_t, so that rb_vm_frame_method_entry()
returns rb_callable_method_entry_t.
You can check a super class of current method by
rb_callable_method_entry_t::defined_class.
* method.h: renamed from rb_method_entry_t::klass to
rb_method_entry_t::owner.
* internal.h: add rb_classext_struct::callable_m_tbl to cache
rb_callable_method_entry_t data.
We need to consider abotu this field again because it is only
active for T_ICLASS.
* class.c (method_entry_i): ditto.
* class.c (rb_define_attr): rb_method_entry() does not takes
defiend_class_ptr.
* gc.c (mark_method_entry): mark RCLASS_CALLABLE_M_TBL() for T_ICLASS.
* cont.c (fiber_init): rb_control_frame_t::klass is removed.
* proc.c: fix `struct METHOD' data structure because
rb_callable_method_t has all information.
* vm_core.h: remove several fields.
* rb_control_frame_t::klass.
* rb_block_t::klass.
And catch up changes.
* eval.c: catch up changes.
* gc.c: ditto.
* insns.def: ditto.
* vm.c: ditto.
* vm_args.c: ditto.
* vm_backtrace.c: ditto.
* vm_dump.c: ditto.
* vm_eval.c: ditto.
* vm_insnhelper.c: ditto.
* vm_method.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-07-03 14:24:50 +03:00
|
|
|
const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
|
2015-06-02 07:20:30 +03:00
|
|
|
|
|
|
|
if (me) {
|
|
|
|
return me->def->original_id;
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 21:50:17 +04:00
|
|
|
}
|
2015-07-06 22:08:05 +03:00
|
|
|
else {
|
|
|
|
return 0;
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2012-07-04 06:11:37 +04:00
|
|
|
static ID
|
|
|
|
frame_called_id(rb_control_frame_t *cfp)
|
2003-12-13 12:13:39 +03:00
|
|
|
{
|
* method.h: introduce rb_callable_method_entry_t to remove
rb_control_frame_t::klass.
[Bug #11278], [Bug #11279]
rb_method_entry_t data belong to modules/classes.
rb_method_entry_t::owner points defined module or class.
module M
def foo; end
end
In this case, owner is M.
rb_callable_method_entry_t data belong to only classes.
For modules, MRI creates corresponding T_ICLASS internally.
rb_callable_method_entry_t can also belong to T_ICLASS.
rb_callable_method_entry_t::defined_class points T_CLASS or
T_ICLASS.
rb_method_entry_t data for classes (not for modules) are also
rb_callable_method_entry_t data because it is completely same data.
In this case, rb_method_entry_t::owner == rb_method_entry_t::defined_class.
For example, there are classes C and D, and incldues M,
class C; include M; end
class D; include M; end
then, two T_ICLASS objects for C's super class and D's super class
will be created.
When C.new.foo is called, then M#foo is searcheed and
rb_callable_method_t data is used by VM to invoke M#foo.
rb_method_entry_t data is only one for M#foo.
However, rb_callable_method_entry_t data are two (and can be more).
It is proportional to the number of including (and prepending)
classes (the number of T_ICLASS which point to the module).
Now, created rb_callable_method_entry_t are collected when
the original module M was modified. We can think it is a cache.
We need to select what kind of method entry data is needed.
To operate definition, then you need to use rb_method_entry_t.
You can access them by the following functions.
* rb_method_entry(VALUE klass, ID id);
* rb_method_entry_with_refinements(VALUE klass, ID id);
* rb_method_entry_without_refinements(VALUE klass, ID id);
* rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me);
To invoke methods, then you need to use rb_callable_method_entry_t
which you can get by the following APIs corresponding to the
above listed functions.
* rb_callable_method_entry(VALUE klass, ID id);
* rb_callable_method_entry_with_refinements(VALUE klass, ID id);
* rb_callable_method_entry_without_refinements(VALUE klass, ID id);
* rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me);
VM pushes rb_callable_method_entry_t, so that rb_vm_frame_method_entry()
returns rb_callable_method_entry_t.
You can check a super class of current method by
rb_callable_method_entry_t::defined_class.
* method.h: renamed from rb_method_entry_t::klass to
rb_method_entry_t::owner.
* internal.h: add rb_classext_struct::callable_m_tbl to cache
rb_callable_method_entry_t data.
We need to consider abotu this field again because it is only
active for T_ICLASS.
* class.c (method_entry_i): ditto.
* class.c (rb_define_attr): rb_method_entry() does not takes
defiend_class_ptr.
* gc.c (mark_method_entry): mark RCLASS_CALLABLE_M_TBL() for T_ICLASS.
* cont.c (fiber_init): rb_control_frame_t::klass is removed.
* proc.c: fix `struct METHOD' data structure because
rb_callable_method_t has all information.
* vm_core.h: remove several fields.
* rb_control_frame_t::klass.
* rb_block_t::klass.
And catch up changes.
* eval.c: catch up changes.
* gc.c: ditto.
* insns.def: ditto.
* vm.c: ditto.
* vm_args.c: ditto.
* vm_backtrace.c: ditto.
* vm_dump.c: ditto.
* vm_eval.c: ditto.
* vm_insnhelper.c: ditto.
* vm_method.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-07-03 14:24:50 +03:00
|
|
|
const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
|
2015-06-02 07:20:30 +03:00
|
|
|
|
|
|
|
if (me) {
|
|
|
|
return me->called_id;
|
2012-07-04 06:11:37 +04:00
|
|
|
}
|
2015-07-06 22:08:05 +03:00
|
|
|
else {
|
|
|
|
return 0;
|
2012-07-04 06:11:37 +04:00
|
|
|
}
|
2003-12-13 12:13:39 +03:00
|
|
|
}
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
ID
|
2012-07-04 06:11:37 +04:00
|
|
|
rb_frame_this_func(void)
|
2008-12-27 10:22:01 +03:00
|
|
|
{
|
2017-10-26 17:44:09 +03:00
|
|
|
return frame_func_id(GET_EC()->cfp);
|
2008-12-27 10:22:01 +03:00
|
|
|
}
|
|
|
|
|
2013-05-25 06:24:33 +04:00
|
|
|
ID
|
|
|
|
rb_frame_callee(void)
|
|
|
|
{
|
2017-10-26 17:44:09 +03:00
|
|
|
return frame_called_id(GET_EC()->cfp);
|
2013-05-25 06:24:33 +04:00
|
|
|
}
|
|
|
|
|
2012-07-04 06:11:37 +04:00
|
|
|
static rb_control_frame_t *
|
2017-10-29 18:13:49 +03:00
|
|
|
previous_frame(const rb_execution_context_t *ec)
|
2003-12-13 12:13:39 +03:00
|
|
|
{
|
2017-10-29 18:13:49 +03:00
|
|
|
rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp);
|
2007-02-04 22:12:52 +03:00
|
|
|
/* check if prev_cfp can be accessible */
|
2017-10-29 18:13:49 +03:00
|
|
|
if ((void *)(ec->vm_stack + ec->vm_stack_size) == (void *)(prev_cfp)) {
|
2007-02-04 22:12:52 +03:00
|
|
|
return 0;
|
|
|
|
}
|
2012-07-04 06:11:37 +04:00
|
|
|
return prev_cfp;
|
|
|
|
}
|
|
|
|
|
2013-05-25 06:24:33 +04:00
|
|
|
static ID
|
|
|
|
prev_frame_callee(void)
|
2012-07-04 06:11:37 +04:00
|
|
|
{
|
2017-10-29 18:13:49 +03:00
|
|
|
rb_control_frame_t *prev_cfp = previous_frame(GET_EC());
|
2012-07-04 06:11:37 +04:00
|
|
|
if (!prev_cfp) return 0;
|
|
|
|
return frame_called_id(prev_cfp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ID
|
2013-05-25 06:24:33 +04:00
|
|
|
prev_frame_func(void)
|
2012-07-04 06:11:37 +04:00
|
|
|
{
|
2017-10-29 18:13:49 +03:00
|
|
|
rb_control_frame_t *prev_cfp = previous_frame(GET_EC());
|
2012-07-04 06:11:37 +04:00
|
|
|
if (!prev_cfp) return 0;
|
2007-02-04 22:12:52 +03:00
|
|
|
return frame_func_id(prev_cfp);
|
2003-12-13 12:13:39 +03:00
|
|
|
}
|
|
|
|
|
2017-07-22 15:26:19 +03:00
|
|
|
/*!
|
|
|
|
* \private
|
|
|
|
* Returns the ID of the last method in the call stack.
|
|
|
|
* \sa rb_frame_this_func
|
|
|
|
* \ingroup defmethod
|
|
|
|
*/
|
2014-12-09 04:16:27 +03:00
|
|
|
ID
|
|
|
|
rb_frame_last_func(void)
|
|
|
|
{
|
2017-10-26 11:41:34 +03:00
|
|
|
const rb_execution_context_t *ec = GET_EC();
|
|
|
|
const rb_control_frame_t *cfp = ec->cfp;
|
2014-12-09 04:16:27 +03:00
|
|
|
ID mid;
|
|
|
|
|
|
|
|
while (!(mid = frame_func_id(cfp)) &&
|
|
|
|
(cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp),
|
2017-10-26 11:41:34 +03:00
|
|
|
!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)));
|
2014-12-09 04:16:27 +03:00
|
|
|
return mid;
|
|
|
|
}
|
|
|
|
|
2003-12-28 03:02:59 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* append_features(mod) -> mod
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2006-12-31 18:02:22 +03:00
|
|
|
* When this module is included in another, Ruby calls
|
2019-03-22 14:04:59 +03:00
|
|
|
* #append_features in this module, passing it the receiving module
|
|
|
|
* in _mod_. Ruby's default implementation is to add the constants,
|
|
|
|
* methods, and module variables of this module to _mod_ if this
|
|
|
|
* module has not already been added to _mod_ or one of its
|
|
|
|
* ancestors. See also Module#include.
|
2003-12-28 03:02:59 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-31 18:02:22 +03:00
|
|
|
rb_mod_append_features(VALUE module, VALUE include)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2013-04-04 12:23:10 +04:00
|
|
|
if (!CLASS_OR_MODULE_P(include)) {
|
2006-12-31 18:02:22 +03:00
|
|
|
Check_Type(include, T_CLASS);
|
|
|
|
}
|
|
|
|
rb_include_module(include, module);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
return module;
|
|
|
|
}
|
2003-12-28 03:02:59 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* include(module, ...) -> self
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2019-03-22 14:04:59 +03:00
|
|
|
* Invokes Module.append_features on each parameter in reverse order.
|
2003-12-28 03:02:59 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-31 18:02:22 +03:00
|
|
|
rb_mod_include(int argc, VALUE *argv, VALUE module)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2006-12-31 18:02:22 +03:00
|
|
|
int i;
|
2012-09-27 06:36:36 +04:00
|
|
|
ID id_append_features, id_included;
|
|
|
|
|
|
|
|
CONST_ID(id_append_features, "append_features");
|
|
|
|
CONST_ID(id_included, "included");
|
1999-08-13 09:45:20 +04:00
|
|
|
|
2022-05-05 22:10:36 +03:00
|
|
|
if (BUILTIN_TYPE(module) == T_MODULE && FL_TEST(module, RMODULE_IS_REFINEMENT)) {
|
2021-12-26 17:17:14 +03:00
|
|
|
rb_raise(rb_eTypeError, "Refinement#include has been removed");
|
2021-10-21 10:21:08 +03:00
|
|
|
}
|
|
|
|
|
2016-11-06 08:42:53 +03:00
|
|
|
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
2021-12-27 22:38:12 +03:00
|
|
|
for (i = 0; i < argc; i++) {
|
2006-12-31 18:02:22 +03:00
|
|
|
Check_Type(argv[i], T_MODULE);
|
2021-12-27 22:38:12 +03:00
|
|
|
if (FL_TEST(argv[i], RMODULE_IS_REFINEMENT)) {
|
|
|
|
rb_raise(rb_eTypeError, "Cannot include refinement");
|
|
|
|
}
|
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
while (argc--) {
|
2012-09-27 06:36:36 +04:00
|
|
|
rb_funcall(argv[argc], id_append_features, 1, module);
|
|
|
|
rb_funcall(argv[argc], id_included, 1, module);
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
return module;
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
|
|
|
|
2012-06-27 11:48:50 +04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* prepend_features(mod) -> mod
|
|
|
|
*
|
|
|
|
* When this module is prepended in another, Ruby calls
|
2019-03-22 14:04:59 +03:00
|
|
|
* #prepend_features in this module, passing it the receiving module
|
|
|
|
* in _mod_. Ruby's default implementation is to overlay the
|
|
|
|
* constants, methods, and module variables of this module to _mod_
|
|
|
|
* if this module has not already been added to _mod_ or one of its
|
|
|
|
* ancestors. See also Module#prepend.
|
2012-06-27 11:48:50 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_prepend_features(VALUE module, VALUE prepend)
|
|
|
|
{
|
2013-04-04 12:23:10 +04:00
|
|
|
if (!CLASS_OR_MODULE_P(prepend)) {
|
2012-06-27 11:48:50 +04:00
|
|
|
Check_Type(prepend, T_CLASS);
|
|
|
|
}
|
|
|
|
rb_prepend_module(prepend, module);
|
|
|
|
|
|
|
|
return module;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* prepend(module, ...) -> self
|
|
|
|
*
|
2019-03-22 14:04:59 +03:00
|
|
|
* Invokes Module.prepend_features on each parameter in reverse order.
|
2012-06-27 11:48:50 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_prepend(int argc, VALUE *argv, VALUE module)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
ID id_prepend_features, id_prepended;
|
|
|
|
|
2022-05-05 22:10:36 +03:00
|
|
|
if (BUILTIN_TYPE(module) == T_MODULE && FL_TEST(module, RMODULE_IS_REFINEMENT)) {
|
2021-12-26 17:17:14 +03:00
|
|
|
rb_raise(rb_eTypeError, "Refinement#prepend has been removed");
|
2021-10-21 10:21:08 +03:00
|
|
|
}
|
|
|
|
|
2012-06-27 11:48:50 +04:00
|
|
|
CONST_ID(id_prepend_features, "prepend_features");
|
|
|
|
CONST_ID(id_prepended, "prepended");
|
2016-11-06 08:42:53 +03:00
|
|
|
|
|
|
|
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
2021-12-27 22:38:12 +03:00
|
|
|
for (i = 0; i < argc; i++) {
|
2012-06-27 11:48:50 +04:00
|
|
|
Check_Type(argv[i], T_MODULE);
|
2021-12-27 22:38:12 +03:00
|
|
|
if (FL_TEST(argv[i], RMODULE_IS_REFINEMENT)) {
|
|
|
|
rb_raise(rb_eTypeError, "Cannot prepend refinement");
|
|
|
|
}
|
|
|
|
}
|
2012-06-27 11:48:50 +04:00
|
|
|
while (argc--) {
|
|
|
|
rb_funcall(argv[argc], id_prepend_features, 1, module);
|
|
|
|
rb_funcall(argv[argc], id_prepended, 1, module);
|
|
|
|
}
|
|
|
|
return module;
|
|
|
|
}
|
|
|
|
|
2016-09-23 14:46:33 +03:00
|
|
|
static void
|
|
|
|
ensure_class_or_module(VALUE obj)
|
|
|
|
{
|
|
|
|
if (!RB_TYPE_P(obj, T_CLASS) && !RB_TYPE_P(obj, T_MODULE)) {
|
|
|
|
rb_raise(rb_eTypeError,
|
|
|
|
"wrong argument type %"PRIsVALUE" (expected Class or Module)",
|
|
|
|
rb_obj_class(obj));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-01 17:56:37 +04:00
|
|
|
static VALUE
|
2014-09-30 09:25:32 +04:00
|
|
|
hidden_identity_hash_new(void)
|
2012-10-01 17:56:37 +04:00
|
|
|
{
|
2015-08-10 04:07:57 +03:00
|
|
|
VALUE hash = rb_ident_hash_new();
|
2012-10-01 17:56:37 +04:00
|
|
|
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RBASIC_CLEAR_CLASS(hash); /* hide from ObjectSpace */
|
2012-10-01 17:56:37 +04:00
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
|
2017-12-03 03:39:26 +03:00
|
|
|
static VALUE
|
|
|
|
refinement_superclass(VALUE superclass)
|
|
|
|
{
|
|
|
|
if (RB_TYPE_P(superclass, T_MODULE)) {
|
|
|
|
/* FIXME: Should ancestors of superclass be used here? */
|
Ensure origins for all included, prepended, and refined modules
This fixes various issues when a module is included in or prepended
to a module or class, and then refined, or refined and then included
or prepended to a module or class.
Implement by renaming ensure_origin to rb_ensure_origin, making it
non-static, and calling it when refining a module.
Fix Module#initialize_copy to handle origins correctly. Previously,
Module#initialize_copy did not handle origins correctly. For example,
this code:
```ruby
module B; end
class A
def b; 2 end
prepend B
end
a = A.dup.new
class A
def b; 1 end
end
p a.b
```
Printed 1 instead of 2. This is because the super chain for
a.singleton_class was:
```
a.singleton_class
A.dup
B(iclass)
B(iclass origin)
A(origin) # not A.dup(origin)
```
The B iclasses would not be modified, so the includer entry would be
still be set to A and not A.dup.
This modifies things so that if the class/module has an origin,
all iclasses between the class/module and the origin are duplicated
and have the correct includer entry set, and the correct origin
is created.
This requires other changes to make sure all tests still pass:
* rb_undef_methods_from doesn't automatically handle classes with
origins, so pass it the origin for Comparable when undefing
methods in Complex. This fixed a failure in the Complex tests.
* When adding a method, the method cache was not cleared
correctly if klass has an origin. Clear the method cache for
the klass before switching to the origin of klass. This fixed
failures in the autoload tests related to overridding require,
without breaking the optimization tests. Also clear the method
cache for both the module and origin when removing a method.
* Module#include? is fixed to skip origin iclasses.
* Refinements are fixed to use the origin class of the module that
has an origin.
* RCLASS_REFINED_BY_ANY is removed as it was only used in a single
place and is no longer needed.
* Marshal#dump is fixed to skip iclass origins.
* rb_method_entry_make is fixed to handled overridden optimized
methods for modules that have origins.
Fixes [Bug #16852]
2020-05-24 06:16:27 +03:00
|
|
|
return rb_include_class_new(RCLASS_ORIGIN(superclass), rb_cBasicObject);
|
2017-12-03 03:39:26 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
return superclass;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-22 15:26:19 +03:00
|
|
|
/*!
|
|
|
|
* \private
|
|
|
|
*/
|
2021-03-18 20:03:56 +03:00
|
|
|
static void
|
2015-03-09 00:22:43 +03:00
|
|
|
rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module)
|
2012-08-02 15:34:19 +04:00
|
|
|
{
|
|
|
|
VALUE iclass, c, superclass = klass;
|
|
|
|
|
2016-09-23 14:46:33 +03:00
|
|
|
ensure_class_or_module(klass);
|
2012-08-02 15:34:19 +04:00
|
|
|
Check_Type(module, T_MODULE);
|
2015-03-08 22:50:37 +03:00
|
|
|
if (NIL_P(CREF_REFINEMENTS(cref))) {
|
2015-03-09 00:22:43 +03:00
|
|
|
CREF_REFINEMENTS_SET(cref, hidden_identity_hash_new());
|
2012-08-02 15:34:19 +04:00
|
|
|
}
|
|
|
|
else {
|
2015-03-08 22:50:37 +03:00
|
|
|
if (CREF_OMOD_SHARED(cref)) {
|
2015-03-09 00:22:43 +03:00
|
|
|
CREF_REFINEMENTS_SET(cref, rb_hash_dup(CREF_REFINEMENTS(cref)));
|
2015-03-08 22:50:37 +03:00
|
|
|
CREF_OMOD_SHARED_UNSET(cref);
|
2012-08-02 15:34:19 +04:00
|
|
|
}
|
2015-03-08 22:50:37 +03:00
|
|
|
if (!NIL_P(c = rb_hash_lookup(CREF_REFINEMENTS(cref), klass))) {
|
2012-08-02 15:34:19 +04:00
|
|
|
superclass = c;
|
2012-12-29 16:22:01 +04:00
|
|
|
while (c && RB_TYPE_P(c, T_ICLASS)) {
|
2012-08-02 15:34:19 +04:00
|
|
|
if (RBASIC(c)->klass == module) {
|
2012-10-08 18:02:46 +04:00
|
|
|
/* already used refinement */
|
2012-08-02 15:34:19 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
c = RCLASS_SUPER(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-12-03 03:39:26 +03:00
|
|
|
superclass = refinement_superclass(superclass);
|
2012-08-02 15:34:19 +04:00
|
|
|
c = iclass = rb_include_class_new(module, superclass);
|
2019-07-22 11:44:58 +03:00
|
|
|
RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass);
|
2013-06-23 00:48:35 +04:00
|
|
|
|
2020-08-11 01:19:17 +03:00
|
|
|
RCLASS_M_TBL(c) = RCLASS_M_TBL(module);
|
2013-06-23 00:48:35 +04:00
|
|
|
|
2012-08-02 15:34:19 +04:00
|
|
|
module = RCLASS_SUPER(module);
|
* fix the behavior when a module is included into a refinement.
This change is a little tricky, so it might be better to prohibit
module inclusion to refinements.
* include/ruby/ruby.h (RMODULE_INCLUDED_INTO_REFINEMENT): new flag
to represent that a module (iclass) is included into a refinement.
* class.c (include_modules_at): set RMODULE_INCLUDED_INTO_REFINEMENT
if klass is a refinement.
* eval.c (rb_mod_refine): set the superclass of a refinement to the
refined class for super.
* eval.c (rb_using_refinement): skip the above superclass (the
refined class) when creating iclasses for refinements. Otherwise,
`using Refinement1; using Refinement2' creates iclasses:
<Refinement2> -> <RefinedClass> -> <Refinement1> -> RefinedClass,
where <Module> is an iclass for Module, so RefinedClass is
searched before Refinement1. The correct iclasses should be
<Refinement2> -> <Refinement1> -> RefinedClass.
* vm_insnhelper.c (vm_search_normal_superclass): if klass is an
iclass for a refinement, use the refinement's superclass instead
of the iclass's superclass. Otherwise, multiple refinements are
searched by super. For example, if a refinement Refinement2
includes a module M (i.e., Refinement2 -> <M> -> RefinedClass,
and if refinements iclasses are <Refinement2> -> <M>' ->
<Refinement1> -> RefinedClass, then super in <Refinement2> should
use Refinement2's superclass <M> instead of <Refinement2>'s
superclass <M>'.
* vm_insnhelper.c (vm_search_super_method): do not raise a
NotImplementError if current_defind_class is a module included
into a refinement. Because of the change of
vm_search_normal_superclass(), the receiver might not be an
instance of the module('s iclass).
* test/ruby/test_refinement.rb: related test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38298 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-10 20:05:45 +04:00
|
|
|
while (module && module != klass) {
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
c = RCLASS_SET_SUPER(c, rb_include_class_new(module, RCLASS_SUPER(c)));
|
2019-07-22 11:44:58 +03:00
|
|
|
RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass);
|
|
|
|
module = RCLASS_SUPER(module);
|
2012-08-02 15:34:19 +04:00
|
|
|
}
|
2015-03-08 22:50:37 +03:00
|
|
|
rb_hash_aset(CREF_REFINEMENTS(cref), klass, iclass);
|
2012-08-02 15:34:19 +04:00
|
|
|
}
|
|
|
|
|
2012-11-01 09:45:28 +04:00
|
|
|
static int
|
|
|
|
using_refinement(VALUE klass, VALUE module, VALUE arg)
|
2012-08-02 15:34:19 +04:00
|
|
|
{
|
2015-03-09 00:22:43 +03:00
|
|
|
rb_cref_t *cref = (rb_cref_t *) arg;
|
2012-08-02 15:34:19 +04:00
|
|
|
|
2012-10-08 18:02:46 +04:00
|
|
|
rb_using_refinement(cref, klass, module);
|
2012-08-02 15:34:19 +04:00
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
2013-07-01 07:57:16 +04:00
|
|
|
static void
|
2015-03-09 00:22:43 +03:00
|
|
|
using_module_recursive(const rb_cref_t *cref, VALUE klass)
|
2012-08-02 15:34:19 +04:00
|
|
|
{
|
2012-10-08 18:02:46 +04:00
|
|
|
ID id_refinements;
|
2013-07-01 07:57:16 +04:00
|
|
|
VALUE super, module, refinements;
|
2012-08-02 15:34:19 +04:00
|
|
|
|
2013-07-01 07:57:16 +04:00
|
|
|
super = RCLASS_SUPER(klass);
|
|
|
|
if (super) {
|
|
|
|
using_module_recursive(cref, super);
|
|
|
|
}
|
|
|
|
switch (BUILTIN_TYPE(klass)) {
|
2013-12-13 07:53:18 +04:00
|
|
|
case T_MODULE:
|
2013-07-01 07:57:16 +04:00
|
|
|
module = klass;
|
|
|
|
break;
|
|
|
|
|
2013-12-13 07:53:18 +04:00
|
|
|
case T_ICLASS:
|
2013-07-01 07:57:16 +04:00
|
|
|
module = RBASIC(klass)->klass;
|
|
|
|
break;
|
|
|
|
|
2013-12-13 07:53:18 +04:00
|
|
|
default:
|
2013-07-01 07:57:16 +04:00
|
|
|
rb_raise(rb_eTypeError, "wrong argument type %s (expected Module)",
|
|
|
|
rb_obj_classname(klass));
|
|
|
|
break;
|
|
|
|
}
|
2012-10-08 18:02:46 +04:00
|
|
|
CONST_ID(id_refinements, "__refinements__");
|
|
|
|
refinements = rb_attr_get(module, id_refinements);
|
|
|
|
if (NIL_P(refinements)) return;
|
2012-11-01 09:45:28 +04:00
|
|
|
rb_hash_foreach(refinements, using_refinement, (VALUE) cref);
|
2012-08-02 15:34:19 +04:00
|
|
|
}
|
|
|
|
|
2017-07-22 15:26:19 +03:00
|
|
|
/*!
|
|
|
|
* \private
|
|
|
|
*/
|
2021-03-18 20:03:56 +03:00
|
|
|
static void
|
2015-03-09 00:22:43 +03:00
|
|
|
rb_using_module(const rb_cref_t *cref, VALUE module)
|
2013-07-01 07:57:16 +04:00
|
|
|
{
|
|
|
|
Check_Type(module, T_MODULE);
|
|
|
|
using_module_recursive(cref, module);
|
2023-07-31 10:17:55 +03:00
|
|
|
rb_clear_all_refinement_method_cache();
|
2013-07-01 07:57:16 +04:00
|
|
|
}
|
|
|
|
|
2022-01-05 11:47:29 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2023-12-15 00:01:48 +03:00
|
|
|
* target -> class_or_module
|
2022-01-05 11:47:29 +03:00
|
|
|
*
|
2023-07-14 09:13:14 +03:00
|
|
|
* Return the class or module refined by the receiver.
|
2023-12-15 00:01:48 +03:00
|
|
|
*
|
|
|
|
* module M
|
|
|
|
* refine String do
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* M.refinements[0].target # => String
|
2022-01-05 11:47:29 +03:00
|
|
|
*/
|
2013-09-09 09:17:17 +04:00
|
|
|
VALUE
|
|
|
|
rb_refinement_module_get_refined_class(VALUE module)
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 17:08:41 +04:00
|
|
|
{
|
|
|
|
ID id_refined_class;
|
|
|
|
|
|
|
|
CONST_ID(id_refined_class, "__refined_class__");
|
|
|
|
return rb_attr_get(module, id_refined_class);
|
|
|
|
}
|
|
|
|
|
2023-07-14 09:13:14 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* refined_class -> class
|
|
|
|
*
|
2023-12-15 00:01:48 +03:00
|
|
|
* Deprecated; prefer #target.
|
|
|
|
*
|
2023-07-14 09:13:14 +03:00
|
|
|
* Return the class refined by the receiver.
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
rb_refinement_refined_class(VALUE module)
|
|
|
|
{
|
|
|
|
rb_warn_deprecated_to_remove("3.4", "Refinement#refined_class", "Refinement#target");
|
|
|
|
return rb_refinement_module_get_refined_class(module);
|
|
|
|
}
|
|
|
|
|
2012-12-08 06:37:16 +04:00
|
|
|
static void
|
|
|
|
add_activated_refinement(VALUE activated_refinements,
|
|
|
|
VALUE klass, VALUE refinement)
|
|
|
|
{
|
|
|
|
VALUE iclass, c, superclass = klass;
|
|
|
|
|
|
|
|
if (!NIL_P(c = rb_hash_lookup(activated_refinements, klass))) {
|
|
|
|
superclass = c;
|
2012-12-29 16:22:01 +04:00
|
|
|
while (c && RB_TYPE_P(c, T_ICLASS)) {
|
2012-12-08 06:37:16 +04:00
|
|
|
if (RBASIC(c)->klass == refinement) {
|
|
|
|
/* already used refinement */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
c = RCLASS_SUPER(c);
|
|
|
|
}
|
|
|
|
}
|
2017-12-03 03:39:26 +03:00
|
|
|
superclass = refinement_superclass(superclass);
|
2012-12-08 06:37:16 +04:00
|
|
|
c = iclass = rb_include_class_new(refinement, superclass);
|
2019-07-22 11:44:58 +03:00
|
|
|
RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass);
|
2012-12-08 06:37:16 +04:00
|
|
|
refinement = RCLASS_SUPER(refinement);
|
2015-06-29 08:52:38 +03:00
|
|
|
while (refinement && refinement != klass) {
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
c = RCLASS_SET_SUPER(c, rb_include_class_new(refinement, RCLASS_SUPER(c)));
|
2019-07-22 11:44:58 +03:00
|
|
|
RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass);
|
2012-12-08 06:37:16 +04:00
|
|
|
refinement = RCLASS_SUPER(refinement);
|
|
|
|
}
|
|
|
|
rb_hash_aset(activated_refinements, klass, iclass);
|
|
|
|
}
|
|
|
|
|
2012-08-02 15:34:19 +04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-23 14:46:33 +03:00
|
|
|
* refine(mod) { block } -> module
|
2012-08-02 15:34:19 +04:00
|
|
|
*
|
2016-09-23 14:46:33 +03:00
|
|
|
* Refine <i>mod</i> in the receiver.
|
2012-08-02 18:38:48 +04:00
|
|
|
*
|
2016-09-23 14:46:33 +03:00
|
|
|
* Returns a module, where refined methods are defined.
|
2012-08-02 15:34:19 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_refine(VALUE module, VALUE klass)
|
|
|
|
{
|
2012-12-08 06:37:16 +04:00
|
|
|
VALUE refinement;
|
|
|
|
ID id_refinements, id_activated_refinements,
|
|
|
|
id_refined_class, id_defined_at;
|
|
|
|
VALUE refinements, activated_refinements;
|
2012-12-08 07:06:13 +04:00
|
|
|
rb_thread_t *th = GET_THREAD();
|
2017-10-26 11:32:49 +03:00
|
|
|
VALUE block_handler = rb_vm_frame_block_handler(th->ec->cfp);
|
2012-08-02 15:34:19 +04:00
|
|
|
|
2016-07-28 14:02:30 +03:00
|
|
|
if (block_handler == VM_BLOCK_HANDLER_NONE) {
|
|
|
|
rb_raise(rb_eArgError, "no block given");
|
2012-10-30 18:58:47 +04:00
|
|
|
}
|
2016-07-28 14:02:30 +03:00
|
|
|
if (vm_block_handler_type(block_handler) != block_handler_type_iseq) {
|
|
|
|
rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine");
|
2012-12-08 07:06:13 +04:00
|
|
|
}
|
2016-07-28 14:02:30 +03:00
|
|
|
|
2016-09-23 14:46:33 +03:00
|
|
|
ensure_class_or_module(klass);
|
2012-10-08 18:02:46 +04:00
|
|
|
CONST_ID(id_refinements, "__refinements__");
|
|
|
|
refinements = rb_attr_get(module, id_refinements);
|
|
|
|
if (NIL_P(refinements)) {
|
|
|
|
refinements = hidden_identity_hash_new();
|
|
|
|
rb_ivar_set(module, id_refinements, refinements);
|
2012-08-02 15:34:19 +04:00
|
|
|
}
|
2012-12-08 06:37:16 +04:00
|
|
|
CONST_ID(id_activated_refinements, "__activated_refinements__");
|
|
|
|
activated_refinements = rb_attr_get(module, id_activated_refinements);
|
|
|
|
if (NIL_P(activated_refinements)) {
|
|
|
|
activated_refinements = hidden_identity_hash_new();
|
|
|
|
rb_ivar_set(module, id_activated_refinements,
|
|
|
|
activated_refinements);
|
|
|
|
}
|
|
|
|
refinement = rb_hash_lookup(refinements, klass);
|
|
|
|
if (NIL_P(refinement)) {
|
2017-12-03 03:39:26 +03:00
|
|
|
VALUE superclass = refinement_superclass(klass);
|
2021-10-21 10:21:08 +03:00
|
|
|
refinement = rb_refinement_new();
|
2017-12-03 03:39:26 +03:00
|
|
|
RCLASS_SET_SUPER(refinement, superclass);
|
2022-05-05 22:10:36 +03:00
|
|
|
RUBY_ASSERT(BUILTIN_TYPE(refinement) == T_MODULE);
|
2012-12-08 06:37:16 +04:00
|
|
|
FL_SET(refinement, RMODULE_IS_REFINEMENT);
|
2012-08-02 15:34:19 +04:00
|
|
|
CONST_ID(id_refined_class, "__refined_class__");
|
2012-12-08 06:37:16 +04:00
|
|
|
rb_ivar_set(refinement, id_refined_class, klass);
|
2012-11-02 12:53:06 +04:00
|
|
|
CONST_ID(id_defined_at, "__defined_at__");
|
2012-12-08 06:37:16 +04:00
|
|
|
rb_ivar_set(refinement, id_defined_at, module);
|
|
|
|
rb_hash_aset(refinements, klass, refinement);
|
|
|
|
add_activated_refinement(activated_refinements, klass, refinement);
|
2012-08-02 15:34:19 +04:00
|
|
|
}
|
2012-12-08 06:37:16 +04:00
|
|
|
rb_yield_refine_block(refinement, activated_refinements);
|
|
|
|
return refinement;
|
2012-08-02 15:34:19 +04:00
|
|
|
}
|
|
|
|
|
2015-12-29 11:54:18 +03:00
|
|
|
static void
|
|
|
|
ignored_block(VALUE module, const char *klass)
|
|
|
|
{
|
|
|
|
const char *anon = "";
|
2017-09-30 15:26:23 +03:00
|
|
|
Check_Type(module, T_MODULE);
|
2015-12-29 11:54:18 +03:00
|
|
|
if (!RTEST(rb_search_class_path(module))) {
|
|
|
|
anon = ", maybe for Module.new";
|
|
|
|
}
|
|
|
|
rb_warn("%s""using doesn't call the given block""%s.", klass, anon);
|
|
|
|
}
|
|
|
|
|
2013-06-12 18:33:59 +04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* using(module) -> self
|
|
|
|
*
|
|
|
|
* Import class refinements from <i>module</i> into the current class or
|
|
|
|
* module definition.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
mod_using(VALUE self, VALUE module)
|
|
|
|
{
|
2017-10-29 18:13:49 +03:00
|
|
|
rb_control_frame_t *prev_cfp = previous_frame(GET_EC());
|
2013-06-12 18:33:59 +04:00
|
|
|
|
|
|
|
if (prev_frame_func()) {
|
|
|
|
rb_raise(rb_eRuntimeError,
|
|
|
|
"Module#using is not permitted in methods");
|
|
|
|
}
|
|
|
|
if (prev_cfp && prev_cfp->self != self) {
|
|
|
|
rb_raise(rb_eRuntimeError, "Module#using is not called on self");
|
|
|
|
}
|
2015-12-29 11:54:18 +03:00
|
|
|
if (rb_block_given_p()) {
|
|
|
|
ignored_block(module, "Module#");
|
|
|
|
}
|
2015-11-20 03:17:25 +03:00
|
|
|
rb_using_module(rb_vm_cref_replace_with_duplicated_cref(), module);
|
2013-06-12 18:33:59 +04:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2022-01-05 11:47:29 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* refinements -> array
|
|
|
|
*
|
|
|
|
* Returns an array of modules defined within the receiver.
|
|
|
|
*
|
|
|
|
* module A
|
|
|
|
* refine Integer do
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* refine String do
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* p A.refinements
|
|
|
|
*
|
|
|
|
* <em>produces:</em>
|
|
|
|
*
|
|
|
|
* [#<refinement:Integer@A>, #<refinement:String@A>]
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
mod_refinements(VALUE self)
|
|
|
|
{
|
|
|
|
ID id_refinements;
|
|
|
|
VALUE refinements;
|
|
|
|
|
|
|
|
CONST_ID(id_refinements, "__refinements__");
|
|
|
|
refinements = rb_attr_get(self, id_refinements);
|
|
|
|
if (NIL_P(refinements)) {
|
|
|
|
return rb_ary_new();
|
|
|
|
}
|
|
|
|
return rb_hash_values(refinements);
|
|
|
|
}
|
|
|
|
|
2016-09-07 19:15:45 +03:00
|
|
|
static int
|
2016-09-08 10:49:02 +03:00
|
|
|
used_modules_i(VALUE _, VALUE mod, VALUE ary)
|
2016-09-07 19:15:45 +03:00
|
|
|
{
|
|
|
|
ID id_defined_at;
|
|
|
|
CONST_ID(id_defined_at, "__defined_at__");
|
2022-05-05 22:10:36 +03:00
|
|
|
while (BUILTIN_TYPE(rb_class_of(mod)) == T_MODULE && FL_TEST(rb_class_of(mod), RMODULE_IS_REFINEMENT)) {
|
2016-09-07 19:15:45 +03:00
|
|
|
rb_ary_push(ary, rb_attr_get(rb_class_of(mod), id_defined_at));
|
|
|
|
mod = RCLASS_SUPER(mod);
|
|
|
|
}
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 10:49:02 +03:00
|
|
|
* used_modules -> array
|
2016-09-07 19:15:45 +03:00
|
|
|
*
|
2016-09-08 10:49:02 +03:00
|
|
|
* Returns an array of all modules used in the current scope. The ordering
|
|
|
|
* of modules in the resulting array is not defined.
|
2016-09-07 19:15:45 +03:00
|
|
|
*
|
|
|
|
* module A
|
|
|
|
* refine Object do
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* module B
|
|
|
|
* refine Object do
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* using A
|
|
|
|
* using B
|
2016-09-08 10:49:02 +03:00
|
|
|
* p Module.used_modules
|
2016-09-07 19:15:45 +03:00
|
|
|
*
|
|
|
|
* <em>produces:</em>
|
|
|
|
*
|
|
|
|
* [B, A]
|
|
|
|
*/
|
|
|
|
static VALUE
|
2019-08-29 05:47:20 +03:00
|
|
|
rb_mod_s_used_modules(VALUE _)
|
2016-09-07 19:15:45 +03:00
|
|
|
{
|
|
|
|
const rb_cref_t *cref = rb_vm_cref();
|
|
|
|
VALUE ary = rb_ary_new();
|
|
|
|
|
2019-09-27 04:20:56 +03:00
|
|
|
while (cref) {
|
|
|
|
if (!NIL_P(CREF_REFINEMENTS(cref))) {
|
2016-09-08 10:49:02 +03:00
|
|
|
rb_hash_foreach(CREF_REFINEMENTS(cref), used_modules_i, ary);
|
2016-09-07 19:15:45 +03:00
|
|
|
}
|
|
|
|
cref = CREF_NEXT(cref);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rb_funcall(ary, rb_intern("uniq"), 0);
|
|
|
|
}
|
|
|
|
|
2022-01-05 10:58:23 +03:00
|
|
|
static int
|
|
|
|
used_refinements_i(VALUE _, VALUE mod, VALUE ary)
|
|
|
|
{
|
2022-05-05 22:10:36 +03:00
|
|
|
while (BUILTIN_TYPE(rb_class_of(mod)) == T_MODULE && FL_TEST(rb_class_of(mod), RMODULE_IS_REFINEMENT)) {
|
2022-01-05 10:58:23 +03:00
|
|
|
rb_ary_push(ary, rb_class_of(mod));
|
|
|
|
mod = RCLASS_SUPER(mod);
|
|
|
|
}
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* used_refinements -> array
|
|
|
|
*
|
|
|
|
* Returns an array of all modules used in the current scope. The ordering
|
|
|
|
* of modules in the resulting array is not defined.
|
|
|
|
*
|
|
|
|
* module A
|
|
|
|
* refine Object do
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* module B
|
|
|
|
* refine Object do
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* using A
|
|
|
|
* using B
|
|
|
|
* p Module.used_refinements
|
|
|
|
*
|
|
|
|
* <em>produces:</em>
|
|
|
|
*
|
|
|
|
* [#<refinement:Object@B>, #<refinement:Object@A>]
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
rb_mod_s_used_refinements(VALUE _)
|
|
|
|
{
|
|
|
|
const rb_cref_t *cref = rb_vm_cref();
|
|
|
|
VALUE ary = rb_ary_new();
|
|
|
|
|
|
|
|
while (cref) {
|
|
|
|
if (!NIL_P(CREF_REFINEMENTS(cref))) {
|
|
|
|
rb_hash_foreach(CREF_REFINEMENTS(cref), used_refinements_i, ary);
|
|
|
|
}
|
|
|
|
cref = CREF_NEXT(cref);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
2021-10-21 10:21:08 +03:00
|
|
|
struct refinement_import_methods_arg {
|
|
|
|
rb_cref_t *cref;
|
|
|
|
VALUE refinement;
|
|
|
|
VALUE module;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* vm.c */
|
|
|
|
rb_cref_t *rb_vm_cref_dup_without_refinements(const rb_cref_t *cref);
|
|
|
|
|
|
|
|
static enum rb_id_table_iterator_result
|
|
|
|
refinement_import_methods_i(ID key, VALUE value, void *data)
|
|
|
|
{
|
|
|
|
const rb_method_entry_t *me = (const rb_method_entry_t *)value;
|
|
|
|
struct refinement_import_methods_arg *arg = (struct refinement_import_methods_arg *)data;
|
|
|
|
|
|
|
|
if (me->def->type != VM_METHOD_TYPE_ISEQ) {
|
2021-12-06 03:40:54 +03:00
|
|
|
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));
|
2021-10-21 10:21:08 +03:00
|
|
|
}
|
|
|
|
rb_cref_t *new_cref = rb_vm_cref_dup_without_refinements(me->def->body.iseq.cref);
|
|
|
|
CREF_REFINEMENTS_SET(new_cref, CREF_REFINEMENTS(arg->cref));
|
|
|
|
rb_add_method_iseq(arg->refinement, key, me->def->body.iseq.iseqptr, new_cref, METHOD_ENTRY_VISI(me));
|
|
|
|
return ID_TABLE_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2021-12-15 01:08:36 +03:00
|
|
|
* Note: docs for the method are in class.c
|
2021-10-21 10:21:08 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
refinement_import_methods(int argc, VALUE *argv, VALUE refinement)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct refinement_import_methods_arg arg;
|
|
|
|
|
|
|
|
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
|
|
Check_Type(argv[i], T_MODULE);
|
|
|
|
if (RCLASS_SUPER(argv[i])) {
|
|
|
|
rb_warn("%"PRIsVALUE" has ancestors, but Refinement#import_methods doesn't import their methods", rb_class_path(argv[i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
arg.cref = rb_vm_cref_replace_with_duplicated_cref();
|
|
|
|
arg.refinement = refinement;
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
|
|
arg.module = argv[i];
|
|
|
|
struct rb_id_table *m_tbl = RCLASS_M_TBL(argv[i]);
|
|
|
|
if (!m_tbl) continue;
|
|
|
|
rb_id_table_foreach(m_tbl, refinement_import_methods_i, &arg);
|
|
|
|
}
|
|
|
|
return refinement;
|
|
|
|
}
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
void
|
2014-03-20 08:03:11 +04:00
|
|
|
rb_obj_call_init(VALUE obj, int argc, const VALUE *argv)
|
1999-01-20 07:59:39 +03:00
|
|
|
{
|
2021-04-04 05:34:51 +03:00
|
|
|
rb_obj_call_init_kw(obj, argc, argv, RB_NO_KEYWORDS);
|
2019-09-14 11:49:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_obj_call_init_kw(VALUE obj, int argc, const VALUE *argv, int kw_splat)
|
|
|
|
{
|
|
|
|
PASS_PASSED_BLOCK_HANDLER();
|
|
|
|
rb_funcallv_kw(obj, idInitialize, argc, argv, kw_splat);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2005-06-12 20:56:06 +04:00
|
|
|
void
|
2006-12-31 18:02:22 +03:00
|
|
|
rb_extend_object(VALUE obj, VALUE module)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2006-12-31 18:02:22 +03:00
|
|
|
rb_include_module(rb_singleton_class(obj), module);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-28 03:02:59 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* extend_object(obj) -> obj
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2006-12-31 18:02:22 +03:00
|
|
|
* Extends the specified object by adding this module's constants and
|
|
|
|
* methods (which are added as singleton methods). This is the callback
|
2019-03-22 14:04:59 +03:00
|
|
|
* method used by Object#extend.
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2006-12-31 18:02:22 +03:00
|
|
|
* module Picky
|
|
|
|
* def Picky.extend_object(o)
|
|
|
|
* if String === o
|
|
|
|
* puts "Can't add Picky to a String"
|
|
|
|
* else
|
|
|
|
* puts "Picky added to #{o.class}"
|
|
|
|
* super
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
* (s = Array.new).extend Picky # Call Object.extend
|
|
|
|
* (s = "quick brown fox").extend Picky
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2003-12-28 03:02:59 +03:00
|
|
|
* <em>produces:</em>
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2006-12-31 18:02:22 +03:00
|
|
|
* Picky added to Array
|
|
|
|
* Can't add Picky to a String
|
2003-12-28 03:02:59 +03:00
|
|
|
*/
|
|
|
|
|
2000-10-11 10:29:16 +04:00
|
|
|
static VALUE
|
2006-12-31 18:02:22 +03:00
|
|
|
rb_mod_extend_object(VALUE mod, VALUE obj)
|
1999-01-20 07:59:39 +03:00
|
|
|
{
|
2006-12-31 18:02:22 +03:00
|
|
|
rb_extend_object(obj, mod);
|
|
|
|
return obj;
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
|
|
|
|
2003-12-28 03:02:59 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* obj.extend(module, ...) -> obj
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2006-12-31 18:02:22 +03:00
|
|
|
* Adds to _obj_ the instance methods from each module given as a
|
|
|
|
* parameter.
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2006-12-31 18:02:22 +03:00
|
|
|
* module Mod
|
|
|
|
* def hello
|
|
|
|
* "Hello from Mod.\n"
|
|
|
|
* end
|
|
|
|
* end
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2006-12-31 18:02:22 +03:00
|
|
|
* class Klass
|
|
|
|
* def hello
|
|
|
|
* "Hello from Klass.\n"
|
|
|
|
* end
|
|
|
|
* end
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2006-12-31 18:02:22 +03:00
|
|
|
* k = Klass.new
|
|
|
|
* k.hello #=> "Hello from Klass.\n"
|
|
|
|
* k.extend(Mod) #=> #<Klass:0x401b3bc8>
|
|
|
|
* k.hello #=> "Hello from Mod.\n"
|
2003-12-28 03:02:59 +03:00
|
|
|
*/
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
static VALUE
|
2006-12-31 18:02:22 +03:00
|
|
|
rb_obj_extend(int argc, VALUE *argv, VALUE obj)
|
1999-01-20 07:59:39 +03:00
|
|
|
{
|
2006-12-31 18:02:22 +03:00
|
|
|
int i;
|
2012-09-27 06:36:36 +04:00
|
|
|
ID id_extend_object, id_extended;
|
|
|
|
|
|
|
|
CONST_ID(id_extend_object, "extend_object");
|
|
|
|
CONST_ID(id_extended, "extended");
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2012-03-15 01:10:34 +04:00
|
|
|
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
2021-12-27 22:38:12 +03:00
|
|
|
for (i = 0; i < argc; i++) {
|
2006-12-31 18:02:22 +03:00
|
|
|
Check_Type(argv[i], T_MODULE);
|
2021-12-27 22:38:12 +03:00
|
|
|
if (FL_TEST(argv[i], RMODULE_IS_REFINEMENT)) {
|
|
|
|
rb_raise(rb_eTypeError, "Cannot extend object with refinement");
|
|
|
|
}
|
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
while (argc--) {
|
2012-09-27 06:36:36 +04:00
|
|
|
rb_funcall(argv[argc], id_extend_object, 1, obj);
|
|
|
|
rb_funcall(argv[argc], id_extended, 1, obj);
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
return obj;
|
2001-06-05 11:19:39 +04:00
|
|
|
}
|
|
|
|
|
2003-12-28 03:02:59 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* include(module, ...) -> self
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2019-03-22 14:04:59 +03:00
|
|
|
* Invokes Module.append_features on each parameter in turn.
|
|
|
|
* Effectively adds the methods and constants in each module to the
|
|
|
|
* receiver.
|
2003-12-28 03:02:59 +03:00
|
|
|
*/
|
|
|
|
|
2001-06-05 11:19:39 +04:00
|
|
|
static VALUE
|
2006-12-31 18:02:22 +03:00
|
|
|
top_include(int argc, VALUE *argv, VALUE self)
|
2001-06-05 11:19:39 +04:00
|
|
|
{
|
2007-02-25 19:29:26 +03:00
|
|
|
rb_thread_t *th = GET_THREAD();
|
|
|
|
|
|
|
|
if (th->top_wrapper) {
|
2012-11-02 03:23:23 +04:00
|
|
|
rb_warning("main.include in the wrapped load is effective only in wrapper module");
|
2007-02-25 19:29:26 +03:00
|
|
|
return rb_mod_include(argc, argv, th->top_wrapper);
|
2001-06-05 11:19:39 +04:00
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
return rb_mod_include(argc, argv, rb_cObject);
|
2001-06-05 11:19:39 +04:00
|
|
|
}
|
|
|
|
|
2012-08-02 15:34:19 +04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* using(module) -> self
|
|
|
|
*
|
|
|
|
* Import class refinements from <i>module</i> into the scope where
|
2019-03-22 14:04:59 +03:00
|
|
|
* #using is called.
|
2012-08-02 15:34:19 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
2012-11-11 10:14:16 +04:00
|
|
|
top_using(VALUE self, VALUE module)
|
2012-08-02 15:34:19 +04:00
|
|
|
{
|
2024-01-11 03:21:55 +03:00
|
|
|
const rb_cref_t *cref = CREF_NEXT(rb_vm_cref());
|
2017-10-29 18:13:49 +03:00
|
|
|
rb_control_frame_t *prev_cfp = previous_frame(GET_EC());
|
2022-08-09 16:22:23 +03:00
|
|
|
rb_thread_t *th = GET_THREAD();
|
2012-08-02 15:34:19 +04:00
|
|
|
|
2022-08-09 16:22:23 +03:00
|
|
|
if ((th->top_wrapper ? CREF_NEXT(cref) : cref) ||
|
|
|
|
(prev_cfp && rb_vm_frame_method_entry(prev_cfp))) {
|
2015-06-02 07:20:30 +03:00
|
|
|
rb_raise(rb_eRuntimeError, "main.using is permitted only at toplevel");
|
2012-12-08 17:35:12 +04:00
|
|
|
}
|
2015-12-29 11:54:18 +03:00
|
|
|
if (rb_block_given_p()) {
|
|
|
|
ignored_block(module, "main.");
|
|
|
|
}
|
2015-11-20 03:17:25 +03:00
|
|
|
rb_using_module(rb_vm_cref_replace_with_duplicated_cref(), module);
|
2012-08-02 15:34:19 +04:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2016-07-28 14:02:30 +03:00
|
|
|
static const VALUE *
|
2017-10-28 14:41:08 +03:00
|
|
|
errinfo_place(const rb_execution_context_t *ec)
|
2000-11-27 12:23:38 +03:00
|
|
|
{
|
2017-10-28 14:41:08 +03:00
|
|
|
const rb_control_frame_t *cfp = ec->cfp;
|
|
|
|
const rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(ec);
|
2000-11-27 12:23:38 +03:00
|
|
|
|
* blockinlining.c, compile.c, compile.h, error.c, eval.c,
eval_intern.h, eval_jump.h, eval_load.c, eval_method.h,
eval_safe.h, gc.c, insnhelper.h, insns.def, iseq.c, proc.c,
process.c, signal.c, thread.c, thread_pthread.ci, thread_win32.ci,
vm.c, vm.h, vm_dump.c, vm_evalbody.ci, vm_macro.def,
yarv.h, yarvcore.h, yarvcore.c: change type and macro names:
* yarv_*_t -> rb_*_t
* yarv_*_struct -> rb_*_struct
* yarv_tag -> rb_vm_tag
* YARV_* -> RUBY_VM_*
* proc.c, vm.c: move functions about env object creation
from proc.c to vm.c.
* proc.c, yarvcore.c: fix rb_cVM initialization place.
* inits.c: change Init_ISeq() order (after Init_VM).
* ruby.h, proc.c: change declaration place of rb_cEnv
from proc.c to ruby.c.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11651 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-06 22:00:03 +03:00
|
|
|
while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
|
2016-08-03 04:50:50 +03:00
|
|
|
if (VM_FRAME_RUBYFRAME_P(cfp)) {
|
2022-03-23 22:19:48 +03:00
|
|
|
if (ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_RESCUE) {
|
2016-07-28 14:02:30 +03:00
|
|
|
return &cfp->ep[VM_ENV_INDEX_LAST_LVAR];
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
2022-03-23 22:19:48 +03:00
|
|
|
else if (ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_ENSURE &&
|
2016-07-28 14:02:30 +03:00
|
|
|
!THROW_DATA_P(cfp->ep[VM_ENV_INDEX_LAST_LVAR]) &&
|
|
|
|
!FIXNUM_P(cfp->ep[VM_ENV_INDEX_LAST_LVAR])) {
|
|
|
|
return &cfp->ep[VM_ENV_INDEX_LAST_LVAR];
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
2000-11-27 12:23:38 +03:00
|
|
|
}
|
* blockinlining.c, compile.c, compile.h, error.c, eval.c,
eval_intern.h, eval_jump.h, eval_load.c, eval_method.h,
eval_safe.h, gc.c, insnhelper.h, insns.def, iseq.c, proc.c,
process.c, signal.c, thread.c, thread_pthread.ci, thread_win32.ci,
vm.c, vm.h, vm_dump.c, vm_evalbody.ci, vm_macro.def,
yarv.h, yarvcore.h, yarvcore.c: change type and macro names:
* yarv_*_t -> rb_*_t
* yarv_*_struct -> rb_*_struct
* yarv_tag -> rb_vm_tag
* YARV_* -> RUBY_VM_*
* proc.c, vm.c: move functions about env object creation
from proc.c to vm.c.
* proc.c, yarvcore.c: fix rb_cVM initialization place.
* inits.c: change Init_ISeq() order (after Init_VM).
* ruby.h, proc.c: change declaration place of rb_cEnv
from proc.c to ruby.c.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11651 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-06 22:00:03 +03:00
|
|
|
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
2000-11-27 12:23:38 +03:00
|
|
|
}
|
2007-08-18 08:26:48 +04:00
|
|
|
return 0;
|
2000-11-27 12:23:38 +03:00
|
|
|
}
|
|
|
|
|
2019-12-16 03:44:01 +03:00
|
|
|
VALUE
|
|
|
|
rb_ec_get_errinfo(const rb_execution_context_t *ec)
|
1999-01-20 07:59:39 +03:00
|
|
|
{
|
2017-10-28 14:41:08 +03:00
|
|
|
const VALUE *ptr = errinfo_place(ec);
|
2007-08-18 08:26:48 +04:00
|
|
|
if (ptr) {
|
|
|
|
return *ptr;
|
|
|
|
}
|
|
|
|
else {
|
2017-10-28 14:41:08 +03:00
|
|
|
return ec->errinfo;
|
2007-08-18 08:26:48 +04:00
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2009-10-10 09:13:08 +04:00
|
|
|
static VALUE
|
|
|
|
get_errinfo(void)
|
|
|
|
{
|
2017-10-28 14:41:08 +03:00
|
|
|
return get_ec_errinfo(GET_EC());
|
2009-10-10 09:13:08 +04:00
|
|
|
}
|
|
|
|
|
2007-08-18 08:26:48 +04:00
|
|
|
static VALUE
|
2019-08-27 05:16:52 +03:00
|
|
|
errinfo_getter(ID id, VALUE *_)
|
2006-12-31 18:02:22 +03:00
|
|
|
{
|
|
|
|
return get_errinfo();
|
|
|
|
}
|
2000-09-20 13:16:32 +04:00
|
|
|
|
2007-08-18 08:26:48 +04:00
|
|
|
VALUE
|
|
|
|
rb_errinfo(void)
|
|
|
|
{
|
2017-10-29 18:13:49 +03:00
|
|
|
return GET_EC()->errinfo;
|
2007-08-18 08:26:48 +04:00
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
void
|
|
|
|
rb_set_errinfo(VALUE err)
|
|
|
|
{
|
2007-08-18 08:26:48 +04:00
|
|
|
if (!NIL_P(err) && !rb_obj_is_kind_of(err, rb_eException)) {
|
|
|
|
rb_raise(rb_eTypeError, "assigning non-exception to $!");
|
|
|
|
}
|
2017-10-26 17:44:09 +03:00
|
|
|
GET_EC()->errinfo = err;
|
2007-08-18 08:26:48 +04:00
|
|
|
}
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
static VALUE
|
2019-08-27 05:16:52 +03:00
|
|
|
errat_getter(ID id, VALUE *_)
|
1999-01-20 07:59:39 +03:00
|
|
|
{
|
2006-12-31 18:02:22 +03:00
|
|
|
VALUE err = get_errinfo();
|
|
|
|
if (!NIL_P(err)) {
|
2016-11-13 08:25:53 +03:00
|
|
|
return rb_get_backtrace(err);
|
2000-08-02 13:22:27 +04:00
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
else {
|
|
|
|
return Qnil;
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
static void
|
|
|
|
errat_setter(VALUE val, ID id, VALUE *var)
|
2000-02-01 06:12:21 +03:00
|
|
|
{
|
2006-12-31 18:02:22 +03:00
|
|
|
VALUE err = get_errinfo();
|
|
|
|
if (NIL_P(err)) {
|
|
|
|
rb_raise(rb_eArgError, "$! not set");
|
|
|
|
}
|
|
|
|
set_backtrace(err, val);
|
2000-02-01 06:12:21 +03:00
|
|
|
}
|
|
|
|
|
2007-03-20 10:21:37 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* __method__ -> symbol
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
*
|
2013-05-25 06:24:33 +04:00
|
|
|
* Returns the name at the definition of the current method as a
|
|
|
|
* Symbol.
|
2007-03-20 10:21:37 +03:00
|
|
|
* If called outside of a method, it returns <code>nil</code>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
2019-08-28 12:19:11 +03:00
|
|
|
rb_f_method_name(VALUE _)
|
2007-03-20 10:21:37 +03:00
|
|
|
{
|
2013-05-25 06:24:33 +04:00
|
|
|
ID fname = prev_frame_func(); /* need *method* ID */
|
2007-03-20 10:21:37 +03:00
|
|
|
|
|
|
|
if (fname) {
|
|
|
|
return ID2SYM(fname);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-25 06:24:33 +04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* __callee__ -> symbol
|
|
|
|
*
|
|
|
|
* Returns the called name of the current method as a Symbol.
|
|
|
|
* If called outside of a method, it returns <code>nil</code>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2012-07-04 06:11:37 +04:00
|
|
|
static VALUE
|
2019-08-28 12:19:11 +03:00
|
|
|
rb_f_callee_name(VALUE _)
|
2012-07-04 06:11:37 +04:00
|
|
|
{
|
2013-05-25 06:24:33 +04:00
|
|
|
ID fname = prev_frame_callee(); /* need *callee* ID */
|
2012-07-04 06:11:37 +04:00
|
|
|
|
|
|
|
if (fname) {
|
|
|
|
return ID2SYM(fname);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-03 05:37:50 +04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* __dir__ -> string
|
|
|
|
*
|
2013-01-24 08:20:33 +04:00
|
|
|
* Returns the canonicalized absolute path of the directory of the file from
|
|
|
|
* which this method is called. It means symlinks in the path is resolved.
|
2012-11-03 05:37:50 +04:00
|
|
|
* If <code>__FILE__</code> is <code>nil</code>, it returns <code>nil</code>.
|
2013-01-24 10:55:24 +04:00
|
|
|
* The return value equals to <code>File.dirname(File.realpath(__FILE__))</code>.
|
2012-11-03 05:37:50 +04:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
static VALUE
|
2019-08-28 12:19:11 +03:00
|
|
|
f_current_dirname(VALUE _)
|
2012-11-03 05:37:50 +04:00
|
|
|
{
|
|
|
|
VALUE base = rb_current_realfilepath();
|
|
|
|
if (NIL_P(base)) {
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
base = rb_file_dirname(base);
|
|
|
|
return base;
|
|
|
|
}
|
|
|
|
|
2019-08-29 04:23:14 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* global_variables -> array
|
|
|
|
*
|
2020-03-07 00:03:58 +03:00
|
|
|
* Returns an array of the names of global variables. This includes
|
|
|
|
* special regexp global variables such as <tt>$~</tt> and <tt>$+</tt>,
|
|
|
|
* but does not include the numbered regexp global variables (<tt>$1</tt>,
|
|
|
|
* <tt>$2</tt>, etc.).
|
2019-08-29 04:23:14 +03:00
|
|
|
*
|
|
|
|
* global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr]
|
|
|
|
*/
|
|
|
|
|
2019-08-28 12:19:11 +03:00
|
|
|
static VALUE
|
|
|
|
f_global_variables(VALUE _)
|
|
|
|
{
|
|
|
|
return rb_f_global_variables();
|
|
|
|
}
|
|
|
|
|
2019-08-29 04:23:14 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* trace_var(symbol, cmd ) -> nil
|
|
|
|
* trace_var(symbol) {|val| block } -> nil
|
|
|
|
*
|
|
|
|
* Controls tracing of assignments to global variables. The parameter
|
|
|
|
* +symbol+ identifies the variable (as either a string name or a
|
|
|
|
* symbol identifier). _cmd_ (which may be a string or a
|
|
|
|
* +Proc+ object) or block is executed whenever the variable
|
|
|
|
* is assigned. The block or +Proc+ object receives the
|
|
|
|
* variable's new value as a parameter. Also see
|
2023-12-31 06:13:24 +03:00
|
|
|
* #untrace_var.
|
2019-08-29 04:23:14 +03:00
|
|
|
*
|
|
|
|
* trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
|
|
|
|
* $_ = "hello"
|
|
|
|
* $_ = ' there'
|
|
|
|
*
|
|
|
|
* <em>produces:</em>
|
|
|
|
*
|
|
|
|
* $_ is now 'hello'
|
|
|
|
* $_ is now ' there'
|
|
|
|
*/
|
|
|
|
|
2019-08-28 12:19:11 +03:00
|
|
|
static VALUE
|
|
|
|
f_trace_var(int c, const VALUE *a, VALUE _)
|
|
|
|
{
|
|
|
|
return rb_f_trace_var(c, a);
|
|
|
|
}
|
|
|
|
|
2019-08-29 04:23:14 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* untrace_var(symbol [, cmd] ) -> array or nil
|
|
|
|
*
|
|
|
|
* Removes tracing for the specified command on the given global
|
|
|
|
* variable and returns +nil+. If no command is specified,
|
|
|
|
* removes all tracing for that variable and returns an array
|
|
|
|
* containing the commands actually removed.
|
|
|
|
*/
|
|
|
|
|
2019-08-28 12:19:11 +03:00
|
|
|
static VALUE
|
|
|
|
f_untrace_var(int c, const VALUE *a, VALUE _)
|
|
|
|
{
|
|
|
|
return rb_f_untrace_var(c, a);
|
|
|
|
}
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
void
|
2007-02-07 16:34:18 +03:00
|
|
|
Init_eval(void)
|
2003-07-16 11:11:30 +04:00
|
|
|
{
|
2006-12-31 18:02:22 +03:00
|
|
|
rb_define_virtual_variable("$@", errat_getter, errat_setter);
|
2007-08-18 08:26:48 +04:00
|
|
|
rb_define_virtual_variable("$!", errinfo_getter, 0);
|
2003-07-16 11:11:30 +04:00
|
|
|
|
Some global variables can be accessed from ractors
Some global variables should be used from non-main Ractors.
[Bug #17268]
```ruby
# ractor-local (derived from created ractor): debug
'$DEBUG' => $DEBUG,
'$-d' => $-d,
# ractor-local (derived from created ractor): verbose
'$VERBOSE' => $VERBOSE,
'$-w' => $-w,
'$-W' => $-W,
'$-v' => $-v,
# process-local (readonly): other commandline parameters
'$-p' => $-p,
'$-l' => $-l,
'$-a' => $-a,
# process-local (readonly): getpid
'$$' => $$,
# thread local: process result
'$?' => $?,
# scope local: match
'$~' => $~.inspect,
'$&' => $&,
'$`' => $`,
'$\'' => $',
'$+' => $+,
'$1' => $1,
# scope local: last line
'$_' => $_,
# scope local: last backtrace
'$@' => $@,
'$!' => $!,
# ractor local: stdin, out, err
'$stdin' => $stdin.inspect,
'$stdout' => $stdout.inspect,
'$stderr' => $stderr.inspect,
```
2020-10-20 04:46:43 +03:00
|
|
|
rb_gvar_ractor_local("$@");
|
|
|
|
rb_gvar_ractor_local("$!");
|
|
|
|
|
2019-08-28 12:19:11 +03:00
|
|
|
rb_define_global_function("raise", f_raise, -1);
|
|
|
|
rb_define_global_function("fail", f_raise, -1);
|
2003-12-28 03:02:59 +03:00
|
|
|
|
2019-08-28 12:19:11 +03:00
|
|
|
rb_define_global_function("global_variables", f_global_variables, 0);
|
2003-07-16 11:11:30 +04:00
|
|
|
|
2007-03-20 10:21:37 +03:00
|
|
|
rb_define_global_function("__method__", rb_f_method_name, 0);
|
2012-07-04 06:11:37 +04:00
|
|
|
rb_define_global_function("__callee__", rb_f_callee_name, 0);
|
2012-11-03 05:37:50 +04:00
|
|
|
rb_define_global_function("__dir__", f_current_dirname, 0);
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
|
2013-09-03 16:42:01 +04:00
|
|
|
rb_define_method(rb_cModule, "include", rb_mod_include, -1);
|
|
|
|
rb_define_method(rb_cModule, "prepend", rb_mod_prepend, -1);
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
|
|
|
|
rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
|
2012-06-27 11:48:50 +04:00
|
|
|
rb_define_private_method(rb_cModule, "prepend_features", rb_mod_prepend_features, 1);
|
2013-01-07 15:22:31 +04:00
|
|
|
rb_define_private_method(rb_cModule, "refine", rb_mod_refine, 1);
|
2013-06-12 18:33:59 +04:00
|
|
|
rb_define_private_method(rb_cModule, "using", mod_using, 1);
|
2022-01-05 11:47:29 +03:00
|
|
|
rb_define_method(rb_cModule, "refinements", mod_refinements, 0);
|
2016-09-08 10:49:02 +03:00
|
|
|
rb_define_singleton_method(rb_cModule, "used_modules",
|
|
|
|
rb_mod_s_used_modules, 0);
|
2022-01-05 10:58:23 +03:00
|
|
|
rb_define_singleton_method(rb_cModule, "used_refinements",
|
|
|
|
rb_mod_s_used_refinements, 0);
|
2013-01-07 15:22:31 +04:00
|
|
|
rb_undef_method(rb_cClass, "refine");
|
2021-10-21 10:21:08 +03:00
|
|
|
rb_define_private_method(rb_cRefinement, "import_methods", refinement_import_methods, -1);
|
2023-07-14 09:13:14 +03:00
|
|
|
rb_define_method(rb_cRefinement, "target", rb_refinement_module_get_refined_class, 0);
|
|
|
|
rb_define_method(rb_cRefinement, "refined_class", rb_refinement_refined_class, 0);
|
2021-12-27 22:38:12 +03:00
|
|
|
rb_undef_method(rb_cRefinement, "append_features");
|
|
|
|
rb_undef_method(rb_cRefinement, "prepend_features");
|
|
|
|
rb_undef_method(rb_cRefinement, "extend_object");
|
2000-02-01 06:12:21 +03:00
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
rb_undef_method(rb_cClass, "module_function");
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 09:47:45 +03:00
|
|
|
|
* method.h, internal.h iseq.h: declare internal functions.
* compile.c, eval.c, iseq.c, object.c, parse.y, proc.c, process.c,
thread.c, vm.c, vm_eval.c, vm_insnhelper.c, vm_method.c: don't
declare internal functions.
Note that rb_method_entry_eq() is defined in vm_method.c but
there was a declaration in proc.c with different const-ness.
Now it is declared in method.h with same const-ness to the
definition.
* object.c (rb_mod_module_exec): don't declare functions declared in
include/ruby/intern.h.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32163 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-06-18 07:49:33 +04:00
|
|
|
Init_vm_eval();
|
|
|
|
Init_eval_method();
|
2003-12-28 03:02:59 +03:00
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
|
|
|
|
rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, -1);
|
2003-12-28 03:02:59 +03:00
|
|
|
|
2013-01-07 15:55:17 +04:00
|
|
|
rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
|
|
|
|
"include", top_include, -1);
|
2013-01-07 15:22:31 +04:00
|
|
|
rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
|
|
|
|
"using", top_using, 1);
|
2012-08-02 15:34:19 +04:00
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
|
2003-12-29 06:56:22 +03:00
|
|
|
|
2019-08-28 12:19:11 +03:00
|
|
|
rb_define_global_function("trace_var", f_trace_var, -1);
|
|
|
|
rb_define_global_function("untrace_var", f_untrace_var, -1);
|
1998-01-16 15:19:22 +03:00
|
|
|
|
2014-09-11 14:53:48 +04:00
|
|
|
rb_vm_register_special_exception(ruby_error_reenter, rb_eFatal, "exception reentered");
|
2017-08-21 09:46:46 +03:00
|
|
|
rb_vm_register_special_exception(ruby_error_stackfatal, rb_eFatal, "machine stack overflow in critical region");
|
2015-02-23 10:05:30 +03:00
|
|
|
|
|
|
|
id_signo = rb_intern_const("signo");
|
|
|
|
id_status = rb_intern_const("status");
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
2023-04-10 04:53:13 +03:00
|
|
|
|
|
|
|
int
|
|
|
|
rb_errno(void)
|
|
|
|
{
|
|
|
|
return *rb_orig_errno_ptr();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_errno_set(int e)
|
|
|
|
{
|
|
|
|
*rb_orig_errno_ptr() = e;
|
|
|
|
}
|
|
|
|
|
|
|
|
int *
|
|
|
|
rb_errno_ptr(void)
|
|
|
|
{
|
|
|
|
return rb_orig_errno_ptr();
|
|
|
|
}
|