ruby-changes:37251
From: nobu <ko1@a...>
Date: Mon, 19 Jan 2015 22:08:47 +0900 (JST)
Subject: [ruby-changes:37251] nobu:r49332 (trunk): class.c: prepend for each classes
nobu 2015-01-19 22:08:28 +0900 (Mon, 19 Jan 2015) New Revision: 49332 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=49332 Log: class.c: prepend for each classes * class.c (include_modules_at): allow prepend each modules upto once for each classes. [EXPERIMENTAL] Modified files: trunk/ChangeLog trunk/class.c trunk/test/ruby/test_module.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 49331) +++ ChangeLog (revision 49332) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Mon Jan 19 22:08:26 2015 Nobuyoshi Nakada <nobu@r...> + + * class.c (include_modules_at): allow prepend each modules upto + once for each classes. [EXPERIMENTAL] + Sun Jan 18 18:32:20 2015 SHIBATA Hiroshi <shibata.hiroshi@g...> * math.c (math_atan2): revive documentation before r49220. Index: class.c =================================================================== --- class.c (revision 49331) +++ class.c (revision 49332) @@ -817,7 +817,7 @@ rb_include_class_new(VALUE module, VALUE https://github.com/ruby/ruby/blob/trunk/class.c#L817 return (VALUE)klass; } -static int include_modules_at(const VALUE klass, VALUE c, VALUE module); +static int include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super); void rb_include_module(VALUE klass, VALUE module) @@ -832,7 +832,7 @@ rb_include_module(VALUE klass, VALUE mod https://github.com/ruby/ruby/blob/trunk/class.c#L832 OBJ_INFECT(klass, module); - changed = include_modules_at(klass, RCLASS_ORIGIN(klass), module); + changed = include_modules_at(klass, RCLASS_ORIGIN(klass), module, TRUE); if (changed < 0) rb_raise(rb_eArgError, "cyclic include detected"); } @@ -845,7 +845,7 @@ add_refined_method_entry_i(st_data_t key https://github.com/ruby/ruby/blob/trunk/class.c#L845 } static int -include_modules_at(const VALUE klass, VALUE c, VALUE module) +include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super) { VALUE p, iclass; int method_changed = 0, constant_changed = 0; @@ -860,28 +860,27 @@ include_modules_at(const VALUE klass, VA https://github.com/ruby/ruby/blob/trunk/class.c#L860 return -1; /* ignore if the module included already in superclasses */ for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) { - switch (BUILTIN_TYPE(p)) { - case T_ICLASS: + int type = BUILTIN_TYPE(p); + if (type == T_ICLASS) { if (RCLASS_M_TBL_WRAPPER(p) == RCLASS_M_TBL_WRAPPER(module)) { if (!superclass_seen) { c = p; /* move insertion point */ } goto skip; } - break; - case T_CLASS: + } + else if (type == T_CLASS) { + if (!search_super) break; superclass_seen = TRUE; - break; } } iclass = rb_include_class_new(module, RCLASS_SUPER(c)); c = RCLASS_SET_SUPER(c, iclass); - if (BUILTIN_TYPE(module) == T_ICLASS) { - rb_module_add_to_subclasses_list(RBASIC(module)->klass, iclass); - } - else { - rb_module_add_to_subclasses_list(module, iclass); + { + VALUE m = module; + if (BUILTIN_TYPE(m) == T_ICLASS) m = RBASIC(m)->klass; + rb_module_add_to_subclasses_list(m, iclass); } if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) { @@ -957,7 +956,7 @@ rb_prepend_module(VALUE klass, VALUE mod https://github.com/ruby/ruby/blob/trunk/class.c#L956 st_foreach(RCLASS_M_TBL(origin), move_refined_method, (st_data_t) RCLASS_M_TBL(klass)); } - changed = include_modules_at(klass, klass, module); + changed = include_modules_at(klass, klass, module, FALSE); if (changed < 0) rb_raise(rb_eArgError, "cyclic prepend detected"); if (changed) { Index: test/ruby/test_module.rb =================================================================== --- test/ruby/test_module.rb (revision 49331) +++ test/ruby/test_module.rb (revision 49332) @@ -1725,6 +1725,17 @@ class TestModule < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_module.rb#L1725 assert_equal('hello!', foo.new.hello, bug9236) end + def test_multiple_prepend + m = labeled_module("M") + c1 = labeled_class("C1") { + prepend m + } + c2 = labeled_class("C2", c1) { + prepend m + } + assert_equal([m, c2, m, c1], c2.ancestors[0, 4]) + end + def test_class_variables m = Module.new m.class_variable_set(:@@foo, 1) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/