1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Revert r31873 Module#mix

* class.c (rb_mix_module): revert Module#mix.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36216 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2012-06-25 08:49:32 +00:00
parent 7c3d0ce3cc
commit 82a408fb9d
5 changed files with 6 additions and 253 deletions

View file

@ -1,3 +1,7 @@
Mon Jun 25 17:49:28 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* class.c (rb_mix_module): revert Module#mix.
Mon Jun 25 16:57:38 2012 Nobuyoshi Nakada <nobu@ruby-lang.org> Mon Jun 25 16:57:38 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* proc.c (rb_mod_define_method): allow method transplanting from a * proc.c (rb_mod_define_method): allow method transplanting from a

134
class.c
View file

@ -120,7 +120,7 @@ rb_class_new(VALUE super)
} }
static void static void
rb_mod_clone_method(VALUE klass, ID mid, const rb_method_entry_t *me) clone_method(VALUE klass, ID mid, const rb_method_entry_t *me)
{ {
VALUE newiseqval; VALUE newiseqval;
if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) { if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) {
@ -138,7 +138,7 @@ rb_mod_clone_method(VALUE klass, ID mid, const rb_method_entry_t *me)
static int static int
clone_method_i(st_data_t key, st_data_t value, st_data_t data) clone_method_i(st_data_t key, st_data_t value, st_data_t data)
{ {
rb_mod_clone_method((VALUE)data, (ID)key, (const rb_method_entry_t *)value); clone_method((VALUE)data, (ID)key, (const rb_method_entry_t *)value);
return ST_CONTINUE; return ST_CONTINUE;
} }
@ -696,136 +696,6 @@ rb_include_module(VALUE klass, VALUE module)
if (changed) rb_clear_cache(); if (changed) rb_clear_cache();
} }
struct mixing_arg {
st_table *mtbl;
ID id;
st_table *aliasing;
VALUE klass;
};
static int
check_mix_const_i(st_data_t key, st_data_t value, st_data_t arg)
{
struct mixing_arg *argp = (struct mixing_arg *)arg;
ID id = (ID)key;
st_table *aliasing = argp->aliasing;
st_data_t alias;
if (!rb_is_const_id(id)) return ST_CONTINUE;
if (aliasing && st_lookup(aliasing, ID2SYM(id), &alias)) {
id = rb_to_id(alias);
}
if (st_lookup(argp->mtbl, id, NULL)) {
argp->id = id;
return ST_STOP;
}
return ST_CONTINUE;
}
static int
do_mix_const_i(st_data_t key, st_data_t value, st_data_t arg)
{
struct mixing_arg *argp = (struct mixing_arg *)arg;
ID id = (ID)key;
st_table *aliasing = argp->aliasing;
st_data_t old, alias;
if (!rb_is_const_id(id)) return ST_CONTINUE;
if (aliasing && st_lookup(aliasing, ID2SYM(id), &alias)) {
id = rb_to_id(alias);
}
if (st_lookup(argp->mtbl, id, &old)) {
argp->id = id;
return ST_STOP;
}
st_insert(argp->mtbl, id, value);
return ST_CONTINUE;
}
static int
check_mix_method_i(st_data_t key, st_data_t value, st_data_t arg)
{
struct mixing_arg *argp = (struct mixing_arg *)arg;
ID id = (ID)key;
st_table *aliasing = argp->aliasing;
st_data_t alias;
if (aliasing && st_lookup(aliasing, ID2SYM(id), &alias)) {
if (NIL_P(alias)) return ST_CONTINUE;
id = rb_to_id(alias);
}
if (st_lookup(argp->mtbl, id, NULL)) {
argp->id = id;
return ST_STOP;
}
return ST_CONTINUE;
}
static int
do_mix_method_i(st_data_t key, st_data_t value, st_data_t arg)
{
struct mixing_arg *argp = (struct mixing_arg *)arg;
ID id = (ID)key;
st_table *aliasing = argp->aliasing;
st_data_t old, alias;
if (aliasing && st_lookup(aliasing, ID2SYM(id), &alias)) {
if (NIL_P(alias)) return ST_CONTINUE;
id = rb_to_id(alias);
}
if (st_lookup(argp->mtbl, id, &old)) {
argp->id = id;
return ST_STOP;
}
rb_mod_clone_method(argp->klass, id, (rb_method_entry_t *)value);
return ST_CONTINUE;
}
void
rb_mix_module(VALUE klass, VALUE module, st_table *constants, st_table *methods)
{
st_table *mtbl_from;
struct mixing_arg methodarg, constarg;
rb_frozen_class_p(klass);
if (!OBJ_UNTRUSTED(klass)) {
rb_secure(4);
}
if (!RB_TYPE_P(module, T_MODULE)) {
Check_Type(module, T_MODULE);
}
OBJ_INFECT(klass, module);
mtbl_from = RMODULE_M_TBL(module);
methodarg.mtbl = RMODULE_M_TBL(klass);
methodarg.id = 0;
methodarg.aliasing = methods;
methodarg.klass = klass;
constarg.mtbl = RMODULE_IV_TBL(klass);
constarg.id = 0;
constarg.aliasing = constants;
st_foreach(mtbl_from, check_mix_method_i, (st_data_t)&methodarg);
if (methodarg.id) {
rb_raise(rb_eArgError, "method would conflict - %s", rb_id2name(methodarg.id));
}
st_foreach(mtbl_from, check_mix_const_i, (st_data_t)&constarg);
if (constarg.id) {
rb_raise(rb_eArgError, "constant would conflict - %s", rb_id2name(constarg.id));
}
st_foreach(mtbl_from, do_mix_method_i, (st_data_t)&methodarg);
if (methodarg.id) {
rb_raise(rb_eArgError, "method would conflict - %s", rb_id2name(methodarg.id));
}
st_foreach(mtbl_from, do_mix_const_i, (st_data_t)&constarg);
if (constarg.id) {
rb_raise(rb_eArgError, "constant would conflict - %s", rb_id2name(constarg.id));
}
rb_vm_inc_const_missing_count();
}
/* /*
* call-seq: * call-seq:
* mod.included_modules -> array * mod.included_modules -> array

61
eval.c
View file

@ -954,66 +954,6 @@ rb_mod_include(int argc, VALUE *argv, VALUE module)
return module; return module;
} }
/*
* call-seq:
* mix(module, ...) -> module
*
* Mix +Module+> into self.
*/
static VALUE
rb_mod_mix_into(int argc, VALUE *argv, VALUE klass)
{
VALUE module, tmp, constants = Qnil, methods = Qnil;
st_table *const_tbl = 0, *method_tbl = 0;
int i = 0;
rb_check_arity(argc, 1, 3);
module = argv[i++];
switch (TYPE(module)) {
case T_CLASS:
case T_MODULE:
break;
default:
Check_Type(module, T_CLASS);
break;
}
if (i < argc) {
constants = argv[i++];
if (!NIL_P(tmp = rb_check_array_type(constants))) {
constants = tmp;
}
else if (!NIL_P(methods = rb_check_hash_type(constants))) {
constants = Qnil;
}
else {
Check_Type(constants, T_HASH);
}
}
if (i < argc && NIL_P(methods)) {
methods = argv[i++];
if (NIL_P(tmp = rb_check_hash_type(methods))) {
Check_Type(methods, T_HASH);
}
methods = tmp;
}
if (i < argc) rb_raise(rb_eArgError, "wrong arguments");
if (!NIL_P(constants)) {
VALUE hash = rb_hash_new();
for (i = 0; i < RARRAY_LEN(constants); ++i) {
rb_hash_update_by(hash, RARRAY_PTR(constants)[i], NULL);
}
const_tbl = RHASH_TBL(RB_GC_GUARD(constants) = hash);
}
if (!NIL_P(methods)) {
method_tbl = RHASH_TBL(RB_GC_GUARD(methods));
}
rb_mix_module(klass, module, const_tbl, method_tbl);
return module;
}
void void
rb_obj_call_init(VALUE obj, int argc, VALUE *argv) rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
{ {
@ -1273,7 +1213,6 @@ Init_eval(void)
rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1); 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); rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
rb_define_private_method(rb_cModule, "include", rb_mod_include, -1); rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
rb_define_private_method(rb_cModule, "mix", rb_mod_mix_into, -1);
rb_undef_method(rb_cClass, "module_function"); rb_undef_method(rb_cClass, "module_function");

