Class: Method

Inherits:
Object show all
Defined in:
proc.c

Instance Method Summary collapse

Instance Method Details

#==(other_meth) ⇒ Boolean

Two method objects are equal if they are bound to the same object and refer to the same method definition.

Returns:

  • (Boolean)


# File 'proc.c'

/*
 * call-seq:
 *   meth == other_meth  -> true or false
 *
 * Two method objects are equal if they are bound to the same
 * object and refer to the same method definition.
 */

static VALUE
method_eq(VALUE method, VALUE other)
{
    struct METHOD *m1, *m2;
    extern int rb_method_entry_eq(rb_method_entry_t *m1, rb_method_entry_t *m2);

    if (!rb_obj_is_method(other))
    return Qfalse;
    if (CLASS_OF(method) != CLASS_OF(other))
    return Qfalse;

    Check_TypedStruct(method, &method_data_type);
    m1 = (struct METHOD *)DATA_PTR(method);
    m2 = (struct METHOD *)DATA_PTR(other);

    if (!rb_method_entry_eq(&m1->me, &m2->me) ||
    m1->rclass != m2->rclass ||
    m1->recv != m2->recv) {
    return Qfalse;
    }

    return Qtrue;
}

#call(args, ...) ⇒ Object #[](args, ...) ⇒ Object

Invokes the meth with the specified arguments, returning the method's return value.

m = 12.method("+")
m.call(3)    #=> 15
m.call(20)   #=> 32

Overloads:



# File 'proc.c'

/*
 *  call-seq:
 *     meth.call(args, ...)    -> obj
 *     meth[args, ...]         -> obj
 *
 *  Invokes the <i>meth</i> with the specified arguments, returning the
 *  method's return value.
 *
 *     m = 12.method("+")
 *     m.call(3)    #=> 15
 *     m.call(20)   #=> 32
 */

VALUE
rb_method_call(int argc, VALUE *argv, VALUE method)
{
    VALUE result = Qnil;    /* OK */
    struct METHOD *data;
    int state;
    volatile int safe = -1;

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
    if (data->recv == Qundef) {
    rb_raise(rb_eTypeError, "can't call unbound method; bind first");
    }
    PUSH_TAG();
    if (OBJ_TAINTED(method)) {
    safe = rb_safe_level();
    if (rb_safe_level() < 4) {
        rb_set_safe_level_force(4);
    }
    }
    if ((state = EXEC_TAG()) == 0) {
    rb_thread_t *th = GET_THREAD();
    VALUE rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, const VALUE *argv,
             const rb_method_entry_t *me);

    PASS_PASSED_BLOCK_TH(th);
    result = rb_vm_call(th, data->recv, data->id,  argc, argv, &data->me);
    }
    POP_TAG();
    if (safe >= 0)
    rb_set_safe_level_force(safe);
    if (state)
    JUMP_TAG(state);
    return result;
}

#arityFixnum

Returns an indication of the number of arguments accepted by a method. Returns a nonnegative integer for methods that take a fixed number of arguments. For Ruby methods that take a variable number of arguments, returns -n-1, where n is the number of required arguments. For methods written in C, returns -1 if the call takes a variable number of arguments.

class C
  def one;    end
  def two(a); end
  def three(*a);  end
  def four(a, b); end
  def five(a, b, *c);    end
  def six(a, b, *c, &d); end
end
c = C.new
c.method(:one).arity     #=> 0
c.method(:two).arity     #=> 1
c.method(:three).arity   #=> -1
c.method(:four).arity    #=> 2
c.method(:five).arity    #=> -3
c.method(:six).arity     #=> -3

"cat".method(:size).arity      #=> 0
"cat".method(:replace).arity   #=> 1
"cat".method(:squeeze).arity   #=> -1
"cat".method(:count).arity     #=> -1

Returns:



# File 'proc.c'

