[macruby-changes] [2987] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Mon Nov 9 18:30:34 PST 2009


Revision: 2987
          http://trac.macosforge.org/projects/ruby/changeset/2987
Author:   lsansonetti at apple.com
Date:     2009-11-09 18:30:31 -0800 (Mon, 09 Nov 2009)
Log Message:
-----------
fixed several bugs in module mixin

Modified Paths:
--------------
    MacRuby/trunk/class.c
    MacRuby/trunk/eval.c
    MacRuby/trunk/marshal.c
    MacRuby/trunk/object.c
    MacRuby/trunk/proc.c
    MacRuby/trunk/variable.c
    MacRuby/trunk/vm.cpp

Modified: MacRuby/trunk/class.c
===================================================================
--- MacRuby/trunk/class.c	2009-11-09 20:21:48 UTC (rev 2986)
+++ MacRuby/trunk/class.c	2009-11-10 02:30:31 UTC (rev 2987)
@@ -387,6 +387,20 @@
 }
 
 VALUE
+rb_make_singleton_class(VALUE super)
+{
+    VALUE klass = rb_class_boot(super);
+    long v = RCLASS_VERSION(klass);
+    if (super == rb_cNSObject) {
+	v ^= RCLASS_IS_OBJECT_SUBCLASS;
+    }
+    v |= RCLASS_IS_RUBY_CLASS;
+    v |= RCLASS_IS_SINGLETON;
+    RCLASS_SET_VERSION(klass, v);
+    return klass;
+}
+
+    VALUE
 rb_make_metaclass(VALUE obj, VALUE super)
 {
     if (TYPE(obj) == T_CLASS && RCLASS_SINGLETON(obj)) {
@@ -394,17 +408,9 @@
 	return rb_cClass;
     }
     else {
-	VALUE klass;
-
-	klass = rb_class_boot(super);
+	VALUE klass = rb_make_singleton_class(super);
+	rb_vm_set_outer(klass, rb_vm_get_outer(super));
 	RBASIC(obj)->klass = klass;
-	if (super == rb_cNSObject) {
-	    long v = RCLASS_VERSION(klass) ^ RCLASS_IS_OBJECT_SUBCLASS;
-	    RCLASS_SET_VERSION(klass, v);
-	}
-	RCLASS_SET_VERSION_FLAG(klass, RCLASS_IS_SINGLETON);
-	rb_vm_set_outer(klass, rb_vm_get_outer(super));
-
 	rb_singleton_class_attached(klass, obj);
 
 	return klass;
@@ -559,29 +565,27 @@
 void
 rb_include_module2(VALUE klass, VALUE module, int check, int add_methods)
 {
-    VALUE ary;
-
     if (check) {
 	rb_frozen_class_p(klass);
-
-	if (!OBJ_TAINTED(klass))
+	if (!OBJ_TAINTED(klass)) {
 	    rb_secure(4);
-
+	}
 	Check_Type(module, T_MODULE);
     }
 
-    ary = rb_attr_get(klass, idIncludedModules);
+    VALUE ary = rb_attr_get(klass, idIncludedModules);
     if (ary == Qnil) {
 	ary = rb_ary_new();
 	rb_ivar_set(klass, idIncludedModules, ary);
     }
     else {
-	if (rb_ary_includes(ary, module))
+	if (rb_ary_includes(ary, module)) {
 	    return;
+	}
     }
     rb_ary_insert(ary, 0, module);
 
-    long v = RCLASS_VERSION(module) | RCLASS_IS_INCLUDED;
+    const long v = RCLASS_VERSION(module) | RCLASS_IS_INCLUDED;
     RCLASS_SET_VERSION(module, v);
 
     ary = rb_attr_get(module, idIncludedInClasses);
@@ -591,15 +595,11 @@
     }
     rb_ary_push(ary, klass);
 
-    CFMutableDictionaryRef iv_dict;
-   
-    iv_dict = rb_class_ivar_dict(klass);
+    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(klass);
     if (iv_dict != NULL) {
 	CFDictionaryRemoveValue(iv_dict, (const void *)idAncestors);
     }
 
-    DLOG("INCM", "%s <- %s", class_getName((Class)klass), class_getName((Class)module));
-
     if (add_methods) {
 	rb_vm_copy_methods((Class)module, (Class)klass);
     }
@@ -646,12 +646,21 @@
 VALUE
 rb_mod_included_modules(VALUE mod)
 {
-    VALUE p, ary = rb_ary_new();
+    VALUE ary = rb_ary_new();
+    bool mod_detected = false;
 
-    for (p = mod; p; p = RCLASS_SUPER(p)) {
+    for (VALUE p = mod; p != 0; p = RCLASS_SUPER(p)) {
+	if (!mod_detected) {
+	    if (RCLASS_MODULE(p)) {
+		mod_detected = true;
+	    }
+	}
+	else {
+	    if (!RCLASS_SINGLETON(p)) {
+		break;
+	    }
+	}
 	rb_mod_included_modules_nosuper(p, ary);
-	if (RCLASS_MODULE(p))
-	    break;
     }
     return ary;
 }
@@ -702,31 +711,31 @@
 VALUE
 rb_mod_ancestors_nocopy(VALUE mod)
 {
-    VALUE ary;
-
-    ary = rb_attr_get(mod, idAncestors);
+    VALUE ary = rb_attr_get(mod, idAncestors);
     if (NIL_P(ary)) {
-	VALUE p;
-
 	ary = rb_ary_new();
-
-	for (p = mod; p; p = RCLASS_SUPER(p)) {
+	for (VALUE p = mod; p != 0; p = RCLASS_SUPER(p)) {
 	    rb_ary_push(ary, p);
 	    rb_mod_included_modules_nosuper(p, ary);
-	    if (RCLASS_MODULE(p))
-		break;
 	}
-
 	rb_ivar_set(mod, idAncestors, ary);	
     }
-
     return ary;
 }
 
 VALUE
 rb_mod_ancestors(VALUE mod)
 {
-    return rb_ary_dup(rb_mod_ancestors_nocopy(mod));
+    // This method should return a new array without singleton classes.
+    VALUE ary = rb_mod_ancestors_nocopy(mod);
+    VALUE filtered = rb_ary_new();
+    for (int i = 0, count = RARRAY_LEN(ary); i < count; i++) {
+	VALUE p = RARRAY_AT(ary, i);
+	if (!RCLASS_SINGLETON(p)) {
+	    rb_ary_push(filtered, p);
+	}
+    }
+    return filtered;
 }
 
 static int

Modified: MacRuby/trunk/eval.c
===================================================================
--- MacRuby/trunk/eval.c	2009-11-09 20:21:48 UTC (rev 2986)
+++ MacRuby/trunk/eval.c	2009-11-10 02:30:31 UTC (rev 2987)
@@ -506,19 +506,39 @@
  *  _mod_ or one of its ancestors. See also <code>Module#include</code>.
  */
 
+VALUE rb_make_singleton_class(VALUE super);
+
 static VALUE
 rb_mod_append_features(VALUE module, SEL sel, VALUE include)
 {
     switch (TYPE(include)) {
-      case T_CLASS:
-      case T_MODULE:
-	break;
-      default:
-	Check_Type(include, T_CLASS);
-	break;
+	case T_CLASS:
+	case T_MODULE:
+	    break;
+	default:
+	    Check_Type(include, T_CLASS);
+	    break;
     }
+    if (RCLASS_RUBY(include)) {
+	VALUE sinclude = rb_make_singleton_class(RCLASS_SUPER(include));
+	RCLASS_SET_SUPER(include, sinclude);
+	include = sinclude;
+    }	
     rb_include_module(include, module);
 
+    VALUE m = module;
+    do {
+	VALUE ary = rb_attr_get(m, idIncludedModules);
+	if (ary != Qnil) {
+	    for (int i = 0, count = RARRAY_LEN(ary); i < count; i++) {
+		VALUE mod = RARRAY_AT(ary, i);
+		rb_mod_append_features(mod, sel, include);
+	    }
+	}
+	m = RCLASS_SUPER(m);
+    }
+    while (m == 0 || RCLASS_SINGLETON(m));
+
     return module;
 }
 
@@ -553,7 +573,16 @@
 void
 rb_extend_object(VALUE obj, VALUE module)
 {
-    rb_include_module(rb_singleton_class(obj), module);
+    VALUE klass;
+    if (TYPE(obj) == T_CLASS && RCLASS_RUBY(obj)) {
+	VALUE sklass = rb_make_singleton_class(RCLASS_SUPER(obj));
+	RCLASS_SET_SUPER(obj, sklass);
+	klass = *(VALUE *)sklass;
+    }
+    else {
+	klass = rb_singleton_class(obj);
+    }	
+    rb_include_module(klass, module);
 }
 
 /*

Modified: MacRuby/trunk/marshal.c
===================================================================
--- MacRuby/trunk/marshal.c	2009-11-09 20:21:48 UTC (rev 2986)
+++ MacRuby/trunk/marshal.c	2009-11-10 02:30:31 UTC (rev 2987)
@@ -871,8 +871,8 @@
 	    break;
 
 	  default:
-	    rb_raise(rb_eTypeError, "can't dump %s",
-		    rb_obj_classname(obj));
+	    rb_raise(rb_eTypeError, "can't dump %s (type %d)",
+		    rb_obj_classname(obj), TYPE(obj));
 	    break;
 	}
     }

Modified: MacRuby/trunk/object.c
===================================================================
--- MacRuby/trunk/object.c	2009-11-09 20:21:48 UTC (rev 2986)
+++ MacRuby/trunk/object.c	2009-11-10 02:30:31 UTC (rev 2987)
@@ -359,15 +359,23 @@
     return (VALUE)objc_msgSend((id)obj, selCopy); 
 }
 
+static VALUE
+rb_obj_type(VALUE obj)
+{
+    return LONG2FIX(TYPE(obj));
+}
+
 /* :nodoc: */
 VALUE
 rb_obj_init_copy(VALUE obj, SEL sel, VALUE orig)
 {
-    if (obj == orig) return obj;
+    if (obj == orig) {
+	return obj;
+    }
     rb_check_frozen(obj);
-    if (TYPE(obj) != TYPE(orig)) {
-	/* FIXME rb_obj_class(obj) != rb_obj_class(orig) */
-	rb_raise(rb_eTypeError, "initialize_copy should take same class object");
+    if (rb_obj_class(obj) != rb_obj_class(orig)) {
+	rb_raise(rb_eTypeError,
+		"initialize_copy should take same class object");
     }
     return obj;
 }
@@ -1532,6 +1540,12 @@
     return rb_mod_ancestors(self);
 }
 
+static VALUE
+rb_mod_ancestors_all_imp(VALUE self, SEL sel)
+{
+    return rb_mod_ancestors_nocopy(self);
+}
+
 /*
  *  call-seq:
  *     mod.freeze
@@ -2927,6 +2941,7 @@
 
     rb_objc_define_method(rb_cNSObject, "clone", rb_obj_clone_imp, 0);
     rb_objc_define_method(rb_cNSObject, "dup", rb_nsobj_dup, 0);
+    rb_objc_define_method(rb_cNSObject, "__type__", rb_obj_type, 0);
 
     rb_objc_define_method(rb_mKernel, "initialize_copy", rb_obj_init_copy, 1);
     rb_objc_define_method(rb_mKernel, "taint", rb_obj_taint_m, 0);
@@ -3004,6 +3019,7 @@
     VALUE rb_mod_name(VALUE, SEL);
     rb_objc_define_method(rb_cModule, "name", rb_mod_name, 0);  /* in variable.c */
     rb_objc_define_method(rb_cModule, "ancestors", rb_mod_ancestors_imp, 0);
+    rb_objc_define_method(rb_cModule, "__ancestors__", rb_mod_ancestors_all_imp, 0);
     VALUE rb_mod_objc_ib_outlet(VALUE, SEL, int, VALUE *);
     rb_objc_define_private_method(rb_cModule, "ib_outlet", rb_mod_objc_ib_outlet, -1); /* in objc.m */
     rb_objc_define_method(rb_cClass, "__meta__?", rb_class_is_meta, 0);

Modified: MacRuby/trunk/proc.c
===================================================================
--- MacRuby/trunk/proc.c	2009-11-09 20:21:48 UTC (rev 2986)
+++ MacRuby/trunk/proc.c	2009-11-10 02:30:31 UTC (rev 2987)
@@ -1270,32 +1270,12 @@
     rb_str_buf_cat2(str, s);
     rb_str_buf_cat2(str, ": ");
 
-    if (RCLASS_SINGLETON(data->oclass)) {
-	VALUE v = rb_iv_get(data->oclass, "__attached__");
-
-	if (data->recv == Qundef) {
-	    rb_str_buf_append(str, rb_inspect(data->oclass));
-	}
-	else if (data->recv == v) {
-	    rb_str_buf_append(str, rb_inspect(v));
-	    sharp = ".";
-	}
-	else {
-	    rb_str_buf_append(str, rb_inspect(data->recv));
-	    rb_str_buf_cat2(str, "(");
-	    rb_str_buf_append(str, rb_inspect(v));
-	    rb_str_buf_cat2(str, ")");
-	    sharp = ".";
-	}
+    rb_str_buf_cat2(str, rb_class2name(data->rclass));
+    if (data->rclass != data->oclass) {
+	rb_str_buf_cat2(str, "(");
+	rb_str_buf_cat2(str, rb_class2name(data->oclass));
+	rb_str_buf_cat2(str, ")");
     }
-    else {
-	rb_str_buf_cat2(str, rb_class2name(data->rclass));
-	if (data->rclass != data->oclass) {
-	    rb_str_buf_cat2(str, "(");
-	    rb_str_buf_cat2(str, rb_class2name(data->oclass));
-	    rb_str_buf_cat2(str, ")");
-	}
-    }
     rb_str_buf_cat2(str, sharp);
     rb_str_buf_cat2(str, sel_getName(data->sel));
     rb_str_buf_cat2(str, ">");

Modified: MacRuby/trunk/variable.c
===================================================================
--- MacRuby/trunk/variable.c	2009-11-09 20:21:48 UTC (rev 2986)
+++ MacRuby/trunk/variable.c	2009-11-10 02:30:31 UTC (rev 2987)
@@ -1780,6 +1780,15 @@
 	if (!recurse && klass != rb_cObject) {
 	    break;
 	}
+	VALUE inc_mods = rb_attr_get(tmp, idIncludedModules);
+	if (inc_mods != Qnil) {
+	    int i, count = RARRAY_LEN(inc_mods);
+	    for (i = 0; i < count; i++) {
+		iv_dict = rb_class_ivar_dict(RARRAY_AT(inc_mods, i));
+		if (CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, (const void **)&value))
+		    return Qtrue;
+	    }
+	}
 	tmp = RCLASS_SUPER(tmp);
     }
     if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2009-11-09 20:21:48 UTC (rev 2986)
+++ MacRuby/trunk/vm.cpp	2009-11-10 02:30:31 UTC (rev 2987)
@@ -1254,7 +1254,7 @@
 	klass = rb_const_get_at(outer, path);
 	check_if_module(klass);
 	if (!(flags & DEFINE_MODULE) && super != 0) {
-	    if (RCLASS_SUPER(klass) != super) {
+	    if (rb_class_real(RCLASS_SUPER(klass)) != super) {
 		rb_raise(rb_eTypeError, "superclass mismatch for class %s",
 			rb_class2name(klass));
 	    }
@@ -2102,64 +2102,84 @@
     }
 
     // Copy methods that have not been JIT'ed yet.
+
+    // First, make a list of selectors.
+    std::vector<SEL> sels_to_copy;
     std::multimap<Class, SEL>::iterator iter =
 	method_source_sels.find(from_class);
 
     if (iter != method_source_sels.end()) {
 	std::multimap<Class, SEL>::iterator last =
 	    method_source_sels.upper_bound(from_class);
-	std::vector<SEL> sels_to_add;
 
 	for (; iter != last; ++iter) {
-	    SEL sel = iter->second;
+	    sels_to_copy.push_back(iter->second);
+	}
+    }
 
-	    std::map<Class, rb_vm_method_source_t *> *dict =
-		method_sources_for_sel(sel, false);
-	    if (dict == NULL) {
-		continue;
-	    }
+    // Force a resolving of these selectors on the target class. This must be
+    // done outside the next loop since the resolver messes up the Core
+    // structures.
+    for (std::vector<SEL>::iterator iter = sels_to_copy.begin();
+	    iter != sels_to_copy.end();
+	    ++iter) {
+	class_getInstanceMethod(to_class, *iter);
+    }
 
-	    std::map<Class, rb_vm_method_source_t *>::iterator
-		iter2 = dict->find(from_class);
-	    if (iter2 == dict->end()) {
-		continue;
-	    }
+    // Now, let's really copy the lazy methods.
+    std::vector<SEL> sels_to_add;
+    for (std::vector<SEL>::iterator iter = sels_to_copy.begin();
+	    iter != sels_to_copy.end();
+	    ++iter) {
+	SEL sel = *iter;
 
-	    rb_vm_method_source_t *m_src = iter2->second;
+	std::map<Class, rb_vm_method_source_t *> *dict =
+	    method_sources_for_sel(sel, false);
+	if (dict == NULL) {
+	    continue;
+	}
 
-	    Method m = class_getInstanceMethod(to_class, sel);
-	    if (m != NULL) {
-		// The method already exists - we need to JIT it.
-		IMP imp = GET_CORE()->compile(m_src->func);
-		resolve_method(to_class, sel, m_src->func, m_src->arity,
-			m_src->flags, imp, m);
-	    }
-	    else {
+	std::map<Class, rb_vm_method_source_t *>::iterator
+	    iter2 = dict->find(from_class);
+	if (iter2 == dict->end()) {
+	    continue;
+	}
+
+	rb_vm_method_source_t *m_src = iter2->second;
+
+	Method m = class_getInstanceMethod(to_class, sel);
+	if (m != NULL) {
+	    // The method already exists on the target class, we need to
+	    // JIT it.
+	    IMP imp = GET_CORE()->compile(m_src->func);
+	    resolve_method(to_class, sel, m_src->func, m_src->arity,
+		    m_src->flags, imp, m);
+	}
+	else {
 #if ROXOR_VM_DEBUG
-		printf("lazy copy %c[%s %s] to %c%s\n",
-			class_isMetaClass(from_class) ? '+' : '-',
-			class_getName(from_class),
-			sel_getName(sel),
-			class_isMetaClass(to_class) ? '+' : '-',
-			class_getName(to_class));
+	    printf("lazy copy %c[%s %s] to %c%s\n",
+		    class_isMetaClass(from_class) ? '+' : '-',
+		    class_getName(from_class),
+		    sel_getName(sel),
+		    class_isMetaClass(to_class) ? '+' : '-',
+		    class_getName(to_class));
 #endif
 
-		rb_vm_method_source_t *m = (rb_vm_method_source_t *)
-		    malloc(sizeof(rb_vm_method_source_t));
-		m->func = m_src->func;
-		m->arity = m_src->arity;
-		m->flags = m_src->flags;
-		dict->insert(std::make_pair(to_class, m));
-		sels_to_add.push_back(sel);
-	    }
+	    rb_vm_method_source_t *m = (rb_vm_method_source_t *)
+		malloc(sizeof(rb_vm_method_source_t));
+	    m->func = m_src->func;
+	    m->arity = m_src->arity;
+	    m->flags = m_src->flags;
+	    dict->insert(std::make_pair(to_class, m));
+	    sels_to_add.push_back(sel);
 	}
+    }
 
-	for (std::vector<SEL>::iterator i = sels_to_add.begin();
-	     i != sels_to_add.end();
-	     ++i) {
-	    method_source_sels.insert(std::make_pair(to_class, *i));
-	}
-    } 
+    for (std::vector<SEL>::iterator i = sels_to_add.begin();
+	    i != sels_to_add.end();
+	    ++i) {
+	method_source_sels.insert(std::make_pair(to_class, *i));
+    }
 }
 
 extern "C"
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20091109/c57a1a34/attachment-0001.html>


More information about the macruby-changes mailing list