[macruby-changes] [2941] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Mon Nov 2 17:22:57 PST 2009


Revision: 2941
          http://trac.macosforge.org/projects/ruby/changeset/2941
Author:   lsansonetti at apple.com
Date:     2009-11-02 17:22:54 -0800 (Mon, 02 Nov 2009)
Log Message:
-----------
when registering a new method, if the given class also responds to the arity-1+1 selector let's make it unavailable, to fully conform to the way Ruby behaves

Modified Paths:
--------------
    MacRuby/trunk/dispatcher.cpp
    MacRuby/trunk/vm.cpp
    MacRuby/trunk/vm.h

Modified: MacRuby/trunk/dispatcher.cpp
===================================================================
--- MacRuby/trunk/dispatcher.cpp	2009-11-02 23:00:03 UTC (rev 2940)
+++ MacRuby/trunk/dispatcher.cpp	2009-11-03 01:22:54 UTC (rev 2941)
@@ -221,9 +221,20 @@
 rb_vm_super_lookup(VALUE klass, SEL sel)
 {
     // Locate the current method implementation.
-    Method m = class_getInstanceMethod((Class)klass, sel);
-    assert(m != NULL);
-    IMP self = objc_imp(method_getImplementation(m));
+    Class k = (Class)klass;
+    IMP self;
+    while (true) {
+	Method m = class_getInstanceMethod(k, sel);
+	assert(m != NULL);
+	self = method_getImplementation(m);
+	if (UNAVAILABLE_IMP(self)) {
+	    k = class_getSuperclass(k);
+	    assert(k != NULL);
+	}
+	else {
+	    break;
+	}
+    }
 
     // Compute the stack call implementations right after our current method.
     void *callstack[128];
@@ -248,7 +259,6 @@
     // the stack.
     VALUE ary = rb_mod_ancestors_nocopy(klass);
     const int count = RARRAY_LEN(ary);
-    VALUE k = klass;
     bool klass_located = false;
 
 #if ROXOR_VM_DEBUG
@@ -272,18 +282,21 @@
         }
         if (klass_located) {
             if (i < count - 1) {
-                k = RARRAY_AT(ary, i + 1);
+                VALUE k = RARRAY_AT(ary, i + 1);
 
 		Method method = class_getInstanceMethod((Class)k, sel);
 		VALUE super = RCLASS_SUPER(k);
 
-		if (method == NULL || REMOVED_IMP(method_getImplementation(method))
-		    || (super != 0
-		        && class_getInstanceMethod((Class)super, sel) == method)) {
+		if (method == NULL) {
 		    continue;
 		}
 
 		IMP imp = method_getImplementation(method);
+		if (UNAVAILABLE_IMP(imp)
+		    || (super != 0 && class_getInstanceMethod((Class)super,
+			    sel) == method)) {
+		    continue;
+		}
 
 		if (std::find(callstack_funcs.begin(), callstack_funcs.end(), 
 			    (void *)imp) == callstack_funcs.end()) {
@@ -556,9 +569,7 @@
 recache2:
 	    IMP imp = method_getImplementation(method);
 
-	    if (UNDEFINED_IMP(imp)
-			|| (REMOVED_IMP(imp)
-				&& rb_vm_super_lookup((VALUE)klass, sel) == NULL)) {
+	    if (UNAVAILABLE_IMP(imp)) {
 		// Method was undefined.
 		goto call_method_missing;
 	    }
@@ -1769,9 +1780,7 @@
 	}
 
 	IMP imp = method_getImplementation(m);
-	if (UNDEFINED_IMP(imp)
-	    || (REMOVED_IMP(imp)
-	        && rb_vm_super_lookup((VALUE)klass, sel) == NULL)) {
+	if (UNAVAILABLE_IMP(imp)) {
 	    return false;
 	}
 

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2009-11-02 23:00:03 UTC (rev 2940)
+++ MacRuby/trunk/vm.cpp	2009-11-03 01:22:54 UTC (rev 2941)
@@ -1379,6 +1379,9 @@
 rb_vm_alias_method(Class klass, Method method, ID name, bool noargs)
 {
     IMP imp = method_getImplementation(method);
+    if (UNAVAILABLE_IMP(imp)) {
+	return;
+    }
     const char *types = method_getTypeEncoding(method);
 
     rb_vm_method_node_t *node = GET_CORE()->method_node_get(method);
@@ -1806,7 +1809,9 @@
 
     m = class_getInstanceMethod(klass, sel);
     if (precompiled) {
-	imp = (IMP)data;
+	if (imp == NULL) {
+	    imp = (IMP)data;
+	}
 	GET_CORE()->resolve_method(klass, sel, NULL, arity, flags, imp, m);
     }
     else {
@@ -1825,23 +1830,34 @@
     }
 
     if (!redefined) {
-	if (!genuine_selector && arity.max != arity.min) {
-	    char buf[100];
+	char buf[100];
+	SEL new_sel = 0;
+	if (!genuine_selector) {
 	    snprintf(buf, sizeof buf, "%s:", sel_name);
-	    sel = sel_registerName(buf);
-	    redefined = true;
-
-	    goto prepare_method;
+	    new_sel = sel_registerName(buf);
+	    if (arity.max != arity.min) {
+		sel = new_sel;
+		redefined = true;
+		goto prepare_method;
+	    }
 	}
-	else if (genuine_selector && arity.min == 0) {
-	    char buf[100];
+	else {
 	    strlcpy(buf, sel_name, sizeof buf);
 	    buf[strlen(buf) - 1] = 0; // remove the ending ':'
-	    sel = sel_registerName(buf);
-	    redefined = true;
-
-	    goto prepare_method;
+	    new_sel = sel_registerName(buf);
+	    if (arity.min == 0) {
+		sel = new_sel;
+		redefined = true;
+		goto prepare_method;
+	    }
 	}
+	Method tmp_m = class_getInstanceMethod(klass, new_sel);
+	if (tmp_m != NULL) {
+	    // If we add -[foo:] and the class responds to -[foo], we need
+	    // to disable it (and vice-versa).
+	    class_replaceMethod(klass, new_sel,
+		    (IMP)rb_vm_undefined_imp, method_getTypeEncoding(tmp_m));	
+	}
     }
 
     if (RCLASS_VERSION(klass) & RCLASS_IS_INCLUDED) {
@@ -2131,6 +2147,9 @@
 	return false;
     }
     IMP imp = method_getImplementation(m);
+    if (UNAVAILABLE_IMP(imp)) {
+	return false;
+    }
     if (pimp != NULL) {
 	*pimp = imp;
     }
@@ -2259,8 +2278,6 @@
     rb_vm_define_method(klass, sel, imp, body, false);
 }
 
-#define UNDEFINED_IMP(imp) (imp == NULL || imp == (IMP)rb_vm_undefined_imp)
-
 void
 RoxorCore::undef_method(Class klass, SEL sel)
 {

Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h	2009-11-02 23:00:03 UTC (rev 2940)
+++ MacRuby/trunk/vm.h	2009-11-03 01:22:54 UTC (rev 2941)
@@ -283,9 +283,10 @@
 void rb_vm_define_method3(Class klass, SEL sel, rb_vm_block_t *node);
 bool rb_vm_resolve_method(Class klass, SEL sel);
 void *rb_vm_undefined_imp(void *rcv, SEL sel);
-#define UNDEFINED_IMP(imp) (imp == NULL || imp == (IMP)rb_vm_undefined_imp)
 void *rb_vm_removed_imp(void *rcv, SEL sel);
-#define REMOVED_IMP(imp) (imp == (IMP)rb_vm_removed_imp)
+#define UNAVAILABLE_IMP(imp) \
+    (imp == NULL || imp == (IMP)rb_vm_undefined_imp \
+     || imp == (IMP)rb_vm_removed_imp)
 void rb_vm_define_attr(Class klass, const char *name, bool read, bool write);
 void rb_vm_undef_method(Class klass, ID name, bool must_exist);
 void rb_vm_alias(VALUE klass, ID name, ID def);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20091102/06f292c7/attachment-0001.html>


More information about the macruby-changes mailing list