Revision: 3475 http://trac.macosforge.org/projects/ruby/changeset/3475 Author: martinlagardette@apple.com Date: 2010-02-10 01:21:54 -0800 (Wed, 10 Feb 2010) Log Message: ----------- - `class.c`: Corrected Class#clone and Module#clone, they now copy methods and constants - `class.rb`: Added test cases for Class#clone, Module#clone, Class#dup and Module#dup - `vm.cpp`: Corrected the output of Class#instance_methods and Module#instance_methods, by not including the superclass methods Modified Paths: -------------- MacRuby/trunk/class.c MacRuby/trunk/test_vm/class.rb MacRuby/trunk/vm.cpp Modified: MacRuby/trunk/class.c =================================================================== --- MacRuby/trunk/class.c 2010-02-10 06:38:36 UTC (rev 3474) +++ MacRuby/trunk/class.c 2010-02-10 09:21:54 UTC (rev 3475) @@ -298,6 +298,9 @@ VALUE rb_mod_init_copy(VALUE clone, SEL sel, VALUE orig) { + static ID classpath = 0; + static ID classid = 0; + rb_obj_init_copy(clone, 0, orig); { VALUE super; @@ -319,26 +322,28 @@ } RCLASS_SET_VERSION(clone, version_flag); - } -#if 0 // TODO - if (RCLASS_IV_TBL(orig)) { - ID id; - GC_WB(&RCLASS_IV_TBL(clone), st_copy(RCLASS_IV_TBL(orig))); - id = rb_intern("__classpath__"); - st_delete(RCLASS_IV_TBL(clone), (st_data_t*)&id, 0); - id = rb_intern("__classid__"); - st_delete(RCLASS_IV_TBL(clone), (st_data_t*)&id, 0); + rb_vm_copy_methods((Class)orig, (Class)clone); + CFMutableDictionaryRef ivar_dict = rb_class_ivar_dict(orig); + if (ivar_dict != NULL) { + CFMutableDictionaryRef cloned_ivar_dict; + + if (classpath == 0) { + classpath = rb_intern("__classpath__"); + } + if (classid == 0) { + classid = rb_intern("__classid__"); + } + cloned_ivar_dict = CFDictionaryCreateMutableCopy(NULL, 0, + (CFDictionaryRef)ivar_dict); + // Remove the classpath & classid (name) so that they are not + // copied over the new module / class + CFDictionaryRemoveValue(cloned_ivar_dict, (const void *)classpath); + CFDictionaryRemoveValue(cloned_ivar_dict, (const void *)classid); + CFMakeCollectable(cloned_ivar_dict); + rb_class_ivar_set_dict(clone, cloned_ivar_dict); + } } - if (RCLASS_M_TBL(orig)) { - struct clone_method_data data; - GC_WB(&RCLASS_M_TBL(clone), st_init_numtable()); - data.tbl = RCLASS_M_TBL(clone); - data.klass = clone; - st_foreach(RCLASS_M_TBL(orig), clone_method, - (st_data_t)&data); - } -#endif return clone; } Modified: MacRuby/trunk/test_vm/class.rb =================================================================== --- MacRuby/trunk/test_vm/class.rb 2010-02-10 06:38:36 UTC (rev 3474) +++ MacRuby/trunk/test_vm/class.rb 2010-02-10 09:21:54 UTC (rev 3475) @@ -104,3 +104,66 @@ end Foo.new } + + +# Test cloning +assert "B, [:CONST_M], [:ok]", %{ + module M + CONST_M = 1 + def ok; end + end + B = M.clone + puts B.to_s + ", " + B.constants.to_s + ", " + B.instance_methods(false).to_s +} + +assert "B, [:CONST_A], [:ok]", %{ + class A + CONST_A = 1 + def ok; end + end + B = A.clone + puts B.to_s + ", " + B.constants.to_s + ", " + B.instance_methods(false).to_s +} + +assert "B, [:CONST_C, :CONST_A], []", %{ + class A + CONST_A = 1 + def ok; end + end + class C < A + CONST_C = 1 + end + B = C.clone + puts B.to_s + ", " + B.constants.to_s + ", " + B.instance_methods(false).to_s +} + +# Test dup +assert "B, [:CONST_M], [:ok]", %{ + module M + CONST_M = 1 + def ok; end + end + B = M.dup + puts B.to_s + ", " + B.constants.to_s + ", " + B.instance_methods(false).to_s +} + +assert "B, [:CONST_A], [:ok]", %{ + class A + CONST_A = 1 + def ok; end + end + B = A.dup + puts B.to_s + ", " + B.constants.to_s + ", " + B.instance_methods(false).to_s +} + +assert "B, [:CONST_C, :CONST_A], []", %{ + class A + CONST_A = 1 + def ok; end + end + class C < A + CONST_C = 1 + end + B = C.dup + puts B.to_s + ", " + B.constants.to_s + ", " + B.instance_methods(false).to_s +} Modified: MacRuby/trunk/vm.cpp =================================================================== --- MacRuby/trunk/vm.cpp 2010-02-10 06:38:36 UTC (rev 3474) +++ MacRuby/trunk/vm.cpp 2010-02-10 09:21:54 UTC (rev 3475) @@ -2302,25 +2302,20 @@ } Class k = klass; - do { - std::multimap<Class, SEL>::iterator iter = - method_source_sels.find(k); + std::multimap<Class, SEL>::iterator iter = + method_source_sels.find(k); - if (iter != method_source_sels.end()) { - std::multimap<Class, SEL>::iterator last = - method_source_sels.upper_bound(k); + if (iter != method_source_sels.end()) { + std::multimap<Class, SEL>::iterator last = + method_source_sels.upper_bound(k); - for (; iter != last; ++iter) { - SEL sel = iter->second; - rb_vm_method_source_t *src = method_source_get(k, sel); - assert(src != NULL); - push_method(ary, sel, src->flags, filter); - } + for (; iter != last; ++iter) { + SEL sel = iter->second; + rb_vm_method_source_t *src = method_source_get(k, sel); + assert(src != NULL); + push_method(ary, sel, src->flags, filter); } - - k = class_getSuperclass(k); } - while (k != NULL); } extern "C"
participants (1)
-
source_changes@macosforge.org