summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eval.c158
-rw-r--r--intern.h3
-rw-r--r--node.h1
3 files changed, 103 insertions, 59 deletions
diff --git a/eval.c b/eval.c
index 8674c8c43..b4e3ea96b 100644
--- a/eval.c
+++ b/eval.c
@@ -4581,7 +4581,7 @@ break_jump(retval)
}
static VALUE bmcall _((VALUE, VALUE));
-static VALUE method_arity _((VALUE));
+static int method_arity _((VALUE));
static VALUE
kk()
@@ -8275,28 +8275,8 @@ proc_call(proc, args)
return proc_invoke(proc, args, Qundef, 0);
}
-/*
- * call-seq:
- * prc.arity -> fixnum
- *
- * Returns the number of arguments required by the block. If the block
- * is declared to take no arguments, returns 0. If the block is known
- * to take exactly n arguments, returns n. If the block has optional
- * arguments, return -n-1, where n is the number of mandatory
- * arguments. A <code>proc</code> with no argument declarations
- * is handled like a block declaring <code>||</code> as its arguments.
- *
- * Proc.new {}.arity #=> 0
- * Proc.new {||}.arity #=> 0
- * Proc.new {|a|}.arity #=> 1
- * Proc.new {|a,b|}.arity #=> 2
- * Proc.new {|a,b,c|}.arity #=> 3
- * Proc.new {|*a|}.arity #=> -1
- * Proc.new {|a,*b|}.arity #=> -2
- */
-
-static VALUE
-proc_arity(proc)
+int
+rb_proc_arity(proc)
VALUE proc;
{
struct BLOCK *data;
@@ -8310,18 +8290,18 @@ proc_arity(proc)
data->body->nd_cfnc == bmcall) {
return method_arity(data->body->nd_tval);
}
- return INT2FIX(0);
+ return 0;
}
- if (var == (NODE*)1) return INT2FIX(0);
- if (var == (NODE*)2) return INT2FIX(0);
+ if (var == (NODE*)1) return 0;
+ if (var == (NODE*)2) return 0;
if (nd_type(var) == NODE_BLOCK_ARG) {
var = var->nd_args;
- if (var == (NODE*)1) return INT2FIX(0);
- if (var == (NODE*)2) return INT2FIX(0);
+ if (var == (NODE*)1) return 0;
+ if (var == (NODE*)2) return 0;
}
switch (nd_type(var)) {
default:
- return INT2FIX(1);
+ return 1;
case NODE_MASGN:
list = var->nd_head;
n = 0;
@@ -8329,12 +8309,40 @@ proc_arity(proc)
n++;
list = list->nd_next;
}
- if (var->nd_args) return INT2FIX(-n-1);
- return INT2FIX(n);
+ if (var->nd_args) return -n-1;
+ return n;
}
}
/*
+ * call-seq:
+ * prc.arity -> fixnum
+ *
+ * Returns the number of arguments required by the block. If the block
+ * is declared to take no arguments, returns 0. If the block is known
+ * to take exactly n arguments, returns n. If the block has optional
+ * arguments, return -n-1, where n is the number of mandatory
+ * arguments. A <code>proc</code> with no argument declarations
+ * is handled like a block declaring <code>||</code> as its arguments.
+ *
+ * Proc.new {}.arity #=> 0
+ * Proc.new {||}.arity #=> 0
+ * Proc.new {|a|}.arity #=> 1
+ * Proc.new {|a,b|}.arity #=> 2
+ * Proc.new {|a,b,c|}.arity #=> 3
+ * Proc.new {|*a|}.arity #=> -1
+ * Proc.new {|a,*b|}.arity #=> -2
+ */
+
+static VALUE
+proc_arity(proc)
+ VALUE proc;
+{
+ int arity = rb_proc_arity(proc);
+ return INT2FIX(arity);
+}
+
+/*
* call-seq:
* prc == other_proc => true or false
*
@@ -8612,7 +8620,7 @@ mnew(klass, obj, id, mklass)
rklass = RCLASS(rklass)->super;
}
if (TYPE(klass) == T_ICLASS) klass = RBASIC(klass)->klass;
- method = Data_Make_Struct(mklass, struct METHOD, bm_mark, free, data);
+ method = Data_Make_Struct(mklass, struct METHOD, bm_mark, -1, data);
data->klass = klass;
data->recv = obj;
data->id = id;
@@ -8986,6 +8994,38 @@ umethod_bind(method, recv)
return method;
}
+int
+rb_node_arity(body)
+ NODE *body;
+{
+ int n;
+
+ switch (nd_type(body)) {
+ case NODE_CFUNC:
+ if (body->nd_argc < 0) return -1;
+ return body->nd_argc;
+ case NODE_ZSUPER:
+ return -1;
+ case NODE_ATTRSET:
+ return 1;
+ case NODE_IVAR:
+ return 0;
+ case NODE_BMETHOD:
+ return rb_proc_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 0;
+ n = body->nd_cnt;
+ if (body->nd_opt || body->nd_rest != -1)
+ n = -n-1;
+ return n;
+ default:
+ rb_raise(rb_eArgError, "invalid node 0x%x", nd_type(body));
+ }
+}
+
/*
* call-seq:
* meth.arity => fixnum
@@ -9020,38 +9060,38 @@ umethod_bind(method, recv)
*/
static VALUE
+method_arity_m(method)
+ VALUE method;
+{
+ int n = method_arity(method);
+ return INT2FIX(n);
+}
+
+static int
method_arity(method)
VALUE method;
{
struct METHOD *data;
- NODE *body;
- int n;
Data_Get_Struct(method, struct METHOD, data);
+ return rb_node_arity(data->body);
+}
- 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);
- default:
- 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 != -1)
- n = -n-1;
- return INT2FIX(n);
- }
+int
+rb_mod_method_arity(mod, id)
+ VALUE mod;
+ ID id;
+{
+ NODE *node = rb_method_node(mod, id);
+ return rb_node_arity(node);
+}
+
+int
+rb_obj_method_arity(obj, id)
+ VALUE obj;
+ ID id;
+{
+ return rb_mod_method_arity(CLASS_OF(obj), id);
}
/*
@@ -9360,7 +9400,7 @@ Init_Proc()
rb_define_method(rb_cMethod, "clone", method_clone, 0);
rb_define_method(rb_cMethod, "call", method_call, -1);
rb_define_method(rb_cMethod, "[]", method_call, -1);
- rb_define_method(rb_cMethod, "arity", method_arity, 0);
+ rb_define_method(rb_cMethod, "arity", method_arity_m, 0);
rb_define_method(rb_cMethod, "inspect", method_inspect, 0);
rb_define_method(rb_cMethod, "to_s", method_inspect, 0);
rb_define_method(rb_cMethod, "to_proc", method_proc, 0);
@@ -9374,7 +9414,7 @@ Init_Proc()
rb_define_method(rb_cUnboundMethod, "eql?", method_eq, 1);
rb_define_method(rb_cUnboundMethod, "hash", method_hash, 0);
rb_define_method(rb_cUnboundMethod, "clone", method_clone, 0);
- rb_define_method(rb_cUnboundMethod, "arity", method_arity, 0);
+ rb_define_method(rb_cUnboundMethod, "arity", method_arity_m, 0);
rb_define_method(rb_cUnboundMethod, "inspect", method_inspect, 0);
rb_define_method(rb_cUnboundMethod, "to_s", method_inspect, 0);
rb_define_method(rb_cUnboundMethod, "bind", umethod_bind, 1);
diff --git a/intern.h b/intern.h
index c0aa9a738..841ade431 100644
--- a/intern.h
+++ b/intern.h
@@ -190,6 +190,9 @@ VALUE rb_class_new_instance _((int, VALUE*, VALUE));
VALUE rb_block_proc _((void));
VALUE rb_f_lambda _((void));
VALUE rb_proc_new _((VALUE (*)(ANYARGS/* VALUE yieldarg[, VALUE procarg] */), VALUE));
+int rb_proc_arity _((VALUE));
+int rb_mod_method_arity _((VALUE, ID));
+int rb_obj_method_arity _((VALUE, ID));
VALUE rb_protect _((VALUE (*)(VALUE), VALUE, int*));
void rb_set_end_proc _((void (*)(VALUE), VALUE));
void rb_mark_end_proc _((void));
diff --git a/node.h b/node.h
index 6c8acb59b..13b0279f3 100644
--- a/node.h
+++ b/node.h
@@ -357,6 +357,7 @@ void rb_add_method _((VALUE, ID, NODE *, int));
NODE *rb_node_newnode _((enum node_type,VALUE,VALUE,VALUE));
NODE* rb_method_node _((VALUE klass, ID id));
+int rb_node_arity _((NODE* node));
struct global_entry *rb_global_entry _((ID));
VALUE rb_gvar_get _((struct global_entry *));