[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