class.c (extend_object): remove method; implement Kernel#extend in C

This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-04-25 18:50:16 +09:00
parent 6c25b5896a
commit 6c72f8b378
5 changed files with 50 additions and 61 deletions
+1
View File
@@ -28,6 +28,7 @@ mrb_method_t mrb_vm_find_method(mrb_state *mrb, struct RClass *c, struct RClass
mrb_value mrb_mod_const_missing(mrb_state *mrb, mrb_value mod);
mrb_value mrb_const_missing(mrb_state *mrb, mrb_value mod, mrb_sym sym);
size_t mrb_class_mt_memsize(mrb_state*, struct RClass*);
mrb_value mrb_obj_extend(mrb_state*, mrb_value obj);
#endif
mrb_value mrb_obj_equal_m(mrb_state *mrb, mrb_value);
-36
View File
@@ -1,36 +0,0 @@
module Kernel
##
# call-seq:
# obj.extend(module, ...) -> obj
#
# Adds to _obj_ the instance methods from each module given as a
# parameter.
#
# module Mod
# def hello
# "Hello from Mod.\n"
# end
# end
#
# class Klass
# def hello
# "Hello from Klass.\n"
# end
# end
#
# k = Klass.new
# k.hello #=> "Hello from Klass.\n"
# k.extend(Mod) #=> #<Klass:0x401b3bc8>
# k.hello #=> "Hello from Mod.\n"
#
# ISO 15.3.1.3.13
def extend(*args)
args.reverse!
obj = self
args.each do |m|
m.__send__(:extend_object, obj)
m.__send__(:extended, obj)
end
self
end
end
+47 -12
View File
@@ -1625,6 +1625,53 @@ mrb_mod_include(mrb_state *mrb, mrb_value mod)
return mod;
}
/* 15.3.1.3.13 */
/*
* call-seq:
* obj.extend(module, ...) -> obj
*
* Adds to _obj_ the instance methods from each module given as a
* parameter.
*
* module Mod
* def hello
* "Hello from Mod.\n"
* end
* end
*
* class Klass
* def hello
* "Hello from Klass.\n"
* end
* end
*
* k = Klass.new
* k.hello #=> "Hello from Klass.\n"
* k.extend(Mod) #=> #<Klass:0x401b3bc8>
* k.hello #=> "Hello from Mod.\n"
*
*/
mrb_value
mrb_obj_extend(mrb_state *mrb, mrb_value obj)
{
mrb_int argc;
mrb_value *argv;
mrb_sym extended = MRB_SYM(extended);
mrb_get_args(mrb, "*", &argv, &argc);
mrb_value cc = mrb_singleton_class(mrb, obj);
while (argc--) {
mrb_value mod = argv[argc];
mrb_check_type(mrb, mod, MRB_TT_MODULE);
mrb_include_module(mrb, mrb_class_ptr(cc), mrb_class_ptr(mod));
if (!mrb_func_basic_p(mrb, cc, extended, mrb_do_nothing)) {
mrb_funcall_argv(mrb, cc, extended, 1, &mod);
}
}
return obj;
}
/* 15.2.2.4.28 */
/*
* call-seq:
@@ -1681,16 +1728,6 @@ mrb_mod_ancestors(mrb_state *mrb, mrb_value self)
return result;
}
static mrb_value
mrb_mod_extend_object(mrb_state *mrb, mrb_value mod)
{
mrb_value obj = mrb_get_arg1(mrb);
mrb_check_type(mrb, mod, MRB_TT_MODULE);
mrb_include_module(mrb, mrb_class_ptr(mrb_singleton_class(mrb, obj)), mrb_class_ptr(mod));
return mod;
}
static mrb_value
mrb_mod_initialize(mrb_state *mrb, mrb_value mod)
{
@@ -3174,7 +3211,6 @@ mrb_init_class(mrb_state *mrb)
init_class_new(mrb, cls);
MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE);
mrb_define_private_method_id(mrb, mod, MRB_SYM(extend_object), mrb_mod_extend_object, MRB_ARGS_REQ(1)); /* 15.2.2.4.25 */
mrb_define_private_method_id(mrb, mod, MRB_SYM(extended), mrb_do_nothing, MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */
mrb_define_private_method_id(mrb, mod, MRB_SYM(prepended), mrb_do_nothing, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, mod, MRB_SYM_Q(include), mrb_mod_include_p, MRB_ARGS_REQ(1)); /* 15.2.2.4.28 */
@@ -3211,7 +3247,6 @@ mrb_init_class(mrb_state *mrb)
mrb_define_private_method_id(mrb, mod, MRB_SYM(method_undefined), mrb_do_nothing, MRB_ARGS_REQ(1));
mrb_define_private_method_id(mrb, mod, MRB_SYM(const_added), mrb_do_nothing, MRB_ARGS_REQ(1));
mrb_undef_method_id(mrb, cls, MRB_SYM(extend_object));
mrb_undef_method_id(mrb, cls, MRB_SYM(module_function));
mrb->top_self = MRB_OBJ_ALLOC(mrb, MRB_TT_OBJECT, mrb->object_class);
+2 -1
View File
@@ -591,6 +591,7 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method_id(mrb, krn, MRB_SYM_Q(eql), mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.10 */
mrb_define_method_id(mrb, krn, MRB_SYM(freeze), mrb_obj_freeze, MRB_ARGS_NONE());
mrb_define_method_id(mrb, krn, MRB_SYM_Q(frozen), mrb_obj_frozen, MRB_ARGS_NONE());
mrb_define_method_id(mrb, krn, MRB_SYM(extend), mrb_obj_extend, MRB_ARGS_ANY()); /* 15.3.1.3.13 */
mrb_define_method_id(mrb, krn, MRB_SYM(hash), mrb_obj_hash, MRB_ARGS_NONE()); /* 15.3.1.3.15 */
mrb_define_private_method_id(mrb, krn, MRB_SYM(initialize_copy), mrb_obj_init_copy, MRB_ARGS_REQ(1)); /* 15.3.1.3.16 */
mrb_define_method_id(mrb, krn, MRB_SYM(inspect), mrb_obj_inspect, MRB_ARGS_NONE()); /* 15.3.1.3.17 */
@@ -611,7 +612,7 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method_id(mrb, krn, MRB_SYM(to_s), mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */
mrb_define_method_id(mrb, krn, MRB_SYM(__case_eqq), mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */
mrb_define_method_id(mrb, krn, MRB_SYM(__to_int), mrb_ensure_int_type, MRB_ARGS_NONE()); /* internal */
mrb_define_private_method_id(mrb, krn, MRB_SYM_Q(respond_to_missing), mrb_false, MRB_ARGS_ARG(1,1));
mrb_define_private_method_id(mrb, krn, MRB_SYM_Q(respond_to_missing), mrb_false, MRB_ARGS_ARG(1,1));
mrb_define_method_id(mrb, krn, MRB_SYM_Q(__inspect_recursive), mrb_obj_inspect_recursive_p, MRB_ARGS_NONE());
mrb_include_module(mrb, mrb->object_class, mrb->kernel_module);
-12
View File
@@ -295,18 +295,6 @@ assert('Module#const_missing', '15.2.2.4.22') do
assert_equal 42, Test4ConstMissing.const_get(:ConstDoesntExist)
end
assert('Module#extend_object', '15.2.2.4.25') do
cls = Class.new
mod = Module.new { def foo; end }
a = cls.new
b = cls.new
mod.__send__(:extend_object,b)
assert_false a.respond_to?(:foo)
assert_true b.respond_to?(:foo)
assert_raise(FrozenError) { mod.__send__(:extend_object,cls.new.freeze) }
assert_raise(FrozenError, TypeError) { mod.__send__(:extend_object,1) }
end
assert('Module#include', '15.2.2.4.27') do
module Test4Include
Const4Include = 42