Class: Method

Inherits:
Object show all
Defined in:
eval.c

Instance Method Summary collapse

Instance Method Details

#==(other_meth) ⇒ Boolean

Two method objects are equal if that are bound to the same object and contain the same body.

Returns:

  • (Boolean)


# File 'eval.c'

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


static VALUE
method_eq(method, other)
    VALUE method, other;
{
    struct METHOD *m1, *m2;

    if (TYPE(other) != T_DATA || RDATA(other)->dmark != (RUBY_DATA_FUNC)bm_mark)
    return Qfalse;
    if (CLASS_OF(method) != CLASS_OF(other))
    return Qfalse;

    Data_Get_Struct(method, struct METHOD, m1);
    Data_Get_Struct(other, struct METHOD, m2);

    if (m1->klass != m2->klass || m1->rklass != m2->rklass ||
    m1->recv != m2->recv || m1->body != m2->body)
    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 'eval.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
 */

static VALUE
method_call(argc, argv, method)
    int argc;
    VALUE *argv;
    VALUE method;
{
    VALUE result = Qnil;    /* OK */
    struct METHOD *data;
    int safe;

    Data_Get_Struct(method, struct METHOD, data);
    if (data->recv == Qundef) {
    rb_raise(rb_eTypeError, "can't call unbound method; bind first");
    }
    if (OBJ_TAINTED(method)) {
        safe = NOEX_WITH(data->safe_level, 4)|NOEX_TAINTED;
    }
    else {
    safe = data->safe_level;
    }
    PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
    result = rb_call0(data->klass,data->recv,data->id,data->oid,argc,argv,data->body,safe);
    POP_ITER();
    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 'eval.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(method)
    VALUE method;
{
    struct METHOD *data;
    NODE *body;
    int n;

    Data_Get_Struct(method, struct METHOD, data);

    body = data->body;
    switch (nd_type(body)) {
      case NODE_CFUNC:
    if (body->nd_argc < 0) return INT2FIX(-1);
    return INT2FIX(body->nd_argc);
      case NODE_ZSUPER:
    return INT2FIX(-1);
      case NODE_ATTRSET:
    return INT2FIX(1);
      case NODE_IVAR:
    return INT2FIX(0);
      case NODE_BMETHOD:
    return proc_arity(body->nd_cval);
      case NODE_DMETHOD:
    return method_arity(body->nd_cval);
      case NODE_SCOPE:
    body = body->nd_next;  /* skip NODE_SCOPE */
    if (nd_type(body) == NODE_BLOCK)
        body = body->nd_head;
    if (!body) return INT2FIX(0);
    n = body->nd_cnt;
    if (body->nd_opt || body->nd_rest)
        n = -n-1;
    return INT2FIX(n);
      default:
    rb_raise(rb_eArgError, "invalid node 0x%x", nd_type(body));
   }
}

#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 'eval.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
 */

static VALUE
method_call(argc, argv, method)
    int argc;
    VALUE *argv;
    VALUE method;
{
    VALUE result = Qnil;    /* OK */
    struct METHOD *data;
    int safe;

    Data_Get_Struct(method, struct METHOD, data);
    if (data->recv == Qundef) {
    rb_raise(rb_eTypeError, "can't call unbound method; bind first");
    }
    if (OBJ_TAINTED(method)) {
        safe = NOEX_WITH(data->safe_level, 4)|NOEX_TAINTED;
    }
    else {
    safe = data->safe_level;
    }
    PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
    result = rb_call0(data->klass,data->recv,data->id,data->oid,argc,argv,data->body,safe);
    POP_ITER();
    return result;
}

#cloneObject

MISSING: documentation



# File 'eval.c'

/*
 * MISSING: documentation
 */

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

    Data_Get_Struct(self, struct METHOD, orig);
    clone = Data_Make_Struct(CLASS_OF(self),struct METHOD, bm_mark, free, data);
    CLONESETUP(clone, self);
    *data = *orig;

    return clone;
}

#to_sString #inspectString

Show the name of the underlying method.

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

Overloads:



# File 'eval.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(method)
    VALUE method;
{
    struct METHOD *data;
    VALUE str;
    const char *s;
    const char *sharp = "#";

    Data_Get_Struct(method, struct METHOD, 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->klass, FL_SINGLETON)) {
    VALUE v = rb_iv_get(data->klass, "__attached__");

    if (data->recv == Qundef) {
        rb_str_buf_append(str, rb_inspect(data->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->rklass));
    if (data->rklass != data->klass) {
        rb_str_buf_cat2(str, "(");
        rb_str_buf_cat2(str, rb_class2name(data->klass));
        rb_str_buf_cat2(str, ")");
    }
    }
    rb_str_buf_cat2(str, sharp);
    rb_str_buf_cat2(str, rb_id2name(data->id));
    rb_str_buf_cat2(str, ">");

    return str;
}

#nameString

Returns the name of the method.

Returns:



# File 'eval.c'

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

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

    Data_Get_Struct(obj, struct METHOD, data);
    return rb_str_new2(rb_id2name(data->id));
}

#ownerObject

Returns the class or module that defines the method.



# File 'eval.c'

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

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

    Data_Get_Struct(obj, struct METHOD, data);
    return data->klass;
}

#receiverObject

Returns the bound receiver of the method object.

Returns:



# File 'eval.c'

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

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

    Data_Get_Struct(obj, struct METHOD, data);
    return data->recv;
}

#to_procProc

Returns a Proc object corresponding to this method.

Returns:



# File 'eval.c'

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

static VALUE
method_proc(method)
    VALUE method;
{
    VALUE proc;
    struct METHOD *mdata;
    struct BLOCK *bdata;

    proc = rb_iterate((VALUE(*)_((VALUE)))mproc, 0, bmcall, method);
    Data_Get_Struct(method, struct METHOD, mdata);
    Data_Get_Struct(proc, struct BLOCK, bdata);
    bdata->body->nd_file = mdata->body->nd_file;
    nd_set_line(bdata->body, nd_line(mdata->body));
    bdata->body->nd_state = YIELD_FUNC_SVALUE;

    return proc;
}

#to_sString #inspectString

Show the name of the underlying method.

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

Overloads:



# File 'eval.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(method)
    VALUE method;
{
    struct METHOD *data;
    VALUE str;
    const char *s;
    const char *sharp = "#";

    Data_Get_Struct(method, struct METHOD, 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->klass, FL_SINGLETON)) {
    VALUE v = rb_iv_get(data->klass, "__attached__");

    if (data->recv == Qundef) {
        rb_str_buf_append(str, rb_inspect(data->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->rklass));
    if (data->rklass != data->klass) {
        rb_str_buf_cat2(str, "(");
        rb_str_buf_cat2(str, rb_class2name(data->klass));
        rb_str_buf_cat2(str, ")");
    }
    }
    rb_str_buf_cat2(str, sharp);
    rb_str_buf_cat2(str, rb_id2name(data->id));
    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 'eval.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(obj)
    VALUE obj;
{
    VALUE method;
    struct METHOD *orig, *data;

    Data_Get_Struct(obj, struct METHOD, orig);
    method = Data_Make_Struct(rb_cUnboundMethod, struct METHOD, bm_mark, free, data);
    data->klass = orig->klass;
    data->recv = Qundef;
    data->id = orig->id;
    data->body = orig->body;
    data->rklass = orig->rklass;
    data->oid = orig->oid;
    OBJ_INFECT(method, obj);

    return method;
}