mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
4c196dcdaa
Use `mrb_exec_irep()`. If possible, re-entry into the VM will be suppressed.
Note that due to the effect of being a tail-call, the backtrace of `Method#call` will be lost, and it will look as if the target method was called directly.
This change fixes the problem of infinite loops when redefining methods that make block calls using `mruby-method`.
```console
% bin/mruby -e 'mm = method(:proc); define_method(:proc, ->(*a, &b) { mm.call(*a, &b) }); p proc { 1 }'
trace (most recent call last):
[257] -e:1
[256] -e:1:in proc
[255] -e:1:in proc
...SNIP...
[1] -e:1:in proc
-e:1:in proc: stack level too deep (SystemStackError)
```
547 lines
16 KiB
C
547 lines
16 KiB
C
#include "mruby.h"
|
|
#include "mruby/array.h"
|
|
#include "mruby/class.h"
|
|
#include "mruby/variable.h"
|
|
#include "mruby/proc.h"
|
|
#include "mruby/string.h"
|
|
#include "mruby/presym.h"
|
|
|
|
mrb_noreturn void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args);
|
|
mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p, mrb_func_t posthook);
|
|
|
|
static mrb_value
|
|
args_shift(mrb_state *mrb)
|
|
{
|
|
mrb_value *argv = mrb->c->ci->stack + 1;
|
|
|
|
if (mrb->c->ci->argc > 0) {
|
|
mrb_value obj = argv[0];
|
|
memmove(argv, argv + 1, (mrb->c->ci->argc + 1 /* block */ - 1 /* first value */) * sizeof(mrb_value));
|
|
mrb->c->ci->argc--;
|
|
return obj;
|
|
}
|
|
else if (mrb->c->ci->argc < 0 && RARRAY_LEN(*argv) > 0) {
|
|
return mrb_ary_shift(mrb, *argv);
|
|
}
|
|
else {
|
|
mrb_argnum_error(mrb, 0, 1, -1);
|
|
return mrb_undef_value(); /* not reached */
|
|
}
|
|
}
|
|
|
|
static void
|
|
args_unshift(mrb_state *mrb, mrb_value obj)
|
|
{
|
|
mrb_value *argv = mrb->c->ci->stack + 1;
|
|
|
|
if (mrb->c->ci->argc >= 0) {
|
|
mrb_value block = argv[mrb->c->ci->argc];
|
|
argv[0] = mrb_ary_new_from_values(mrb, mrb->c->ci->argc, argv);
|
|
argv[1] = block;
|
|
mrb->c->ci->argc = -1;
|
|
}
|
|
|
|
mrb_ary_unshift(mrb, *argv, obj);
|
|
}
|
|
|
|
static struct RProc*
|
|
method_missing_prepare(mrb_state *mrb, mrb_sym *mid, mrb_value recv, struct RClass **tc)
|
|
{
|
|
const mrb_sym id_method_missing = MRB_SYM(method_missing);
|
|
|
|
if (*mid == id_method_missing) {
|
|
method_missing: ;
|
|
int argc = mrb->c->ci->argc;
|
|
mrb_value *argv = mrb->c->ci->stack + 1;
|
|
mrb_value args = (argc < 0) ? argv[0] : mrb_ary_new_from_values(mrb, argc, argv);
|
|
mrb_method_missing(mrb, *mid, recv, args);
|
|
}
|
|
|
|
*tc = mrb_class(mrb, recv);
|
|
mrb_method_t m = mrb_method_search_vm(mrb, tc, id_method_missing);
|
|
if (MRB_METHOD_UNDEF_P(m)) {
|
|
goto method_missing;
|
|
}
|
|
|
|
struct RProc *proc;
|
|
if (MRB_METHOD_FUNC_P(m)) {
|
|
proc = mrb_proc_new_cfunc(mrb, MRB_METHOD_FUNC(m));
|
|
MRB_PROC_SET_TARGET_CLASS(proc, *tc);
|
|
}
|
|
else {
|
|
proc = MRB_METHOD_PROC(m);
|
|
}
|
|
|
|
args_unshift(mrb, mrb_symbol_value(*mid));
|
|
*mid = id_method_missing;
|
|
|
|
return proc;
|
|
}
|
|
|
|
static struct RObject *
|
|
method_object_alloc(mrb_state *mrb, struct RClass *mclass)
|
|
{
|
|
return (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mclass);
|
|
}
|
|
|
|
static struct RProc*
|
|
method_extract_proc(mrb_state *mrb, mrb_value self)
|
|
{
|
|
mrb_value obj = mrb_iv_get(mrb, self, MRB_SYM(_proc));
|
|
if (mrb_nil_p(obj)) {
|
|
return NULL;
|
|
}
|
|
else {
|
|
mrb_check_type(mrb, obj, MRB_TT_PROC);
|
|
return mrb_proc_ptr(obj);
|
|
}
|
|
}
|
|
|
|
static mrb_value
|
|
method_extract_receiver(mrb_state *mrb, mrb_value self)
|
|
{
|
|
return mrb_iv_get(mrb, self, MRB_SYM(_recv));
|
|
}
|
|
|
|
static mrb_sym
|
|
method_extract_mid(mrb_state *mrb, mrb_value self)
|
|
{
|
|
mrb_value obj = mrb_iv_get(mrb, self, MRB_SYM(_name));
|
|
mrb_check_type(mrb, obj, MRB_TT_SYMBOL);
|
|
return mrb_symbol(obj);
|
|
}
|
|
|
|
static struct RClass*
|
|
method_extract_owner(mrb_state *mrb, mrb_value self)
|
|
{
|
|
mrb_value obj = mrb_iv_get(mrb, self, MRB_SYM(_owner));
|
|
switch (mrb_type(obj)) {
|
|
case MRB_TT_CLASS:
|
|
case MRB_TT_MODULE:
|
|
case MRB_TT_SCLASS:
|
|
break;
|
|
default:
|
|
mrb_raise(mrb, E_TYPE_ERROR, "not class/module as owner of method object");
|
|
}
|
|
return mrb_class_ptr(obj);
|
|
}
|
|
|
|
static void
|
|
bind_check(mrb_state *mrb, mrb_value recv, mrb_value owner)
|
|
{
|
|
if (!mrb_module_p(owner) &&
|
|
mrb_class_ptr(owner) != mrb_obj_class(mrb, recv) &&
|
|
!mrb_obj_is_kind_of(mrb, recv, mrb_class_ptr(owner))) {
|
|
if (mrb_sclass_p(owner)) {
|
|
mrb_raise(mrb, E_TYPE_ERROR, "singleton method called for a different object");
|
|
} else {
|
|
mrb_raisef(mrb, E_TYPE_ERROR, "bind argument must be an instance of %v", owner);
|
|
}
|
|
}
|
|
}
|
|
|
|
static mrb_value
|
|
unbound_method_bind(mrb_state *mrb, mrb_value self)
|
|
{
|
|
struct RObject *me;
|
|
mrb_value owner = mrb_iv_get(mrb, self, MRB_SYM(_owner));
|
|
mrb_value name = mrb_iv_get(mrb, self, MRB_SYM(_name));
|
|
mrb_value proc = mrb_iv_get(mrb, self, MRB_SYM(_proc));
|
|
mrb_value klass = mrb_iv_get(mrb, self, MRB_SYM(_klass));
|
|
mrb_value recv = mrb_get_arg1(mrb);
|
|
|
|
bind_check(mrb, recv, owner);
|
|
me = method_object_alloc(mrb, mrb_class_get_id(mrb, MRB_SYM(Method)));
|
|
mrb_obj_iv_set(mrb, me, MRB_SYM(_owner), owner);
|
|
mrb_obj_iv_set(mrb, me, MRB_SYM(_recv), recv);
|
|
mrb_obj_iv_set(mrb, me, MRB_SYM(_name), name);
|
|
mrb_obj_iv_set(mrb, me, MRB_SYM(_proc), proc);
|
|
mrb_obj_iv_set(mrb, me, MRB_SYM(_klass), klass);
|
|
|
|
return mrb_obj_value(me);
|
|
}
|
|
|
|
#define IV_GET(value, name) mrb_iv_get(mrb, value, name)
|
|
static mrb_value
|
|
method_eql(mrb_state *mrb, mrb_value self)
|
|
{
|
|
mrb_value other = mrb_get_arg1(mrb);
|
|
mrb_value receiver, orig_proc, other_proc;
|
|
struct RClass *owner, *klass;
|
|
struct RProc *orig_rproc, *other_rproc;
|
|
|
|
if (!mrb_obj_is_instance_of(mrb, other, mrb_class(mrb, self)))
|
|
return mrb_false_value();
|
|
|
|
if (mrb_class(mrb, self) != mrb_class(mrb, other))
|
|
return mrb_false_value();
|
|
|
|
klass = mrb_class_ptr(IV_GET(self, MRB_SYM(_klass)));
|
|
if (klass != mrb_class_ptr(IV_GET(other, MRB_SYM(_klass))))
|
|
return mrb_false_value();
|
|
|
|
owner = mrb_class_ptr(IV_GET(self, MRB_SYM(_owner)));
|
|
if (owner != mrb_class_ptr(IV_GET(other, MRB_SYM(_owner))))
|
|
return mrb_false_value();
|
|
|
|
receiver = IV_GET(self, MRB_SYM(_recv));
|
|
if (!mrb_obj_equal(mrb, receiver, IV_GET(other, MRB_SYM(_recv))))
|
|
return mrb_false_value();
|
|
|
|
orig_proc = IV_GET(self, MRB_SYM(_proc));
|
|
other_proc = IV_GET(other, MRB_SYM(_proc));
|
|
if (mrb_nil_p(orig_proc) && mrb_nil_p(other_proc)) {
|
|
if (mrb_symbol(IV_GET(self, MRB_SYM(_name))) == mrb_symbol(IV_GET(other, MRB_SYM(_name))))
|
|
return mrb_true_value();
|
|
else
|
|
return mrb_false_value();
|
|
}
|
|
|
|
if (mrb_nil_p(orig_proc))
|
|
return mrb_false_value();
|
|
if (mrb_nil_p(other_proc))
|
|
return mrb_false_value();
|
|
|
|
orig_rproc = mrb_proc_ptr(orig_proc);
|
|
other_rproc = mrb_proc_ptr(other_proc);
|
|
if (MRB_PROC_CFUNC_P(orig_rproc)) {
|
|
if (!MRB_PROC_CFUNC_P(other_rproc))
|
|
return mrb_false_value();
|
|
if (orig_rproc->body.func != other_rproc->body.func)
|
|
return mrb_false_value();
|
|
}
|
|
else {
|
|
if (MRB_PROC_CFUNC_P(other_rproc))
|
|
return mrb_false_value();
|
|
if (orig_rproc->body.irep != other_rproc->body.irep)
|
|
return mrb_false_value();
|
|
}
|
|
|
|
return mrb_true_value();
|
|
}
|
|
|
|
#undef IV_GET
|
|
|
|
static mrb_value
|
|
mcall(mrb_state *mrb, mrb_value self, mrb_value recv)
|
|
{
|
|
struct RProc *proc = method_extract_proc(mrb, self);
|
|
mrb_sym mid = method_extract_mid(mrb, self);
|
|
struct RClass *tc = method_extract_owner(mrb, self);
|
|
|
|
if (mrb_undef_p(recv)) {
|
|
recv = method_extract_receiver(mrb, self);
|
|
}
|
|
else {
|
|
bind_check(mrb, recv, mrb_obj_value(tc));
|
|
}
|
|
|
|
if (!proc) {
|
|
proc = method_missing_prepare(mrb, &mid, recv, &tc);
|
|
}
|
|
mrb->c->ci->mid = mid;
|
|
mrb->c->ci->u.target_class = tc;
|
|
|
|
return mrb_exec_irep(mrb, recv, proc, NULL);
|
|
}
|
|
|
|
static mrb_value
|
|
method_call(mrb_state *mrb, mrb_value self)
|
|
{
|
|
return mcall(mrb, self, mrb_undef_value());
|
|
}
|
|
|
|
static mrb_value
|
|
method_bcall(mrb_state *mrb, mrb_value self)
|
|
{
|
|
mrb_value recv = args_shift(mrb);
|
|
mrb_gc_protect(mrb, recv);
|
|
return mcall(mrb, self, recv);
|
|
}
|
|
|
|
static mrb_value
|
|
method_unbind(mrb_state *mrb, mrb_value self)
|
|
{
|
|
struct RObject *ume;
|
|
mrb_value owner = mrb_iv_get(mrb, self, MRB_SYM(_owner));
|
|
mrb_value name = mrb_iv_get(mrb, self, MRB_SYM(_name));
|
|
mrb_value proc = mrb_iv_get(mrb, self, MRB_SYM(_proc));
|
|
mrb_value klass = mrb_iv_get(mrb, self, MRB_SYM(_klass));
|
|
|
|
ume = method_object_alloc(mrb, mrb_class_get_id(mrb, MRB_SYM(UnboundMethod)));
|
|
mrb_obj_iv_set(mrb, ume, MRB_SYM(_owner), owner);
|
|
mrb_obj_iv_set(mrb, ume, MRB_SYM(_recv), mrb_nil_value());
|
|
mrb_obj_iv_set(mrb, ume, MRB_SYM(_name), name);
|
|
mrb_obj_iv_set(mrb, ume, MRB_SYM(_proc), proc);
|
|
mrb_obj_iv_set(mrb, ume, MRB_SYM(_klass), klass);
|
|
|
|
return mrb_obj_value(ume);
|
|
}
|
|
|
|
static struct RProc *
|
|
method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
|
|
{
|
|
mrb_method_t m = mrb_method_search_vm(mrb, cp, mid);
|
|
if (MRB_METHOD_UNDEF_P(m))
|
|
return NULL;
|
|
if (MRB_METHOD_PROC_P(m))
|
|
return MRB_METHOD_PROC(m);
|
|
return mrb_proc_new_cfunc(mrb, MRB_METHOD_FUNC(m));
|
|
}
|
|
|
|
static mrb_value
|
|
method_super_method(mrb_state *mrb, mrb_value self)
|
|
{
|
|
mrb_value recv = mrb_iv_get(mrb, self, MRB_SYM(_recv));
|
|
mrb_value klass = mrb_iv_get(mrb, self, MRB_SYM(_klass));
|
|
mrb_value owner = mrb_iv_get(mrb, self, MRB_SYM(_owner));
|
|
mrb_value name = mrb_iv_get(mrb, self, MRB_SYM(_name));
|
|
struct RClass *super, *rklass;
|
|
struct RProc *proc;
|
|
struct RObject *me;
|
|
|
|
switch (mrb_type(klass)) {
|
|
case MRB_TT_SCLASS:
|
|
super = mrb_class_ptr(klass)->super->super;
|
|
break;
|
|
case MRB_TT_ICLASS:
|
|
super = mrb_class_ptr(klass)->super;
|
|
break;
|
|
default:
|
|
super = mrb_class_ptr(owner)->super;
|
|
break;
|
|
}
|
|
|
|
proc = method_search_vm(mrb, &super, mrb_symbol(name));
|
|
if (!proc)
|
|
return mrb_nil_value();
|
|
|
|
rklass = super;
|
|
while (super->tt == MRB_TT_ICLASS)
|
|
super = super->c;
|
|
|
|
me = method_object_alloc(mrb, mrb_obj_class(mrb, self));
|
|
mrb_obj_iv_set(mrb, me, MRB_SYM(_owner), mrb_obj_value(super));
|
|
mrb_obj_iv_set(mrb, me, MRB_SYM(_recv), recv);
|
|
mrb_obj_iv_set(mrb, me, MRB_SYM(_name), name);
|
|
mrb_obj_iv_set(mrb, me, MRB_SYM(_proc), mrb_obj_value(proc));
|
|
mrb_obj_iv_set(mrb, me, MRB_SYM(_klass), mrb_obj_value(rklass));
|
|
|
|
return mrb_obj_value(me);
|
|
}
|
|
|
|
static mrb_value
|
|
method_arity(mrb_state *mrb, mrb_value self)
|
|
{
|
|
mrb_value proc = mrb_iv_get(mrb, self, MRB_SYM(_proc));
|
|
mrb_int arity = mrb_nil_p(proc) ? -1 : mrb_proc_arity(mrb_proc_ptr(proc));
|
|
return mrb_fixnum_value(arity);
|
|
}
|
|
|
|
static mrb_value
|
|
method_source_location(mrb_state *mrb, mrb_value self)
|
|
{
|
|
mrb_value proc = mrb_iv_get(mrb, self, MRB_SYM(_proc));
|
|
struct RProc *rproc;
|
|
struct RClass *orig;
|
|
mrb_value ret;
|
|
|
|
if (mrb_nil_p(proc))
|
|
return mrb_nil_value();
|
|
|
|
rproc = mrb_proc_ptr(proc);
|
|
orig = rproc->c;
|
|
rproc->c = mrb->proc_class;
|
|
ret = mrb_funcall_id(mrb, proc, MRB_SYM(source_location), 0);
|
|
rproc->c = orig;
|
|
return ret;
|
|
}
|
|
|
|
static mrb_value
|
|
method_parameters(mrb_state *mrb, mrb_value self)
|
|
{
|
|
mrb_value proc = mrb_iv_get(mrb, self, MRB_SYM(_proc));
|
|
struct RProc *rproc;
|
|
struct RClass *orig;
|
|
mrb_value ret;
|
|
|
|
if (mrb_nil_p(proc)) {
|
|
mrb_value rest = mrb_symbol_value(MRB_SYM(rest));
|
|
mrb_value arest = mrb_ary_new_from_values(mrb, 1, &rest);
|
|
return mrb_ary_new_from_values(mrb, 1, &arest);
|
|
}
|
|
|
|
rproc = mrb_proc_ptr(proc);
|
|
orig = rproc->c;
|
|
rproc->c = mrb->proc_class;
|
|
ret = mrb_funcall_id(mrb, proc, MRB_SYM(parameters), 0);
|
|
rproc->c = orig;
|
|
return ret;
|
|
}
|
|
|
|
static mrb_value
|
|
method_to_s(mrb_state *mrb, mrb_value self)
|
|
{
|
|
mrb_value owner = mrb_iv_get(mrb, self, MRB_SYM(_owner));
|
|
mrb_value klass = mrb_iv_get(mrb, self, MRB_SYM(_klass));
|
|
mrb_value name = mrb_iv_get(mrb, self, MRB_SYM(_name));
|
|
mrb_value str = mrb_str_new_lit(mrb, "#<");
|
|
struct RClass *rklass;
|
|
|
|
mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, self));
|
|
mrb_str_cat_lit(mrb, str, ": ");
|
|
rklass = mrb_class_ptr(klass);
|
|
if (mrb_class_ptr(owner) == rklass) {
|
|
mrb_str_concat(mrb, str, owner);
|
|
mrb_str_cat_lit(mrb, str, "#");
|
|
mrb_str_concat(mrb, str, name);
|
|
}
|
|
else {
|
|
mrb_str_cat_cstr(mrb, str, mrb_class_name(mrb, rklass));
|
|
mrb_str_cat_lit(mrb, str, "(");
|
|
mrb_str_concat(mrb, str, owner);
|
|
mrb_str_cat_lit(mrb, str, ")#");
|
|
mrb_str_concat(mrb, str, name);
|
|
}
|
|
mrb_str_cat_lit(mrb, str, ">");
|
|
return str;
|
|
}
|
|
|
|
static void
|
|
mrb_search_method_owner(mrb_state *mrb, struct RClass *c, mrb_value obj, mrb_sym name, struct RClass **owner, struct RProc **proc, mrb_bool unbound)
|
|
{
|
|
mrb_value ret;
|
|
|
|
*owner = c;
|
|
*proc = method_search_vm(mrb, owner, name);
|
|
if (!*proc) {
|
|
if (unbound) {
|
|
goto name_error;
|
|
}
|
|
if (!mrb_respond_to(mrb, obj, MRB_SYM_Q(respond_to_missing))) {
|
|
goto name_error;
|
|
}
|
|
ret = mrb_funcall_id(mrb, obj, MRB_SYM_Q(respond_to_missing), 2, mrb_symbol_value(name), mrb_true_value());
|
|
if (!mrb_test(ret)) {
|
|
goto name_error;
|
|
}
|
|
*owner = c;
|
|
}
|
|
|
|
while ((*owner)->tt == MRB_TT_ICLASS)
|
|
*owner = (*owner)->c;
|
|
|
|
return;
|
|
|
|
name_error:
|
|
mrb_raisef(mrb, E_NAME_ERROR, "undefined method '%n' for class '%C'", name, c);
|
|
}
|
|
|
|
static mrb_value
|
|
mrb_kernel_method(mrb_state *mrb, mrb_value self)
|
|
{
|
|
struct RClass *owner;
|
|
struct RProc *proc;
|
|
struct RObject *me;
|
|
mrb_sym name;
|
|
|
|
mrb_get_args(mrb, "n", &name);
|
|
|
|
mrb_search_method_owner(mrb, mrb_class(mrb, self), self, name, &owner, &proc, FALSE);
|
|
|
|
me = method_object_alloc(mrb, mrb_class_get_id(mrb, MRB_SYM(Method)));
|
|
mrb_obj_iv_set(mrb, me, MRB_SYM(_owner), mrb_obj_value(owner));
|
|
mrb_obj_iv_set(mrb, me, MRB_SYM(_recv), self);
|
|
mrb_obj_iv_set(mrb, me, MRB_SYM(_name), mrb_symbol_value(name));
|
|
mrb_obj_iv_set(mrb, me, MRB_SYM(_proc), proc ? mrb_obj_value(proc) : mrb_nil_value());
|
|
mrb_obj_iv_set(mrb, me, MRB_SYM(_klass), mrb_obj_value(mrb_class(mrb, self)));
|
|
|
|
return mrb_obj_value(me);
|
|
}
|
|
|
|
static mrb_value
|
|
mrb_module_instance_method(mrb_state *mrb, mrb_value self)
|
|
{
|
|
struct RClass *owner;
|
|
struct RProc *proc;
|
|
struct RObject *ume;
|
|
mrb_sym name;
|
|
|
|
mrb_get_args(mrb, "n", &name);
|
|
|
|
mrb_search_method_owner(mrb, mrb_class_ptr(self), self, name, &owner, &proc, TRUE);
|
|
|
|
ume = method_object_alloc(mrb, mrb_class_get_id(mrb, MRB_SYM(UnboundMethod)));
|
|
mrb_obj_iv_set(mrb, ume, MRB_SYM(_owner), mrb_obj_value(owner));
|
|
mrb_obj_iv_set(mrb, ume, MRB_SYM(_recv), mrb_nil_value());
|
|
mrb_obj_iv_set(mrb, ume, MRB_SYM(_name), mrb_symbol_value(name));
|
|
mrb_obj_iv_set(mrb, ume, MRB_SYM(_proc), proc ? mrb_obj_value(proc) : mrb_nil_value());
|
|
mrb_obj_iv_set(mrb, ume, MRB_SYM(_klass), self);
|
|
|
|
return mrb_obj_value(ume);
|
|
}
|
|
|
|
static mrb_value
|
|
method_owner(mrb_state *mrb, mrb_value self)
|
|
{
|
|
return mrb_iv_get(mrb, self, MRB_SYM(_owner));
|
|
}
|
|
|
|
static mrb_value
|
|
method_receiver(mrb_state *mrb, mrb_value self)
|
|
{
|
|
return mrb_iv_get(mrb, self, MRB_SYM(_recv));
|
|
}
|
|
|
|
static mrb_value
|
|
method_name(mrb_state *mrb, mrb_value self)
|
|
{
|
|
return mrb_iv_get(mrb, self, MRB_SYM(_name));
|
|
}
|
|
|
|
void
|
|
mrb_mruby_method_gem_init(mrb_state* mrb)
|
|
{
|
|
struct RClass *unbound_method = mrb_define_class_id(mrb, MRB_SYM(UnboundMethod), mrb->object_class);
|
|
struct RClass *method = mrb_define_class_id(mrb, MRB_SYM(Method), mrb->object_class);
|
|
|
|
mrb_undef_class_method(mrb, unbound_method, "new");
|
|
mrb_define_method(mrb, unbound_method, "bind", unbound_method_bind, MRB_ARGS_REQ(1));
|
|
mrb_define_method(mrb, unbound_method, "super_method", method_super_method, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, unbound_method, "==", method_eql, MRB_ARGS_REQ(1));
|
|
mrb_define_method(mrb, unbound_method, "eql?", method_eql, MRB_ARGS_REQ(1));
|
|
mrb_define_method(mrb, unbound_method, "to_s", method_to_s, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, unbound_method, "inspect", method_to_s, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, unbound_method, "arity", method_arity, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, unbound_method, "source_location", method_source_location, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, unbound_method, "parameters", method_parameters, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, unbound_method, "bind_call", method_bcall, MRB_ARGS_REQ(1)|MRB_ARGS_ANY());
|
|
mrb_define_method(mrb, unbound_method, "owner", method_owner, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, unbound_method, "name", method_name, MRB_ARGS_NONE());
|
|
|
|
mrb_undef_class_method(mrb, method, "new");
|
|
mrb_define_method(mrb, method, "==", method_eql, MRB_ARGS_REQ(1));
|
|
mrb_define_method(mrb, method, "eql?", method_eql, MRB_ARGS_REQ(1));
|
|
mrb_define_method(mrb, method, "to_s", method_to_s, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, method, "inspect", method_to_s, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, method, "call", method_call, MRB_ARGS_ANY());
|
|
mrb_define_method(mrb, method, "[]", method_call, MRB_ARGS_ANY());
|
|
mrb_define_method(mrb, method, "unbind", method_unbind, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, method, "super_method", method_super_method, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, method, "arity", method_arity, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, method, "source_location", method_source_location, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, method, "parameters", method_parameters, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, method, "owner", method_owner, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, method, "receiver", method_receiver, MRB_ARGS_NONE());
|
|
mrb_define_method(mrb, method, "name", method_name, MRB_ARGS_NONE());
|
|
|
|
mrb_define_method(mrb, mrb->kernel_module, "method", mrb_kernel_method, MRB_ARGS_REQ(1));
|
|
|
|
mrb_define_method(mrb, mrb->module_class, "instance_method", mrb_module_instance_method, MRB_ARGS_REQ(1));
|
|
}
|
|
|
|
void
|
|
mrb_mruby_method_gem_final(mrb_state* mrb)
|
|
{
|
|
}
|