/*
 *  call-seq:
 *     meth.arity    -> fixnum
 *
 *  Returns an indication of the number of arguments accepted by a
 *  method. Returns a nonnegative integer for methods that take a fixed
 *  number of arguments. For Ruby methods that take a variable number of
 *  arguments, returns -n-1, where n is the number of required
 *  arguments. For methods written in C, returns -1 if the call takes a
 *  variable number of arguments.
 *
 *     class C
 *       def one;    end
 *       def two(a); end
 *       def three(*a);  end
 *       def four(a, b); end
 *       def five(a, b, *c);    end
 *       def six(a, b, *c, &d); end
 *     end
 *     c = C.new
 *     c.method(:one).arity     #=> 0
 *     c.method(:two).arity     #=> 1
 *     c.method(:three).arity   #=> -1
 *     c.method(:four).arity    #=> 2
 *     c.method(:five).arity    #=> -3
 *     c.method(:six).arity     #=> -3
 *
 *     "cat".method(:size).arity      #=> 0
 *     "cat".method(:replace).arity   #=> 1
 *     "cat".method(:squeeze).arity   #=> -1
 *     "cat".method(:count).arity     #=> -1
 */

static VALUE
method_arity_m(VALUE method)
{
    int n = method_arity(method);
    return INT2FIX(n);
}

#call(args, ...) ⇒ Object #[](args, ...) ⇒ Object

Invokes the meth with the specified arguments, returning the method's return value.

m = 12.method("+")
m.call(3)    #=> 15
m.call(20)   #=> 32

Overloads:



# File 'proc.c'

/*
 *  call-seq:
 *     meth.call(args, ...)    -> obj
 *     meth[args, ...]         -> obj
 *
 *  Invokes the <i>meth</i> with the specified arguments, returning the
 *  method's return value.
 *
 *     m = 12.method("+")
 *     m.call(3)    #=> 15
 *     m.call(20)   #=> 32
 */

VALUE
rb_method_call(int argc, VALUE *argv, VALUE method)
{
    VALUE result = Qnil;    /* OK */
    struct METHOD *data;
    int state;
    volatile int safe = -1;

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
    if (data->recv == Qundef) {
    rb_raise(rb_eTypeError, "can't call unbound method; bind first");
    }
    PUSH_TAG();
    if (OBJ_TAINTED(method)) {
    safe = rb_safe_level();
    if (rb_safe_level() < 4) {
        rb_set_safe_level_force(4);
    }
    }
    if ((state = EXEC_TAG()) == 0) {
    rb_thread_t *th = GET_THREAD();
    VALUE rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, const VALUE *argv,
             const rb_method_entry_t *me);

    PASS_PASSED_BLOCK_TH(th);
    result = rb_vm_call(th, data->recv, data->id,  argc, argv, &data->me);
    }
    POP_TAG();
    if (safe >= 0)
    rb_set_safe_level_force(safe);
    if (state)
    JUMP_TAG(state);
    return result;
}

#cloneObject

MISSING: documentation



# File 'proc.c'

/*
 * MISSING: documentation
 */

static VALUE
method_clone(VALUE self)
{
    VALUE clone;
    struct METHOD *orig, *data;

    TypedData_Get_Struct(self, struct METHOD, &method_data_type, orig);
    clone = TypedData_Make_Struct(CLASS_OF(self), struct METHOD, &method_data_type, data);
    CLONESETUP(clone, self);
    *data = *orig;
    if (data->me.def) data->me.def->alias_count++;

    return clone;
}

#==(other_meth) ⇒ Boolean

Two method objects are equal if they are bound to the same object and refer to the same method definition.

Returns:

  • (Boolean)


# File 'proc.c'

/*
 * call-seq:
 *   meth == other_meth  -> true or false
 *
 * Two method objects are equal if they are bound to the same
 * object and refer to the same method definition.
 */

static VALUE
method_eq(VALUE method, VALUE other)
{
    struct METHOD *m1, *m2;
    extern int rb_method_entry_eq(rb_method_entry_t *m1, rb_method_entry_t *m2);

    if (!rb_obj_is_method(other))
    return Qfalse;
    if (CLASS_OF(method) != CLASS_OF(other))
    return Qfalse;

    Check_TypedStruct(method, &method_data_type);
    m1 = (struct METHOD *)DATA_PTR(method);
    m2 = (struct METHOD *)DATA_PTR(other);

    if (!rb_method_entry_eq(&m1->me, &m2->me) ||
    m1->rclass != m2->rclass ||
    m1->recv != m2->recv) {
    return Qfalse;
    }

    return Qtrue;
}

