[439] | 1 | #include "mruby.h"
|
---|
| 2 | #include "mruby/array.h"
|
---|
| 3 | #include "mruby/class.h"
|
---|
| 4 | #include "mruby/variable.h"
|
---|
| 5 | #include "mruby/proc.h"
|
---|
| 6 | #include "mruby/string.h"
|
---|
| 7 |
|
---|
| 8 | static struct RObject *
|
---|
| 9 | method_object_alloc(mrb_state *mrb, struct RClass *mclass)
|
---|
| 10 | {
|
---|
| 11 | return (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mclass);
|
---|
| 12 | }
|
---|
| 13 |
|
---|
| 14 | static void
|
---|
| 15 | bind_check(mrb_state *mrb, mrb_value recv, mrb_value owner)
|
---|
| 16 | {
|
---|
| 17 | if (!mrb_module_p(owner) &&
|
---|
| 18 | mrb_class_ptr(owner) != mrb_obj_class(mrb, recv) &&
|
---|
| 19 | !mrb_obj_is_kind_of(mrb, recv, mrb_class_ptr(owner))) {
|
---|
| 20 | if (mrb_sclass_p(owner)) {
|
---|
| 21 | mrb_raise(mrb, E_TYPE_ERROR, "singleton method called for a different object");
|
---|
| 22 | } else {
|
---|
| 23 | mrb_raisef(mrb, E_TYPE_ERROR, "bind argument must be an instance of %v", owner);
|
---|
| 24 | }
|
---|
| 25 | }
|
---|
| 26 | }
|
---|
| 27 |
|
---|
| 28 | static mrb_value
|
---|
| 29 | unbound_method_bind(mrb_state *mrb, mrb_value self)
|
---|
| 30 | {
|
---|
| 31 | struct RObject *me;
|
---|
| 32 | mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_owner"));
|
---|
| 33 | mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
|
---|
| 34 | mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
|
---|
| 35 | mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_klass"));
|
---|
| 36 | mrb_value recv;
|
---|
| 37 |
|
---|
| 38 | mrb_get_args(mrb, "o", &recv);
|
---|
| 39 | bind_check(mrb, recv, owner);
|
---|
| 40 | me = method_object_alloc(mrb, mrb_class_get(mrb, "Method"));
|
---|
| 41 | mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_owner"), owner);
|
---|
| 42 | mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_recv"), recv);
|
---|
| 43 | mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_name"), name);
|
---|
| 44 | mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_proc"), proc);
|
---|
| 45 | mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_klass"), klass);
|
---|
| 46 |
|
---|
| 47 | return mrb_obj_value(me);
|
---|
| 48 | }
|
---|
| 49 |
|
---|
| 50 | #define IV_GET(value, name) mrb_iv_get(mrb, value, mrb_intern_lit(mrb, name))
|
---|
| 51 | static mrb_value
|
---|
| 52 | method_eql(mrb_state *mrb, mrb_value self)
|
---|
| 53 | {
|
---|
| 54 | mrb_value other, receiver, orig_proc, other_proc;
|
---|
| 55 | struct RClass *owner, *klass;
|
---|
| 56 | struct RProc *orig_rproc, *other_rproc;
|
---|
| 57 |
|
---|
| 58 | mrb_get_args(mrb, "o", &other);
|
---|
| 59 | if (!mrb_obj_is_instance_of(mrb, other, mrb_class(mrb, self)))
|
---|
| 60 | return mrb_false_value();
|
---|
| 61 |
|
---|
| 62 | if (mrb_class(mrb, self) != mrb_class(mrb, other))
|
---|
| 63 | return mrb_false_value();
|
---|
| 64 |
|
---|
| 65 | klass = mrb_class_ptr(IV_GET(self, "_klass"));
|
---|
| 66 | if (klass != mrb_class_ptr(IV_GET(other, "_klass")))
|
---|
| 67 | return mrb_false_value();
|
---|
| 68 |
|
---|
| 69 | owner = mrb_class_ptr(IV_GET(self, "_owner"));
|
---|
| 70 | if (owner != mrb_class_ptr(IV_GET(other, "_owner")))
|
---|
| 71 | return mrb_false_value();
|
---|
| 72 |
|
---|
| 73 | receiver = IV_GET(self, "_recv");
|
---|
| 74 | if (!mrb_obj_equal(mrb, receiver, IV_GET(other, "_recv")))
|
---|
| 75 | return mrb_false_value();
|
---|
| 76 |
|
---|
| 77 | orig_proc = IV_GET(self, "_proc");
|
---|
| 78 | other_proc = IV_GET(other, "_proc");
|
---|
| 79 | if (mrb_nil_p(orig_proc) && mrb_nil_p(other_proc)) {
|
---|
| 80 | if (mrb_symbol(IV_GET(self, "_name")) == mrb_symbol(IV_GET(other, "_name")))
|
---|
| 81 | return mrb_true_value();
|
---|
| 82 | else
|
---|
| 83 | return mrb_false_value();
|
---|
| 84 | }
|
---|
| 85 |
|
---|
| 86 | if (mrb_nil_p(orig_proc))
|
---|
| 87 | return mrb_false_value();
|
---|
| 88 | if (mrb_nil_p(other_proc))
|
---|
| 89 | return mrb_false_value();
|
---|
| 90 |
|
---|
| 91 | orig_rproc = mrb_proc_ptr(orig_proc);
|
---|
| 92 | other_rproc = mrb_proc_ptr(other_proc);
|
---|
| 93 | if (MRB_PROC_CFUNC_P(orig_rproc)) {
|
---|
| 94 | if (!MRB_PROC_CFUNC_P(other_rproc))
|
---|
| 95 | return mrb_false_value();
|
---|
| 96 | if (orig_rproc->body.func != other_rproc->body.func)
|
---|
| 97 | return mrb_false_value();
|
---|
| 98 | }
|
---|
| 99 | else {
|
---|
| 100 | if (MRB_PROC_CFUNC_P(other_rproc))
|
---|
| 101 | return mrb_false_value();
|
---|
| 102 | if (orig_rproc->body.irep != other_rproc->body.irep)
|
---|
| 103 | return mrb_false_value();
|
---|
| 104 | }
|
---|
| 105 |
|
---|
| 106 | return mrb_true_value();
|
---|
| 107 | }
|
---|
| 108 |
|
---|
| 109 | #undef IV_GET
|
---|
| 110 |
|
---|
| 111 | static mrb_value
|
---|
| 112 | mcall(mrb_state *mrb, mrb_value recv, mrb_value proc, mrb_value name, struct RClass *owner,
|
---|
| 113 | int argc, mrb_value *argv, mrb_value block)
|
---|
| 114 | {
|
---|
| 115 | mrb_value ret;
|
---|
| 116 | mrb_sym orig_mid = mrb->c->ci->mid;
|
---|
| 117 |
|
---|
| 118 | mrb->c->ci->mid = mrb_symbol(name);
|
---|
| 119 | if (mrb_nil_p(proc)) {
|
---|
| 120 | mrb_value missing_argv = mrb_ary_new_from_values(mrb, argc, argv);
|
---|
| 121 | mrb_ary_unshift(mrb, missing_argv, name);
|
---|
| 122 | ret = mrb_funcall_argv(mrb, recv, mrb_intern_lit(mrb, "method_missing"), argc + 1, RARRAY_PTR(missing_argv));
|
---|
| 123 | }
|
---|
| 124 | else if (!mrb_nil_p(block)) {
|
---|
| 125 | /*
|
---|
| 126 | workaround since `mrb_yield_with_class` does not support passing block as parameter
|
---|
| 127 | need new API that initializes `mrb->c->stack[argc+1]` with block passed by argument
|
---|
| 128 | */
|
---|
| 129 | ret = mrb_funcall_with_block(mrb, recv, mrb_symbol(name), argc, argv, block);
|
---|
| 130 | }
|
---|
| 131 | else {
|
---|
| 132 | ret = mrb_yield_with_class(mrb, proc, argc, argv, recv, owner);
|
---|
| 133 | }
|
---|
| 134 | mrb->c->ci->mid = orig_mid;
|
---|
| 135 | return ret;
|
---|
| 136 | }
|
---|
| 137 |
|
---|
| 138 | static mrb_value
|
---|
| 139 | method_call(mrb_state *mrb, mrb_value self)
|
---|
| 140 | {
|
---|
| 141 | mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
|
---|
| 142 | mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
|
---|
| 143 | mrb_value recv = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_recv"));
|
---|
| 144 | struct RClass *owner = mrb_class_ptr(mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_owner")));
|
---|
| 145 | mrb_int argc;
|
---|
| 146 | mrb_value *argv, block;
|
---|
| 147 |
|
---|
| 148 | mrb_get_args(mrb, "*&", &argv, &argc, &block);
|
---|
| 149 | return mcall(mrb, recv, proc, name, owner, argc, argv, block);
|
---|
| 150 | }
|
---|
| 151 |
|
---|
| 152 | static mrb_value
|
---|
| 153 | method_bcall(mrb_state *mrb, mrb_value self)
|
---|
| 154 | {
|
---|
| 155 | mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
|
---|
| 156 | mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
|
---|
| 157 | mrb_value recv = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_recv"));
|
---|
| 158 | mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_owner"));
|
---|
| 159 | mrb_int argc;
|
---|
| 160 | mrb_value *argv, block;
|
---|
| 161 |
|
---|
| 162 | mrb_get_args(mrb, "o*&", &recv, &argv, &argc, &block);
|
---|
| 163 | bind_check(mrb, recv, owner);
|
---|
| 164 | return mcall(mrb, recv, proc, name, mrb_class_ptr(owner), argc, argv, block);
|
---|
| 165 | }
|
---|
| 166 |
|
---|
| 167 | static mrb_value
|
---|
| 168 | method_unbind(mrb_state *mrb, mrb_value self)
|
---|
| 169 | {
|
---|
| 170 | struct RObject *ume;
|
---|
| 171 | mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_owner"));
|
---|
| 172 | mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
|
---|
| 173 | mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
|
---|
| 174 | mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_klass"));
|
---|
| 175 |
|
---|
| 176 | ume = method_object_alloc(mrb, mrb_class_get(mrb, "UnboundMethod"));
|
---|
| 177 | mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_owner"), owner);
|
---|
| 178 | mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_recv"), mrb_nil_value());
|
---|
| 179 | mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_name"), name);
|
---|
| 180 | mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_proc"), proc);
|
---|
| 181 | mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_klass"), klass);
|
---|
| 182 |
|
---|
| 183 | return mrb_obj_value(ume);
|
---|
| 184 | }
|
---|
| 185 |
|
---|
| 186 | static struct RProc *
|
---|
| 187 | method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
|
---|
| 188 | {
|
---|
| 189 | mrb_method_t m = mrb_method_search_vm(mrb, cp, mid);
|
---|
| 190 | if (MRB_METHOD_UNDEF_P(m))
|
---|
| 191 | return NULL;
|
---|
| 192 | if (MRB_METHOD_PROC_P(m))
|
---|
| 193 | return MRB_METHOD_PROC(m);
|
---|
| 194 | return mrb_proc_new_cfunc(mrb, MRB_METHOD_FUNC(m));
|
---|
| 195 | }
|
---|
| 196 |
|
---|
| 197 | static mrb_value
|
---|
| 198 | method_super_method(mrb_state *mrb, mrb_value self)
|
---|
| 199 | {
|
---|
| 200 | mrb_value recv = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_recv"));
|
---|
| 201 | mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_klass"));
|
---|
| 202 | mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_owner"));
|
---|
| 203 | mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
|
---|
| 204 | struct RClass *super, *rklass;
|
---|
| 205 | struct RProc *proc;
|
---|
| 206 | struct RObject *me;
|
---|
| 207 |
|
---|
| 208 | switch (mrb_type(klass)) {
|
---|
| 209 | case MRB_TT_SCLASS:
|
---|
| 210 | super = mrb_class_ptr(klass)->super->super;
|
---|
| 211 | break;
|
---|
| 212 | case MRB_TT_ICLASS:
|
---|
| 213 | super = mrb_class_ptr(klass)->super;
|
---|
| 214 | break;
|
---|
| 215 | default:
|
---|
| 216 | super = mrb_class_ptr(owner)->super;
|
---|
| 217 | break;
|
---|
| 218 | }
|
---|
| 219 |
|
---|
| 220 | proc = method_search_vm(mrb, &super, mrb_symbol(name));
|
---|
| 221 | if (!proc)
|
---|
| 222 | return mrb_nil_value();
|
---|
| 223 |
|
---|
| 224 | rklass = super;
|
---|
| 225 | while (super->tt == MRB_TT_ICLASS)
|
---|
| 226 | super = super->c;
|
---|
| 227 |
|
---|
| 228 | me = method_object_alloc(mrb, mrb_obj_class(mrb, self));
|
---|
| 229 | mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_owner"), mrb_obj_value(super));
|
---|
| 230 | mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_recv"), recv);
|
---|
| 231 | mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_name"), name);
|
---|
| 232 | mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_proc"), mrb_obj_value(proc));
|
---|
| 233 | mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_klass"), mrb_obj_value(rklass));
|
---|
| 234 |
|
---|
| 235 | return mrb_obj_value(me);
|
---|
| 236 | }
|
---|
| 237 |
|
---|
| 238 | static mrb_value
|
---|
| 239 | method_arity(mrb_state *mrb, mrb_value self)
|
---|
| 240 | {
|
---|
| 241 | mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
|
---|
| 242 | mrb_int arity = mrb_nil_p(proc) ? -1 : mrb_proc_arity(mrb_proc_ptr(proc));
|
---|
| 243 | return mrb_fixnum_value(arity);
|
---|
| 244 | }
|
---|
| 245 |
|
---|
| 246 | static mrb_value
|
---|
| 247 | method_source_location(mrb_state *mrb, mrb_value self)
|
---|
| 248 | {
|
---|
| 249 | mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
|
---|
| 250 | struct RProc *rproc;
|
---|
| 251 | struct RClass *orig;
|
---|
| 252 | mrb_value ret;
|
---|
| 253 |
|
---|
| 254 | if (mrb_nil_p(proc))
|
---|
| 255 | return mrb_nil_value();
|
---|
| 256 |
|
---|
| 257 | rproc = mrb_proc_ptr(proc);
|
---|
| 258 | orig = rproc->c;
|
---|
| 259 | rproc->c = mrb->proc_class;
|
---|
| 260 | ret = mrb_funcall(mrb, proc, "source_location", 0);
|
---|
| 261 | rproc->c = orig;
|
---|
| 262 | return ret;
|
---|
| 263 | }
|
---|
| 264 |
|
---|
| 265 | static mrb_value
|
---|
| 266 | method_parameters(mrb_state *mrb, mrb_value self)
|
---|
| 267 | {
|
---|
| 268 | mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
|
---|
| 269 | struct RProc *rproc;
|
---|
| 270 | struct RClass *orig;
|
---|
| 271 | mrb_value ret;
|
---|
| 272 |
|
---|
| 273 | if (mrb_nil_p(proc)) {
|
---|
| 274 | mrb_value rest = mrb_symbol_value(mrb_intern_lit(mrb, "rest"));
|
---|
| 275 | mrb_value arest = mrb_ary_new_from_values(mrb, 1, &rest);
|
---|
| 276 | return mrb_ary_new_from_values(mrb, 1, &arest);
|
---|
| 277 | }
|
---|
| 278 |
|
---|
| 279 | rproc = mrb_proc_ptr(proc);
|
---|
| 280 | orig = rproc->c;
|
---|
| 281 | rproc->c = mrb->proc_class;
|
---|
| 282 | ret = mrb_funcall(mrb, proc, "parameters", 0);
|
---|
| 283 | rproc->c = orig;
|
---|
| 284 | return ret;
|
---|
| 285 | }
|
---|
| 286 |
|
---|
| 287 | static mrb_value
|
---|
| 288 | method_to_s(mrb_state *mrb, mrb_value self)
|
---|
| 289 | {
|
---|
| 290 | mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_owner"));
|
---|
| 291 | mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_klass"));
|
---|
| 292 | mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
|
---|
| 293 | mrb_value str = mrb_str_new_lit(mrb, "#<");
|
---|
| 294 | struct RClass *rklass;
|
---|
| 295 |
|
---|
| 296 | mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, self));
|
---|
| 297 | mrb_str_cat_lit(mrb, str, ": ");
|
---|
| 298 | rklass = mrb_class_ptr(klass);
|
---|
| 299 | if (mrb_class_ptr(owner) == rklass) {
|
---|
| 300 | mrb_str_concat(mrb, str, owner);
|
---|
| 301 | mrb_str_cat_lit(mrb, str, "#");
|
---|
| 302 | mrb_str_concat(mrb, str, name);
|
---|
| 303 | }
|
---|
| 304 | else {
|
---|
| 305 | mrb_str_cat_cstr(mrb, str, mrb_class_name(mrb, rklass));
|
---|
| 306 | mrb_str_cat_lit(mrb, str, "(");
|
---|
| 307 | mrb_str_concat(mrb, str, owner);
|
---|
| 308 | mrb_str_cat_lit(mrb, str, ")#");
|
---|
| 309 | mrb_str_concat(mrb, str, name);
|
---|
| 310 | }
|
---|
| 311 | mrb_str_cat_lit(mrb, str, ">");
|
---|
| 312 | return str;
|
---|
| 313 | }
|
---|
| 314 |
|
---|
| 315 | static void
|
---|
| 316 | 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)
|
---|
| 317 | {
|
---|
| 318 | mrb_value ret;
|
---|
| 319 |
|
---|
| 320 | *owner = c;
|
---|
| 321 | *proc = method_search_vm(mrb, owner, name);
|
---|
| 322 | if (!*proc) {
|
---|
| 323 | if (unbound) {
|
---|
| 324 | goto name_error;
|
---|
| 325 | }
|
---|
| 326 | if (!mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "respond_to_missing?"))) {
|
---|
| 327 | goto name_error;
|
---|
| 328 | }
|
---|
| 329 | ret = mrb_funcall(mrb, obj, "respond_to_missing?", 2, mrb_symbol_value(name), mrb_true_value());
|
---|
| 330 | if (!mrb_test(ret)) {
|
---|
| 331 | goto name_error;
|
---|
| 332 | }
|
---|
| 333 | *owner = c;
|
---|
| 334 | }
|
---|
| 335 |
|
---|
| 336 | while ((*owner)->tt == MRB_TT_ICLASS)
|
---|
| 337 | *owner = (*owner)->c;
|
---|
| 338 |
|
---|
| 339 | return;
|
---|
| 340 |
|
---|
| 341 | name_error:
|
---|
| 342 | mrb_raisef(mrb, E_NAME_ERROR, "undefined method '%n' for class '%C'", name, c);
|
---|
| 343 | }
|
---|
| 344 |
|
---|
| 345 | static mrb_value
|
---|
| 346 | mrb_kernel_method(mrb_state *mrb, mrb_value self)
|
---|
| 347 | {
|
---|
| 348 | struct RClass *owner;
|
---|
| 349 | struct RProc *proc;
|
---|
| 350 | struct RObject *me;
|
---|
| 351 | mrb_sym name;
|
---|
| 352 |
|
---|
| 353 | mrb_get_args(mrb, "n", &name);
|
---|
| 354 |
|
---|
| 355 | mrb_search_method_owner(mrb, mrb_class(mrb, self), self, name, &owner, &proc, FALSE);
|
---|
| 356 |
|
---|
| 357 | me = method_object_alloc(mrb, mrb_class_get(mrb, "Method"));
|
---|
| 358 | mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_owner"), mrb_obj_value(owner));
|
---|
| 359 | mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_recv"), self);
|
---|
| 360 | mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_name"), mrb_symbol_value(name));
|
---|
| 361 | mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_proc"), proc ? mrb_obj_value(proc) : mrb_nil_value());
|
---|
| 362 | mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_klass"), mrb_obj_value(mrb_class(mrb, self)));
|
---|
| 363 |
|
---|
| 364 | return mrb_obj_value(me);
|
---|
| 365 | }
|
---|
| 366 |
|
---|
| 367 | static mrb_value
|
---|
| 368 | mrb_module_instance_method(mrb_state *mrb, mrb_value self)
|
---|
| 369 | {
|
---|
| 370 | struct RClass *owner;
|
---|
| 371 | struct RProc *proc;
|
---|
| 372 | struct RObject *ume;
|
---|
| 373 | mrb_sym name;
|
---|
| 374 |
|
---|
| 375 | mrb_get_args(mrb, "n", &name);
|
---|
| 376 |
|
---|
| 377 | mrb_search_method_owner(mrb, mrb_class_ptr(self), self, name, &owner, &proc, TRUE);
|
---|
| 378 |
|
---|
| 379 | ume = method_object_alloc(mrb, mrb_class_get(mrb, "UnboundMethod"));
|
---|
| 380 | mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_owner"), mrb_obj_value(owner));
|
---|
| 381 | mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_recv"), mrb_nil_value());
|
---|
| 382 | mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_name"), mrb_symbol_value(name));
|
---|
| 383 | mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_proc"), proc ? mrb_obj_value(proc) : mrb_nil_value());
|
---|
| 384 | mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_klass"), self);
|
---|
| 385 |
|
---|
| 386 | return mrb_obj_value(ume);
|
---|
| 387 | }
|
---|
| 388 |
|
---|
| 389 | static mrb_value
|
---|
| 390 | method_owner(mrb_state *mrb, mrb_value self)
|
---|
| 391 | {
|
---|
| 392 | return mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_owner"));
|
---|
| 393 | }
|
---|
| 394 |
|
---|
| 395 | static mrb_value
|
---|
| 396 | method_receiver(mrb_state *mrb, mrb_value self)
|
---|
| 397 | {
|
---|
| 398 | return mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_recv"));
|
---|
| 399 | }
|
---|
| 400 |
|
---|
| 401 | static mrb_value
|
---|
| 402 | method_name(mrb_state *mrb, mrb_value self)
|
---|
| 403 | {
|
---|
| 404 | return mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
|
---|
| 405 | }
|
---|
| 406 |
|
---|
| 407 | void
|
---|
| 408 | mrb_mruby_method_gem_init(mrb_state* mrb)
|
---|
| 409 | {
|
---|
| 410 | struct RClass *unbound_method = mrb_define_class(mrb, "UnboundMethod", mrb->object_class);
|
---|
| 411 | struct RClass *method = mrb_define_class(mrb, "Method", mrb->object_class);
|
---|
| 412 |
|
---|
| 413 | mrb_undef_class_method(mrb, unbound_method, "new");
|
---|
| 414 | mrb_define_method(mrb, unbound_method, "bind", unbound_method_bind, MRB_ARGS_REQ(1));
|
---|
| 415 | mrb_define_method(mrb, unbound_method, "super_method", method_super_method, MRB_ARGS_NONE());
|
---|
| 416 | mrb_define_method(mrb, unbound_method, "==", method_eql, MRB_ARGS_REQ(1));
|
---|
| 417 | mrb_define_method(mrb, unbound_method, "eql?", method_eql, MRB_ARGS_REQ(1));
|
---|
| 418 | mrb_define_method(mrb, unbound_method, "to_s", method_to_s, MRB_ARGS_NONE());
|
---|
| 419 | mrb_define_method(mrb, unbound_method, "inspect", method_to_s, MRB_ARGS_NONE());
|
---|
| 420 | mrb_define_method(mrb, unbound_method, "arity", method_arity, MRB_ARGS_NONE());
|
---|
| 421 | mrb_define_method(mrb, unbound_method, "source_location", method_source_location, MRB_ARGS_NONE());
|
---|
| 422 | mrb_define_method(mrb, unbound_method, "parameters", method_parameters, MRB_ARGS_NONE());
|
---|
| 423 | mrb_define_method(mrb, unbound_method, "bind_call", method_bcall, MRB_ARGS_REQ(1)|MRB_ARGS_ANY());
|
---|
| 424 | mrb_define_method(mrb, unbound_method, "owner", method_owner, MRB_ARGS_NONE());
|
---|
| 425 | mrb_define_method(mrb, unbound_method, "name", method_name, MRB_ARGS_NONE());
|
---|
| 426 |
|
---|
| 427 | mrb_undef_class_method(mrb, method, "new");
|
---|
| 428 | mrb_define_method(mrb, method, "==", method_eql, MRB_ARGS_REQ(1));
|
---|
| 429 | mrb_define_method(mrb, method, "eql?", method_eql, MRB_ARGS_REQ(1));
|
---|
| 430 | mrb_define_method(mrb, method, "to_s", method_to_s, MRB_ARGS_NONE());
|
---|
| 431 | mrb_define_method(mrb, method, "inspect", method_to_s, MRB_ARGS_NONE());
|
---|
| 432 | mrb_define_method(mrb, method, "call", method_call, MRB_ARGS_ANY());
|
---|
| 433 | mrb_define_method(mrb, method, "[]", method_call, MRB_ARGS_ANY());
|
---|
| 434 | mrb_define_method(mrb, method, "unbind", method_unbind, MRB_ARGS_NONE());
|
---|
| 435 | mrb_define_method(mrb, method, "super_method", method_super_method, MRB_ARGS_NONE());
|
---|
| 436 | mrb_define_method(mrb, method, "arity", method_arity, MRB_ARGS_NONE());
|
---|
| 437 | mrb_define_method(mrb, method, "source_location", method_source_location, MRB_ARGS_NONE());
|
---|
| 438 | mrb_define_method(mrb, method, "parameters", method_parameters, MRB_ARGS_NONE());
|
---|
| 439 | mrb_define_method(mrb, method, "owner", method_owner, MRB_ARGS_NONE());
|
---|
| 440 | mrb_define_method(mrb, method, "receiver", method_receiver, MRB_ARGS_NONE());
|
---|
| 441 | mrb_define_method(mrb, method, "name", method_name, MRB_ARGS_NONE());
|
---|
| 442 |
|
---|
| 443 | mrb_define_method(mrb, mrb->kernel_module, "method", mrb_kernel_method, MRB_ARGS_REQ(1));
|
---|
| 444 |
|
---|
| 445 | mrb_define_method(mrb, mrb->module_class, "instance_method", mrb_module_instance_method, MRB_ARGS_REQ(1));
|
---|
| 446 | }
|
---|
| 447 |
|
---|
| 448 | void
|
---|
| 449 | mrb_mruby_method_gem_final(mrb_state* mrb)
|
---|
| 450 | {
|
---|
| 451 | }
|
---|