Exemplo n.º 1
0
VALUE
rb_mod_init_copy(VALUE clone, SEL sel, VALUE orig)
{
    rb_obj_init_copy(clone, 0, orig);

    VALUE super;
    if (!RCLASS_RUBY(orig)) {
	super = orig;
	rb_warn("cloning class `%s' is not supported, creating a " \
		"subclass instead", rb_class2name(orig));
    }
    else {
	super = RCLASS_SUPER(orig);
    }
    RCLASS_SET_SUPER(clone, super);

    // Copy flags.
    unsigned long version_flag = RCLASS_IS_RUBY_CLASS;
    if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS)
	    == RCLASS_IS_OBJECT_SUBCLASS) {
	version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
    }
    if (RCLASS_MODULE(orig)) {
	version_flag |= RCLASS_IS_MODULE;
    }
    RCLASS_SET_VERSION(clone, version_flag);
    if (!class_isMetaClass((Class)clone)) {
	// Clear type info.
	RCLASS_SET_VERSION(*(Class *)clone, RCLASS_VERSION(*(Class *)clone));
    }

    // Copy methods.
    rb_vm_copy_methods((Class)orig, (Class)clone);
    if (!class_isMetaClass((Class)orig)) {
	rb_vm_copy_methods(*(Class *)orig, *(Class *)clone);
    }

    // Copy ivars.
    CFMutableDictionaryRef orig_dict = rb_class_ivar_dict(orig);
    CFMutableDictionaryRef clone_dict;
    if (orig_dict != NULL) {
	clone_dict = CFDictionaryCreateMutableCopy(NULL, 0, orig_dict);
	rb_class_ivar_set_dict(clone, clone_dict);
	CFMakeCollectable(clone_dict);
    }
    else {
	clone_dict = rb_class_ivar_dict_or_create(clone);
    }

    // Remove the classpath & classid (name) so that they are not
    // copied over the new module / class.
    CFDictionaryRemoveValue(clone_dict, (const void *)id_classpath);
    CFDictionaryRemoveValue(clone_dict, (const void *)id_classid);
    return clone;
}
Exemplo n.º 2
0
Arquivo: class.c Projeto: MSch/MacRuby
VALUE
rb_singleton_class_clone(VALUE obj)
{
    VALUE klass = RBASIC(obj)->klass;
    if (!RCLASS_SINGLETON(klass)) {
	return klass;
    }

    // Create new singleton class.
    VALUE clone = rb_objc_create_class(NULL, RCLASS_SUPER(klass));

    // Copy ivars.
    CFMutableDictionaryRef ivar_dict = rb_class_ivar_dict(klass);
    if (ivar_dict != NULL) {
	CFMutableDictionaryRef cloned_ivar_dict =
	    CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)ivar_dict);
	rb_class_ivar_set_dict(clone, cloned_ivar_dict);
	CFMakeCollectable(cloned_ivar_dict);
    }

    // Copy methods.
    rb_vm_copy_methods((Class)klass, (Class)clone);	

    rb_singleton_class_attached(clone, obj);
    if (RCLASS_SUPER(clone) == rb_cRubyObject) {
	long v = RCLASS_VERSION(clone) ^ RCLASS_IS_OBJECT_SUBCLASS;
	RCLASS_SET_VERSION(clone, v);
    }
    RCLASS_SET_VERSION_FLAG(clone, RCLASS_IS_SINGLETON);
    return clone;
}
Exemplo n.º 3
0
Arquivo: class.c Projeto: MSch/MacRuby
static VALUE
rb_objc_alloc_class(const char *name, VALUE super, VALUE flags, VALUE klass)
{
    char ocname[512] = { '\0' };
    if (!rb_vm_generate_objc_class_name(name, ocname, sizeof ocname)) {
	goto no_more_classes;
    }

    Class ocklass = objc_allocateClassPair((Class)super, ocname, 0);
    if (ocklass == NULL) {
	goto no_more_classes;
    }

    long version_flag = RCLASS_IS_RUBY_CLASS;
    if (flags == T_MODULE) {
	version_flag |= RCLASS_IS_MODULE;
    }
    RCLASS_SET_VERSION(ocklass, version_flag);

    objc_registerClassPair(ocklass);

    if (klass != 0 && super != 0) {
	rb_objc_class_sync_version(ocklass, (Class)super);
    }

    return (VALUE)ocklass;

no_more_classes:
    rb_raise(rb_eRuntimeError, "can't create new classes");
}
Exemplo n.º 4
0
Arquivo: class.c Projeto: MSch/MacRuby
void
rb_define_object_special_methods(VALUE klass)
{
    RCLASS_SET_VERSION(*(VALUE *)klass,
	    (RCLASS_VERSION(*(VALUE *)klass) | RCLASS_HAS_ROBJECT_ALLOC));

    rb_objc_define_method(*(VALUE *)klass, "new",
	    rb_class_new_instance_imp, -1);
    rb_objc_define_method(klass, "dup", rb_obj_dup, 0);
    rb_objc_define_private_method(klass, "initialize", rb_objc_init, -1);
    rb_objc_define_private_method(klass, "initialize_copy",
	    rb_obj_init_copy, 1);
    rb_objc_define_method(klass, "hash", rb_obj_id, 0);

    // To make sure singleton classes will be filtered.
    rb_objc_define_method(*(VALUE *)klass, "superclass", rb_obj_superclass, 0);
    rb_objc_define_method(klass, "class", rb_obj_class, 0);

    rb_objc_install_method(*(Class *)klass, selAllocWithZone,
	    (IMP)rb_obj_imp_allocWithZone);
    rb_objc_install_method((Class)klass, selIsEqual,
	    (IMP)rb_obj_imp_isEqual);
    rb_objc_install_method((Class)klass, selInit, (IMP)rb_obj_imp_init);
    rb_objc_install_method((Class)klass, selDescription,
	    (IMP)rb_obj_imp_description);

    // Create -copyWithZone:, since the method doesn't exist yet we need to
    // find the type encoding somewhere, here we check Symbol since it's
    // created very early. 
    Method m = class_getInstanceMethod((Class)rb_cSymbol, selCopyWithZone);
    assert(m != NULL);
    class_replaceMethod((Class)klass, selCopyWithZone, 
	    (IMP)rb_obj_imp_copyWithZone, method_getTypeEncoding(m));
}
Exemplo n.º 5
0
Arquivo: class.c Projeto: MSch/MacRuby
/* :nodoc: */
VALUE
rb_mod_init_copy(VALUE clone, SEL sel, VALUE orig)
{
    static ID classpath = 0;
    static ID classid = 0;

    rb_obj_init_copy(clone, 0, orig);
    {
	VALUE super;
	unsigned long version_flag;

	if (!RCLASS_RUBY(orig)) {
	    super = orig;
	    rb_warn("cloning class `%s' is not supported, creating a " \
		    "subclass instead", rb_class2name(orig));
	}
	else {
	    super = RCLASS_SUPER(orig);
	}
	RCLASS_SET_SUPER(clone, super);

	version_flag = RCLASS_IS_RUBY_CLASS;
	if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS) == RCLASS_IS_OBJECT_SUBCLASS) {
	    version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
	}

	RCLASS_SET_VERSION(clone, version_flag);

	rb_vm_copy_methods((Class)orig, (Class)clone);
	CFMutableDictionaryRef ivar_dict = rb_class_ivar_dict(orig);
	if (ivar_dict != NULL) {
	    CFMutableDictionaryRef cloned_ivar_dict;

	    if (classpath == 0) {
		classpath = rb_intern("__classpath__");
	    }
	    if (classid == 0) {
		classid = rb_intern("__classid__");
	    }
	    cloned_ivar_dict = CFDictionaryCreateMutableCopy(NULL, 0,
		(CFDictionaryRef)ivar_dict);
	    // Remove the classpath & classid (name) so that they are not
	    // copied over the new module / class
	    CFDictionaryRemoveValue(cloned_ivar_dict, (const void *)classpath);
	    CFDictionaryRemoveValue(cloned_ivar_dict, (const void *)classid);
	    CFMakeCollectable(cloned_ivar_dict);
	    rb_class_ivar_set_dict(clone, cloned_ivar_dict);
	}
    }

    return clone;
}
Exemplo n.º 6
0
Arquivo: class.c Projeto: MSch/MacRuby
VALUE
rb_make_singleton_class(VALUE super)
{
    VALUE klass = rb_objc_create_class(NULL, super);
    long v = RCLASS_VERSION(klass);
    if (super == rb_cRubyObject) {
	v ^= RCLASS_IS_OBJECT_SUBCLASS;
    }
    v |= RCLASS_IS_RUBY_CLASS;
    v |= RCLASS_IS_SINGLETON;
    RCLASS_SET_VERSION(klass, v);
    return klass;
}
Exemplo n.º 7
0
Arquivo: class.c Projeto: MSch/MacRuby
void
rb_objc_class_sync_version(Class ocklass, Class ocsuper)
{
    const long super_version = RCLASS_VERSION(ocsuper);
    long klass_version = RCLASS_VERSION(ocklass);

    if (ocsuper == (Class)rb_cRubyObject
	|| (super_version & RCLASS_IS_OBJECT_SUBCLASS)
	    == RCLASS_IS_OBJECT_SUBCLASS) {
	klass_version |= RCLASS_IS_OBJECT_SUBCLASS;
    }

    RCLASS_SET_VERSION(ocklass, klass_version);
}
Exemplo n.º 8
0
static VALUE
specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
{
    VALUE retval;

    // XXX: not exception-safe
    const long old_version = RCLASS_VERSION(klass);

    if (rb_block_given_p()) {
        if (argc > 0) {
            rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)",
		    argc);
        }
	rb_vm_set_current_scope(klass, SCOPE_PUBLIC);
        retval = rb_vm_yield_under(klass, self, 1, &self);
    }
    else {
	const char *file = "(eval)";
	int line = 1;

        if (argc == 0) {
            rb_raise(rb_eArgError, "block not supplied");
        }
	if (rb_safe_level() >= 4) {
	    StringValue(argv[0]);
	}
	else {
	    SafeStringValue(argv[0]);
	}
	if (argc > 3) {
	    const char *name = rb_id2name(rb_frame_callee());
	    rb_raise(rb_eArgError,
		    "wrong number of arguments: %s(src) or %s{..}",
		    name, name);
	}
	if (argc > 2) {
	    line = NUM2INT(argv[2]);
	}
	if (argc > 1) {
	    file = StringValuePtr(argv[1]);
	}
	rb_vm_set_current_scope(klass, SCOPE_PUBLIC);
	retval = eval_under(self, klass, argv[0], Qnil, file, line);
    }

    RCLASS_SET_VERSION(klass, old_version);

    return retval;
}
Exemplo n.º 9
0
Arquivo: class.c Projeto: MSch/MacRuby
VALUE
rb_objc_create_class(const char *name, VALUE super)
{
    if (super == 0) {
	super = rb_cObject;
    }
    VALUE klass = rb_objc_alloc_class(name, super, T_CLASS, rb_cClass);
   
    if (super != rb_cNSObject && super != 0
	    && ((RCLASS_VERSION(*(VALUE *)super) & RCLASS_HAS_ROBJECT_ALLOC)
		== RCLASS_HAS_ROBJECT_ALLOC)) {
	RCLASS_SET_VERSION(*(VALUE *)klass,
		(RCLASS_VERSION(*(VALUE *)klass) | RCLASS_HAS_ROBJECT_ALLOC));
    }

    if (name != NULL && rb_class_tbl != NULL) {
	st_insert(rb_class_tbl, (st_data_t)rb_intern(name), (st_data_t)klass);
    }

    return klass;
}
Exemplo n.º 10
0
Arquivo: class.c Projeto: MSch/MacRuby
void
rb_include_module2(VALUE klass, VALUE orig_klass, VALUE module, bool check,
	bool add_methods)
{
    if (check) {
	rb_frozen_class_p(klass);
	if (!OBJ_TAINTED(klass)) {
	    rb_secure(4);
	}
	Check_Type(module, T_MODULE);
    }

    // Register the module as included in the class.
    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)) {
	    return;
	}
    }
    rb_ary_insert(ary, 0, module);

    // Mark the module as included somewhere.
    const long v = RCLASS_VERSION(module) | RCLASS_IS_INCLUDED;
    RCLASS_SET_VERSION(module, v);

    // Register the class as included in the module.
    ary = rb_attr_get(module, idIncludedInClasses);
    if (ary == Qnil) {
	ary = rb_ary_new();
	rb_ivar_set(module, idIncludedInClasses, ary);
    }
    rb_ary_push(ary, klass);

    // Delete the ancestors array if it exists, since we just changed it.
    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(klass);
    if (iv_dict != NULL) {
	CFDictionaryRemoveValue(iv_dict, (const void *)idAncestors);
    }

    if (add_methods) {
	// Copy methods. If original class has the basic -initialize and if the
	// module has a customized -initialize, we must copy the customized
	// version to the original class too.
	rb_vm_copy_methods((Class)module, (Class)klass);

	// When including into the class Class, also copy the methods to the
	// singleton class of NSObject.
	if (klass == rb_cClass || klass == rb_cModule) {
            rb_vm_copy_methods((Class)module, *(Class *)rb_cNSObject);
	}

	if (orig_klass != 0 && orig_klass != klass) {
	    Method m = class_getInstanceMethod((Class)orig_klass,
		    selInitialize);
	    Method m2 = class_getInstanceMethod((Class)klass, selInitialize);
	    if (m != NULL && m2 != NULL
		&& method_getImplementation(m) == (IMP)rb_objc_init
		&& method_getImplementation(m2) != (IMP)rb_objc_init) {
		rb_vm_copy_method((Class)orig_klass, m2);
	    }
	}
    }
}