#hashInteger

Return a hash value corresponding to the method object.

Returns:



# File 'proc.c'

/*
 * call-seq:
 *    meth.hash   -> integer
 *
 * Return a hash value corresponding to the method object.
 */

static VALUE
method_hash(VALUE method)
{
    struct METHOD *m;
    st_index_t hash;

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, m);
    hash = rb_hash_start((st_index_t)m->rclass);
    hash = rb_hash_uint(hash, (st_index_t)m->recv);
    hash = rb_hash_uint(hash, (st_index_t)m->me.def);
    hash = rb_hash_end(hash);

    return INT2FIX(hash);
}

#to_sString #inspectString

Show the name of the underlying method.

"cat".method(:count).inspect   #=> "#<Method: String#count>"

Overloads:



# File 'proc.c'

/*
 *  call-seq:
 *   meth.to_s      ->  string
 *   meth.inspect   ->  string
 *
 *  Show the name of the underlying method.
 *
 *    "cat".method(:count).inspect   #=> "#<Method: String#count>"
 */

static VALUE
method_inspect(VALUE method)
{
    struct METHOD *data;
    VALUE str;
    const char *s;
    const char *sharp = "#";

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
    str = rb_str_buf_new2("#<");
    s = rb_obj_classname(method);
    rb_str_buf_cat2(str, s);
    rb_str_buf_cat2(str, ": ");

    if (FL_TEST(data->me.klass, FL_SINGLETON)) {
    VALUE v = rb_iv_get(data->me.klass, "__attached__");

    if (data->recv == Qundef) {
        rb_str_buf_append(str, rb_inspect(data->me.klass));
    }
    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 = ".";
    }
    }
    else {
    rb_str_buf_cat2(str, rb_class2name(data->rclass));
    if (data->rclass != data->me.klass) {
        rb_str_buf_cat2(str, "(");
        rb_str_buf_cat2(str, rb_class2name(data->me.klass));
        rb_str_buf_cat2(str, ")");
    }
    }
    rb_str_buf_cat2(str, sharp);
    rb_str_append(str, rb_id2str(data->me.def->original_id));
    if (data->me.def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
        rb_str_buf_cat2(str, " (not-implemented)");
    }
    rb_str_buf_cat2(str, ">");

    return str;
}

#nameObject

Returns the name of the method.



# File 'proc.c'

/*
 *  call-seq:
 *     meth.name    -> symbol
 *
 *  Returns the name of the method.
 */

static VALUE
method_name(VALUE obj)
{
    struct METHOD *data;

    TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
    return ID2SYM(data->id);
}

#ownerObject

Returns the class or module that defines the method.



# File 'proc.c'

/*
 *  call-seq:
 *     meth.owner    -> class_or_module
 *
 *  Returns the class or module that defines the method.
 */

static VALUE
method_owner(VALUE obj)
{
    struct METHOD *data;

    TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
    return data->me.klass;
}

#parametersArray

returns the parameter information of this method

Returns:



# File 'proc.c'

/*
 * call-seq:
 *    meth.parameters  -> array
 *
 * returns the parameter information of this method
 */

static VALUE
rb_method_parameters(VALUE method)
{
    rb_iseq_t *iseq = rb_method_get_iseq(method);
    if (!iseq) {
    return unnamed_parameters(method_arity(method));
    }
    return rb_iseq_parameters(iseq, 0);
}

#receiverObject

Returns the bound receiver of the method object.

Returns:



# File 'proc.c'

/*
 *  call-seq:
 *     meth.receiver    -> object
 *
 *  Returns the bound receiver of the method object.
 */

static VALUE
method_receiver(VALUE obj)
{
    struct METHOD *data;

    TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
    return data->recv;
}

#source_locationArray

