2306 |
2306 |
*
|
2307 |
2307 |
*/
|
2308 |
2308 |
|
|
2309 |
static void
|
|
2310 |
convert_umethod_to_method_components(VALUE method, VALUE recv, VALUE *methclass_out, VALUE *klass_out, const rb_method_entry_t **me_out)
|
|
2311 |
{
|
|
2312 |
struct METHOD *data;
|
|
2313 |
|
|
2314 |
TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
|
|
2315 |
|
|
2316 |
VALUE methclass = data->me->owner;
|
|
2317 |
VALUE klass = CLASS_OF(recv);
|
|
2318 |
|
|
2319 |
if (!RB_TYPE_P(methclass, T_MODULE) &&
|
|
2320 |
methclass != CLASS_OF(recv) && !rb_obj_is_kind_of(recv, methclass)) {
|
|
2321 |
if (FL_TEST(methclass, FL_SINGLETON)) {
|
|
2322 |
rb_raise(rb_eTypeError,
|
|
2323 |
"singleton method called for a different object");
|
|
2324 |
}
|
|
2325 |
else {
|
|
2326 |
rb_raise(rb_eTypeError, "bind argument must be an instance of % "PRIsVALUE,
|
|
2327 |
methclass);
|
|
2328 |
}
|
|
2329 |
}
|
|
2330 |
|
|
2331 |
const rb_method_entry_t *me = rb_method_entry_clone(data->me);
|
|
2332 |
|
|
2333 |
if (RB_TYPE_P(me->owner, T_MODULE)) {
|
|
2334 |
VALUE ic = rb_class_search_ancestor(klass, me->owner);
|
|
2335 |
if (ic) {
|
|
2336 |
klass = ic;
|
|
2337 |
}
|
|
2338 |
else {
|
|
2339 |
klass = rb_include_class_new(methclass, klass);
|
|
2340 |
}
|
|
2341 |
me = (const rb_method_entry_t *) rb_method_entry_complement_defined_class(me, me->called_id, klass);
|
|
2342 |
}
|
|
2343 |
|
|
2344 |
*methclass_out = methclass;
|
|
2345 |
*klass_out = klass;
|
|
2346 |
*me_out = me;
|
|
2347 |
}
|
|
2348 |
|
2309 |
2349 |
/*
|
2310 |
2350 |
* call-seq:
|
2311 |
2351 |
* umeth.bind(obj) -> method
|
... | ... | |
2344 |
2384 |
static VALUE
|
2345 |
2385 |
umethod_bind(VALUE method, VALUE recv)
|
2346 |
2386 |
{
|
2347 |
|
struct METHOD *data, *bound;
|
2348 |
2387 |
VALUE methclass, klass;
|
|
2388 |
const rb_method_entry_t *me;
|
|
2389 |
convert_umethod_to_method_components(method, recv, &methclass, &klass, &me);
|
2349 |
2390 |
|
2350 |
|
TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
|
2351 |
|
|
2352 |
|
methclass = data->me->owner;
|
|
2391 |
struct METHOD *bound;
|
|
2392 |
method = TypedData_Make_Struct(rb_cMethod, struct METHOD, &method_data_type, bound);
|
|
2393 |
RB_OBJ_WRITE(method, &bound->recv, recv);
|
|
2394 |
RB_OBJ_WRITE(method, &bound->klass, klass);
|
|
2395 |
RB_OBJ_WRITE(method, &bound->me, me);
|
2353 |
2396 |
|
2354 |
|
if (!RB_TYPE_P(methclass, T_MODULE) &&
|
2355 |
|
methclass != CLASS_OF(recv) && !rb_obj_is_kind_of(recv, methclass)) {
|
2356 |
|
if (FL_TEST(methclass, FL_SINGLETON)) {
|
2357 |
|
rb_raise(rb_eTypeError,
|
2358 |
|
"singleton method called for a different object");
|
2359 |
|
}
|
2360 |
|
else {
|
2361 |
|
rb_raise(rb_eTypeError, "bind argument must be an instance of % "PRIsVALUE,
|
2362 |
|
methclass);
|
2363 |
|
}
|
2364 |
|
}
|
|
2397 |
return method;
|
|
2398 |
}
|
2365 |
2399 |
|
2366 |
|
klass = CLASS_OF(recv);
|
|
2400 |
/*
|
|
2401 |
* call-seq:
|
|
2402 |
* umeth.apply(obj, args, ...) -> obj
|
|
2403 |
*
|
|
2404 |
* Bind <i>umeth</i> to <i>obj</i> and then invokes the method with the
|
|
2405 |
* specified arguments.
|
|
2406 |
* This is equivalent to <code>umeth.bind(obj).call(args, ...)</code>.
|
|
2407 |
*/
|
|
2408 |
static VALUE
|
|
2409 |
umethod_apply(int argc, VALUE *argv, VALUE method)
|
|
2410 |
{
|
|
2411 |
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
|
2412 |
VALUE recv = argv[0];
|
|
2413 |
argc--;
|
|
2414 |
argv++;
|
2367 |
2415 |
|
2368 |
|
method = TypedData_Make_Struct(rb_cMethod, struct METHOD, &method_data_type, bound);
|
2369 |
|
RB_OBJ_WRITE(method, &bound->recv, recv);
|
2370 |
|
RB_OBJ_WRITE(method, &bound->klass, data->klass);
|
2371 |
|
RB_OBJ_WRITE(method, &bound->me, rb_method_entry_clone(data->me));
|
|
2416 |
VALUE methclass, klass;
|
|
2417 |
const rb_method_entry_t *me;
|
|
2418 |
convert_umethod_to_method_components(method, recv, &methclass, &klass, &me);
|
|
2419 |
struct METHOD bound = { recv, klass, 0, me };
|
2372 |
2420 |
|
2373 |
|
if (RB_TYPE_P(bound->me->owner, T_MODULE)) {
|
2374 |
|
VALUE ic = rb_class_search_ancestor(klass, bound->me->owner);
|
2375 |
|
if (ic) {
|
2376 |
|
klass = ic;
|
2377 |
|
}
|
2378 |
|
else {
|
2379 |
|
klass = rb_include_class_new(methclass, klass);
|
2380 |
|
}
|
2381 |
|
RB_OBJ_WRITE(method, &bound->me, rb_method_entry_complement_defined_class(bound->me, bound->me->called_id, klass));
|
2382 |
|
}
|
|
2421 |
VALUE passed_procval = rb_block_given_p() ? rb_block_proc() : Qnil;
|
2383 |
2422 |
|
2384 |
|
return method;
|
|
2423 |
rb_execution_context_t *ec = GET_EC();
|
|
2424 |
return call_method_data(ec, &bound, argc, argv, passed_procval);
|
2385 |
2425 |
}
|
2386 |
2426 |
|
2387 |
2427 |
/*
|
... | ... | |
3671 |
3711 |
rb_define_method(rb_cUnboundMethod, "original_name", method_original_name, 0);
|
3672 |
3712 |
rb_define_method(rb_cUnboundMethod, "owner", method_owner, 0);
|
3673 |
3713 |
rb_define_method(rb_cUnboundMethod, "bind", umethod_bind, 1);
|
|
3714 |
rb_define_method(rb_cUnboundMethod, "apply", umethod_apply, -1);
|
3674 |
3715 |
rb_define_method(rb_cUnboundMethod, "source_location", rb_method_location, 0);
|
3675 |
3716 |
rb_define_method(rb_cUnboundMethod, "parameters", rb_method_parameters, 0);
|
3676 |
3717 |
rb_define_method(rb_cUnboundMethod, "super_method", method_super_method, 0);
|