[macruby-changes] [543] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Mon Sep 1 20:30:10 PDT 2008


Revision: 543
          http://trac.macosforge.org/projects/ruby/changeset/543
Author:   lsansonetti at apple.com
Date:     2008-09-01 20:30:09 -0700 (Mon, 01 Sep 2008)
Log Message:
-----------
fixes for #121, #117 and #52

Modified Paths:
--------------
    MacRuby/trunk/class.c
    MacRuby/trunk/objc.m
    MacRuby/trunk/object.c
    MacRuby/trunk/test/ruby/test_objc.rb
    MacRuby/trunk/vm_eval.c
    MacRuby/trunk/vm_insnhelper.c

Modified: MacRuby/trunk/class.c
===================================================================
--- MacRuby/trunk/class.c	2008-09-01 21:08:39 UTC (rev 542)
+++ MacRuby/trunk/class.c	2008-09-02 03:30:09 UTC (rev 543)
@@ -61,17 +61,27 @@
     return (VALUE)obj;
 }
 
-static VALUE
-rb_objc_init(VALUE rcv)
+static BOOL
+rb_obj_imp_isEqual(void *rcv, SEL sel, void *obj)
 {
-    rb_funcall(rcv, idInitialize, 0);
+    return rb_funcall((VALUE)rcv, idEq, 1, OC2RB(obj)) == Qtrue;
+}
+
+static void *
+rb_obj_imp_init(void *rcv, SEL sel)
+{
+    rb_funcall((VALUE)rcv, idInitialize, 0);
     return rcv;
 }
 
-static BOOL
-rb_obj_imp_isEqual(void *rcv, SEL sel, void *obj)
+static VALUE
+rb_objc_init(VALUE rcv)
 {
-    return rb_funcall((VALUE)rcv, idEq, 1, OC2RB(obj)) == Qtrue;
+    IMP imp = class_getMethodImplementation((Class)CLASS_OF(rcv), selInit);
+    if (imp != NULL && imp != (IMP)rb_obj_imp_init) {
+	return (VALUE)((void *(*)(void *, SEL))*imp)((void *)rcv, selInit);
+    }
+    return rcv;
 }
 
 void
@@ -79,14 +89,17 @@
 {
     rb_define_alloc_func(klass, rb_class_allocate_instance);
     rb_define_singleton_method(klass, "new", rb_class_new_instance, -1);
+    rb_define_singleton_method(klass, "__new__", rb_class_new_instance, -1);
     rb_define_method(klass, "dup", rb_obj_dup, 0);
-    rb_define_method(klass, "init", rb_objc_init, 0);
+    rb_define_method(klass, "initialize", rb_objc_init, 0);
     rb_define_method(klass, "initialize_copy", rb_obj_init_copy, 1);
 
     static SEL sel_isEqual = 0;
     if (sel_isEqual == 0)
 	sel_isEqual = sel_registerName("isEqual:");
     class_addMethod((Class)klass, sel_isEqual, (IMP)rb_obj_imp_isEqual, "c@:@");
+
+    class_addMethod((Class)klass, selInit, (IMP)rb_obj_imp_init, "@@:");
 }
 
 static VALUE