View file

@ -102,6 +102,5 @@ void rb_mark_method_entry(const rb_method_entry_t *me);
void rb_free_method_entry(rb_method_entry_t *me); void rb_free_method_entry(rb_method_entry_t *me);
void rb_sweep_method_entry(void *vm); void rb_sweep_method_entry(void *vm);
void rb_free_m_table(st_table *tbl); void rb_free_m_table(st_table *tbl);
void rb_mix_module(VALUE klass, VALUE module, struct st_table *constants, struct st_table *methods);
#endif /* METHOD_H */ #endif /* METHOD_H */

View file

@ -1238,63 +1238,4 @@ class TestModule < Test::Unit::TestCase
INPUT INPUT
assert_in_out_err([], src, ["NameError"], []) assert_in_out_err([], src, ["NameError"], [])
end end
def test_mix_method
american = Module.new do
attr_accessor :address
end
japanese = Module.new do
attr_accessor :address
end
japanese_american = Class.new
assert_nothing_raised(ArgumentError) {
japanese_american.class_eval {mix american}
}
assert_raise(ArgumentError) {
japanese_american.class_eval {mix japanese}
}
japanese_american = Class.new
assert_nothing_raised(ArgumentError) {
japanese_american.class_eval {
mix american, :address => :us_address, :address= => :us_address=
}
}
assert_nothing_raised(ArgumentError) {
japanese_american.class_eval {
mix japanese, :address => :jp_address, :address= => :jp_address=
}
}
japanese_american = Class.new
assert_nothing_raised(ArgumentError) {
japanese_american.class_eval {
mix japanese, :address => nil, :address= => nil
}
}
assert_raise(NoMethodError) {
japanese_american.new.address
}
assert_nothing_raised(ArgumentError) {
japanese_american.class_eval {
mix american
}
}
end
def test_mix_const
foo = Module.new do
const_set(:D, 55)
end
bar = Class.new do
const_set(:D, 42)
end
assert_nothing_raised(ArgumentError) {
bar.class_eval {
mix foo
}
}
assert_equal(42, bar::D)
end
end end