[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