示例#1
0
static VALUE
rb_mod_modfunc(VALUE module, SEL sel, int argc, VALUE *argv)
{
    if (TYPE(module) != T_MODULE) {
	rb_raise(rb_eTypeError, "module_function must be called for modules");
    }

    secure_visibility(module);
    if (argc == 0) {
	rb_vm_set_current_scope(module, SCOPE_MODULE_FUNC);
	return module;
    }

    set_method_visibility(module, argc, argv, NOEX_PRIVATE);

    for (int i = 0; i < argc; i++) {
	ID id = rb_to_id(argv[i]);
	IMP imp = NULL;
	rb_vm_method_node_t *node = NULL;
	SEL sel = 0;

	if (rb_vm_lookup_method2((Class)module, id, &sel, &imp, &node)
		|| (TYPE(module) == T_MODULE
		    && rb_vm_lookup_method2((Class)rb_cObject, id, &sel,
			&imp, &node))) {
	    rb_vm_define_method2(*(Class *)module, sel, node, -1, false);
	}
	else {
	    rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
	}
    }

    return module;
}
示例#2
0
static void
rb_export_method(VALUE klass, ID name, ID noex)
{
    rb_vm_method_node_t *node;
    SEL sel;

    if (klass == rb_cObject) {
	rb_secure(4);
    }

    if (!rb_vm_lookup_method2((Class)klass, name, &sel, NULL, &node)) {
	if (TYPE(klass) != T_MODULE
	    || !rb_vm_lookup_method2((Class)rb_cObject, name, &sel, NULL, &node)) {
	    rb_print_undef(klass, name, 0);
	}
    }

#if 0 // TODO
    if (node->nd_noex != noex) {
	// TODO if the method exists on a super class, we should add a new method
	// with the correct noex that calls super
	assert(!rb_vm_lookup_method((Class)RCLASS_SUPER(klass), sel, NULL, NULL));

	node->nd_noex = noex;
    }
#endif
}
示例#3
0
static VALUE
rb_mod_modfunc(VALUE module, SEL sel, int argc, VALUE *argv)
{
    int i;

    if (TYPE(module) != T_MODULE) {
	rb_raise(rb_eTypeError, "module_function must be called for modules");
    }

    secure_visibility(module);
    if (argc == 0) {
	// TODO change scope!
	return module;
    }

    set_method_visibility(module, argc, argv, NOEX_PRIVATE);

    for (i = 0; i < argc; i++) {
	ID id = rb_to_id(argv[i]);
	IMP imp;
	rb_vm_method_node_t *node;
	SEL sel;

	if (!rb_vm_lookup_method2((Class)module, id, &sel, &imp, &node)) {
	    // Methods are checked in set_method_visibility().
	    rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
	}

	rb_vm_define_method2(*(Class *)module, sel, node, false);
    }

    return module;
}
示例#4
0
static void
rb_export_method(VALUE klass, ID name, ID noex)
{
    rb_vm_method_node_t *node;
    SEL sel;

    if (klass == rb_cObject) {
	rb_secure(4);
    }

    if (!rb_vm_lookup_method2((Class)klass, name, &sel, NULL, &node)) {
	if (TYPE(klass) != T_MODULE
		|| !rb_vm_lookup_method2((Class)rb_cObject, name, &sel, NULL,
		    &node)) {
	    rb_print_undef(klass, name, 0);
	}
    }

    if (node == NULL) {
	rb_raise(rb_eRuntimeError,
		"can't change visibility of non Ruby method `%s'",
		sel_getName(sel));
    }

    long flags = (node->flags & ~VM_METHOD_PRIVATE) & ~VM_METHOD_PROTECTED;
    switch (noex) {
	case NOEX_PRIVATE:
	    flags |= VM_METHOD_PRIVATE;
	    break;

	case NOEX_PROTECTED:
	    flags |= VM_METHOD_PROTECTED;
	    break;

	default:
	    break;
    }

    if (node->flags != flags) {
	if (node->klass == (Class)klass) {
	    node->flags = flags;
	}
	else {
	    rb_vm_define_method2((Class)klass, sel, node, flags, false);
	}
    }
}
示例#5
0
rb_vm_method_t *
rb_vm_get_method(VALUE klass, VALUE obj, ID mid, int scope)
{
    SEL sel = 0;
    IMP imp = NULL;
    rb_vm_method_node_t *node = NULL;

    // TODO honor scope

    if (!rb_vm_lookup_method2((Class)klass, mid, &sel, &imp, &node)) {
	rb_print_undef(klass, mid, 0);
    }

    Class k, oklass = (Class)klass;
    while ((k = class_getSuperclass(oklass)) != NULL) {
	if (!rb_vm_lookup_method(k, sel, NULL, NULL)) {
	    break;
	}
	oklass = k;
    }

    Method method = class_getInstanceMethod((Class)klass, sel);
    assert(method != NULL);

    int arity;
    rb_vm_method_node_t *new_node;
    if (node == NULL) {
	arity = rb_method_getNumberOfArguments(method) - 2;
	new_node = NULL;
    }
    else {
	arity = rb_vm_arity_n(node->arity);
	new_node = (rb_vm_method_node_t *)xmalloc(sizeof(rb_vm_method_node_t));
	memcpy(new_node, node, sizeof(rb_vm_method_node_t));
    }

    rb_vm_method_t *m = (rb_vm_method_t *)xmalloc(sizeof(rb_vm_method_t));

    m->oclass = (VALUE)oklass;
    m->rclass = klass;
    GC_WB(&m->recv, obj);
    m->sel = sel;
    m->arity = arity;
    GC_WB(&m->node, new_node);

    // Let's allocate a static cache here, since a rb_vm_method_t must always
    // point to the method it was created from.
    struct mcache *c = (struct mcache *)xmalloc(sizeof(struct mcache));
    if (new_node == NULL) {
	fill_ocache(c, obj, oklass, imp, sel, method, arity);
    }
    else {
	fill_rcache(c, oklass, sel, new_node);
    }
    GC_WB(&m->cache, c);

    return m;
}
示例#6
0
static VALUE
check_method_visibility(VALUE mod, ID id, int visi)
{
    rb_vm_method_node_t *node;
    if (rb_vm_lookup_method2((Class)mod, id, NULL, NULL, &node)) {
	if (node != NULL) {
	    if ((node->flags & NOEX_MASK) == visi) {
		return Qtrue;
	    }
	}
    }
    return Qfalse;
}
示例#7
0
static VALUE
rb_mod_method_defined(VALUE mod, SEL sel, VALUE mid)
{
    ID id = rb_to_id(mid);
    if (rb_obj_respond_to2(Qnil, mod, id, true, false)) {
	rb_vm_method_node_t *node;
	if (rb_vm_lookup_method2((Class)mod, id, NULL, NULL, &node)) {
	    if (node != NULL) {
		if (node->flags & NOEX_PRIVATE) {
		    return Qfalse;
		}
	    }
	    return Qtrue;
	}
    }
    return Qfalse;
}