returns the ruby source filename and line number containing this method or nil if this method was not defined in ruby (i.e. native)

Returns:



# File 'proc.c'

/*
 * call-seq:
 *    meth.source_location  -> [String, Fixnum]
 *
 * returns the ruby source filename and line number containing this method
 * or nil if this method was not defined in ruby (i.e. native)
 */

VALUE
rb_method_location(VALUE method)
{
    rb_method_definition_t *def = method_get_def(method);
    if (def->type == VM_METHOD_TYPE_ATTRSET || def->type == VM_METHOD_TYPE_IVAR) {
    if (!def->body.attr.location)
        return Qnil;
    return rb_ary_dup(def->body.attr.location);
    }
    return iseq_location(method_get_iseq(def));
}

#to_procProc

Returns a Proc object corresponding to this method.

Returns:



# File 'proc.c'

/*
 *  call-seq:
 *     meth.to_proc    -> prc
 *
 *  Returns a <code>Proc</code> object corresponding to this method.
 */

static VALUE
method_proc(VALUE method)
{
    VALUE procval;
    rb_proc_t *proc;
    /*
     * class Method
     *   def to_proc
     *     proc{|*args|
     *       self.call(*args)
     *     }
     *   end
     * end
     */
    procval = rb_iterate(mlambda, 0, bmcall, method);
    GetProcPtr(procval, proc);
    proc->is_from_method = 1;
    return procval;
}

#to_sString #inspectString

Show the name of the underlying method.

"cat".method(:count).inspect   #=> "#<Method: String#count>"

Overloads:



# File 'proc.c'

/*
 *  call-seq:
 *   meth.to_s      ->  string
 *   meth.inspect   ->  string
 *
 *  Show the name of the underlying method.
 *
 *    "cat".method(:count).inspect   #=> "#<Method: String#count>"
 */

static VALUE
method_inspect(VALUE method)
{
    struct METHOD *data;
    VALUE str;
    const char *s;
    const char *sharp = "#";

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
    str = rb_str_buf_new2("#<");
    s = rb_obj_classname(method);
    rb_str_buf_cat2(str, s);
    rb_str_buf_cat2(str, ": ");

    if (FL_TEST(data->me.klass, FL_SINGLETON)) {
    VALUE v = rb_iv_get(data->me.klass, "__attached__");

    if (data->recv == Qundef) {
        rb_str_buf_append(str, rb_inspect(data->me.klass));
    }
    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 = ".";
    }
    }
    else {
    rb_str_buf_cat2(str, rb_class2name(data->rclass));
    if (data->rclass != data->me.klass) {
        rb_str_buf_cat2(str, "(");
        rb_str_buf_cat2(str, rb_class2name(data->me.klass));
        rb_str_buf_cat2(str, ")");
    }
    }
    rb_str_buf_cat2(str, sharp);
    rb_str_append(str, rb_id2str(data->me.def->original_id));
    if (data->me.def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
        rb_str_buf_cat2(str, " (not-implemented)");
    }
    rb_str_buf_cat2(str, ">");

    return str;
}

#unbindObject

Dissociates meth from it's current receiver. The resulting UnboundMethod can subsequently be bound to a new object of the same class (see UnboundMethod).



# File 'proc.c'

/*
 *  call-seq:
 *     meth.unbind    -> unbound_method
 *
 *  Dissociates <i>meth</i> from it's current receiver. The resulting
 *  <code>UnboundMethod</code> can subsequently be bound to a new object
 *  of the same class (see <code>UnboundMethod</code>).
 */

static VALUE
method_unbind(VALUE obj)
{
    VALUE method;
    struct METHOD *orig, *data;

    TypedData_Get_Struct(obj, struct METHOD, &method_data_type, orig);
    method = TypedData_Make_Struct(rb_cUnboundMethod, struct METHOD,
                   &method_data_type, data);
    data->recv = Qundef;
    data->id = orig->id;
    data->me = orig->me;
    if (orig->me.def) orig->me.def->alias_count++;
    data->rclass = orig->rclass;
    OBJ_INFECT(method, obj);

    return method;
}