@@ -548,7 +561,7 @@
 static void
 rb_mod_included_modules_nosuper(VALUE mod, VALUE ary)
 {
-    VALUE inc_mods = rb_ivar_get(mod, idIncludedModules);
+    VALUE inc_mods = rb_attr_get(mod, idIncludedModules);
     if (inc_mods != Qnil) {
 	int i, count = RARRAY_LEN(inc_mods);
 	for (i = 0; i < count; i++) {
@@ -680,6 +693,11 @@
     Method *methods;
     unsigned int i, count;
 
+    /* XXX: 
+     * - fails to ignore undefined methods (#undef_method)
+     * - does not filter public/private/protected methods
+     */
+
     methods = class_copyMethodList((Class)mod, &count); 
     if (methods != NULL) {  
 	for (i = 0; i < count; i++) { 
@@ -691,6 +709,7 @@
 	    char buf[100];
 	    BOOL is_ruby_method;
 	    size_t len;
+	    IMP imp;
 	   
 	    method = methods[i];
 
@@ -698,12 +717,15 @@
 	    if (sel == sel_ignored)
 		continue; 
 
-	    sel_name = (char *)sel;
-	    is_ruby_method = rb_objc_method_node3(method_getImplementation(method)) != NULL;
+	    imp = method_getImplementation(method);
+	    if (imp == NULL)
+		continue;
 
+	    is_ruby_method = rb_objc_method_node3(imp) != NULL;
 	    if (!is_ruby_method && objc_methods == Qfalse)
 		continue;
 
+	    sel_name = (char *)sel;
 	    len = strlen(sel_name);
 
 	    if (is_ruby_method && len > 8 && sel_name[0] == '_' && sel_name[1] == '_' && sel_name[2] == 'r' && sel_name[3] == 'b' && sel_name[4] == '_' && sel_name[len - 1] == '_' && sel_name[len - 2] == '_') {

Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m	2008-09-01 21:08:39 UTC (rev 542)
+++ MacRuby/trunk/objc.m	2008-09-02 03:30:09 UTC (rev 543)
@@ -3163,7 +3163,7 @@
 	CFRunLoopAddTimer(CFRunLoopGetMain(), timer, kCFRunLoopDefaultMode);
     }
 
-    rb_define_method(rb_cBasicObject, "__super_objc_send__", rb_super_objc_send, -1);
+    rb_define_method(rb_cNSObject, "__super_objc_send__", rb_super_objc_send, -1);
 
     Method m = class_getInstanceMethod(objc_getClass("NSKeyValueUnnestedProperty"), sel_registerName("isaForAutonotifying"));
     assert(m != NULL);

Modified: MacRuby/trunk/object.c
===================================================================
--- MacRuby/trunk/object.c	2008-09-01 21:08:39 UTC (rev 542)
+++ MacRuby/trunk/object.c	2008-09-02 03:30:09 UTC (rev 543)
@@ -1480,7 +1480,7 @@
 {
     VALUE obj;
 
-    if (RCLASS_SUPER(klass) == 0 && klass != rb_cBasicObject) {
+    if (RCLASS_SUPER(klass) == 0 && klass != rb_cBasicObject && klass != rb_cObject) {
 	rb_raise(rb_eTypeError, "can't instantiate uninitialized class");
     }
     if (RCLASS_SINGLETON(klass)) {
@@ -2441,26 +2441,32 @@
 void
 Init_Object(void)
 {
-    rb_cNSObject = rb_cObject = (VALUE)objc_getClass("NSObject");
+    rb_cObject = rb_cNSObject = (VALUE)objc_getClass("NSObject");
     rb_const_set(rb_cObject, rb_intern("Object"), rb_cNSObject);
     rb_set_class_path(rb_cObject, rb_cObject, "NSObject");
-    rb_cBasicObject = rb_cObject; // TODO
+    rb_cBasicObject = (VALUE)objc_duplicateClass((Class)rb_cObject, "BasicObject", 0);
     rb_cModule = boot_defclass("Module", rb_cObject);
     rb_cClass =  boot_defclass("Class",  rb_cModule);
     RCLASS_SUPER(*(Class *)rb_cNSObject) = rb_cClass;
 
-    rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy, 0);
+    rb_define_private_method(rb_cNSObject, "initialize", rb_obj_dummy, 0);
     rb_define_method(rb_cNSObject, "==", rb_obj_equal, 1);
     rb_define_method(rb_cNSObject, "equal?", rb_obj_equal, 1);
     rb_define_method(rb_cNSObject, "!", rb_obj_not, 0);
     rb_define_method(rb_cNSObject, "!=", rb_obj_not_equal, 1);
 
-    rb_define_private_method(rb_cBasicObject, "singleton_method_added", rb_obj_dummy, 1);
-    rb_define_private_method(rb_cBasicObject, "singleton_method_removed", rb_obj_dummy, 1);
-    rb_define_private_method(rb_cBasicObject, "singleton_method_undefined", rb_obj_dummy, 1);
+    rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy, 0);
+    rb_define_method(rb_cBasicObject, "==", rb_obj_equal, 1);
+    rb_define_method(rb_cBasicObject, "equal?", rb_obj_equal, 1);
+    rb_define_method(rb_cBasicObject, "!", rb_obj_not, 0);
+    rb_define_method(rb_cBasicObject, "!=", rb_obj_not_equal, 1);
 
+    rb_define_private_method(rb_cNSObject, "singleton_method_added", rb_obj_dummy, 1);
+    rb_define_private_method(rb_cNSObject, "singleton_method_removed", rb_obj_dummy, 1);
+    rb_define_private_method(rb_cNSObject, "singleton_method_undefined", rb_obj_dummy, 1);
+
     rb_mKernel = rb_define_module("Kernel");
-    rb_include_module(rb_cObject, rb_mKernel);
+    rb_include_module(rb_cNSObject, rb_mKernel);
     rb_define_private_method(rb_cClass, "inherited", rb_obj_dummy, 1);
     rb_define_private_method(rb_cModule, "included", rb_obj_dummy, 1);
     rb_define_private_method(rb_cModule, "extended", rb_obj_dummy, 1);

Modified: MacRuby/trunk/test/ruby/test_objc.rb
===================================================================
--- MacRuby/trunk/test/ruby/test_objc.rb	2008-09-01 21:08:39 UTC (rev 542)
+++ MacRuby/trunk/test/ruby/test_objc.rb	2008-09-02 03:30:09 UTC (rev 543)
@@ -388,4 +388,18 @@
     assert(s.respond_to?('setString:'))
     assert(s.respond_to?('performSelector:withObject:'))
   end
+
+  class TestCallSuperOverridenNew
+    def self.new(x)
+      super
+    end
+    def initialize(x)
+      @x = x
+    end
+    attr_reader :x
+  end
+  def test_call_super_overriden_new
+    o = TestCallSuperOverridenNew.new(42)
+    assert_equal(42, o.x)
+  end
 end

Modified: MacRuby/trunk/vm_eval.c
===================================================================
--- MacRuby/trunk/vm_eval.c	2008-09-01 21:08:39 UTC (rev 542)
+++ MacRuby/trunk/vm_eval.c	2008-09-02 03:30:09 UTC (rev 543)
@@ -1341,17 +1341,15 @@
 
     rb_define_global_function("loop", rb_f_loop, 0);
 
-#if WITH_OBJC
     rb_define_method(rb_cNSObject, "instance_eval", rb_obj_instance_eval, -1);
     rb_define_method(rb_cNSObject, "instance_exec", rb_obj_instance_exec, -1);
     rb_define_private_method(rb_cNSObject, "method_missing", rb_method_missing, -1);
     rb_define_method(rb_cNSObject, "__send__", rb_f_send, -1);
-#else
+
     rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
     rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
     rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
     rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
-#endif
 
     rb_define_method(rb_mKernel, "send", rb_f_send, -1);
     rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);

Modified: MacRuby/trunk/vm_insnhelper.c
===================================================================
--- MacRuby/trunk/vm_insnhelper.c	2008-09-01 21:08:39 UTC (rev 542)
+++ MacRuby/trunk/vm_insnhelper.c	2008-09-02 03:30:09 UTC (rev 543)
@@ -1418,12 +1418,20 @@
 
 #if WITH_OBJC
 static inline VALUE
-vm_search_normal_superclass2(VALUE klass, VALUE recv, ID mid, NODE **mnp, IMP *impp, SEL *selp)
+vm_search_normal_superclass2(VALUE klass, VALUE recv, ID mid, NODE **mnp, 
+			     IMP *impp, SEL *selp)
 {
     static ID idPreviousKlass = 0;
+    static ID idNew = 0, idNew2 = 0, idNew3 = 0;
     CFMutableDictionaryRef iv_dict;
     VALUE ary, k;
   
+    if (idNew == 0) {
+	idNew = rb_intern("new");
+	idNew2 = rb_intern("new:");
+	idNew3 = rb_intern("__new__");
+    }
+
     if (idPreviousKlass == 0) {
 	idPreviousKlass = rb_intern("__previous_sklass__");
     }
@@ -1453,11 +1461,27 @@
     }
 
     iv_dict = rb_class_ivar_dict(klass);
-    if (iv_dict != NULL && CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, (const void *)idPreviousKlass, (const void **)&k)) {
+    if (iv_dict != NULL 
+	&& CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, 
+					 (const void *)idPreviousKlass, 
+					 (const void **)&k)) {
 	CFDictionaryRemoveValue(iv_dict, (const void *)idPreviousKlass);
 	klass = k;
     }
-    return vm_search_normal_superclass(klass, recv);
+
+    k = vm_search_normal_superclass(klass, recv);
+   
+    /* because #new is added on every new NSObject subclasses, and if overriden
+       we should still call our implementation with super */ 
+    if ((mid == idNew || mid == idNew2) && k == *(VALUE *)rb_cNSObject) {
+	*mnp = rb_objc_method_node(klass, idNew3, impp, selp);
+	if (*mnp == NULL)
+	    rb_bug("can't look up __new__ in klass `%s'\n", 
+		   class_getName((Class)klass));
+	k = klass;
+    }
+
+    return k;
 }
 #endif
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macruby-changes/attachments/20080901/c7f7d24e/attachment-0001.html 


More information about the macruby-changes mailing list