mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* proc.c: Add {*}_min_max_arity and refactor.
[Bug #7765] * test/ruby/test_proc.rb: Fix wrong test git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39007 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
4b4d889fe0
commit
83610815d4
3 changed files with 84 additions and 35 deletions
|
@ -1,3 +1,10 @@
|
||||||
|
Sat Feb 2 07:44:15 2013 Marc-Andre Lafortune <ruby-core@marc-andre.ca>
|
||||||
|
|
||||||
|
* proc.c: Add {*}_min_max_arity and refactor.
|
||||||
|
[Bug #7765]
|
||||||
|
|
||||||
|
* test/ruby/test_proc.rb: Fix wrong test
|
||||||
|
|
||||||
Fri Feb 2 00:46:00 2013 Charlie Somerville <charlie@charliesomerville.com>
|
Fri Feb 2 00:46:00 2013 Charlie Somerville <charlie@charliesomerville.com>
|
||||||
|
|
||||||
* marshal.c: add security considerations to marshal overview, refer to
|
* marshal.c: add security considerations to marshal overview, refer to
|
||||||
|
|
110
proc.c
110
proc.c
|
@ -30,6 +30,7 @@ VALUE rb_cProc;
|
||||||
|
|
||||||
static VALUE bmcall(VALUE, VALUE);
|
static VALUE bmcall(VALUE, VALUE);
|
||||||
static int method_arity(VALUE);
|
static int method_arity(VALUE);
|
||||||
|
static int method_min_max_arity(VALUE, int *max);
|
||||||
static ID attached;
|
static ID attached;
|
||||||
|
|
||||||
/* Proc */
|
/* Proc */
|
||||||
|
@ -655,8 +656,23 @@ proc_arity(VALUE self)
|
||||||
return INT2FIX(arity);
|
return INT2FIX(arity);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static inline int
|
||||||
rb_proc_arity(VALUE self)
|
rb_iseq_min_max_arity(const rb_iseq_t *iseq, int *max)
|
||||||
|
{
|
||||||
|
*max = iseq->arg_rest == -1 ?
|
||||||
|
iseq->argc + iseq->arg_post_len + iseq->arg_opts - (iseq->arg_opts > 0)
|
||||||
|
: UNLIMITED_ARGUMENTS;
|
||||||
|
return iseq->argc + iseq->arg_post_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the number of required parameters and stores the maximum
|
||||||
|
* number of parameters in max, or UNLIMITED_ARGUMENTS if no max.
|
||||||
|
* For non-lambda procs, the maximum is the number of non-ignored
|
||||||
|
* parameters even though there is no actual limit to the number of parameters
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
rb_proc_min_max_arity(VALUE self, int *max)
|
||||||
{
|
{
|
||||||
rb_proc_t *proc;
|
rb_proc_t *proc;
|
||||||
rb_iseq_t *iseq;
|
rb_iseq_t *iseq;
|
||||||
|
@ -664,22 +680,27 @@ rb_proc_arity(VALUE self)
|
||||||
iseq = proc->block.iseq;
|
iseq = proc->block.iseq;
|
||||||
if (iseq) {
|
if (iseq) {
|
||||||
if (BUILTIN_TYPE(iseq) != T_NODE) {
|
if (BUILTIN_TYPE(iseq) != T_NODE) {
|
||||||
if (iseq->arg_rest < 0 && (!proc->is_lambda || iseq->arg_opts == 0)) {
|
return rb_iseq_min_max_arity(iseq, max);
|
||||||
return iseq->argc;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return -(iseq->argc + 1 + iseq->arg_post_len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
NODE *node = (NODE *)iseq;
|
NODE *node = (NODE *)iseq;
|
||||||
if (IS_METHOD_PROC_NODE(node)) {
|
if (IS_METHOD_PROC_NODE(node)) {
|
||||||
/* method(:foo).to_proc.arity */
|
/* e.g. method(:foo).to_proc.arity */
|
||||||
return method_arity(node->nd_tval);
|
return method_min_max_arity(node->nd_tval, max);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
*max = UNLIMITED_ARGUMENTS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_proc_arity(VALUE self)
|
||||||
|
{
|
||||||
|
rb_proc_t *proc;
|
||||||
|
int max, min = rb_proc_min_max_arity(self, &max);
|
||||||
|
GetProcPtr(self, proc);
|
||||||
|
return (proc->is_lambda ? min == max : max != UNLIMITED_ARGUMENTS) ? min : -min-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define get_proc_iseq rb_proc_get_iseq
|
#define get_proc_iseq rb_proc_get_iseq
|
||||||
|
@ -1646,54 +1667,66 @@ umethod_bind(VALUE method, VALUE recv)
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
/*
|
||||||
rb_method_entry_arity(const rb_method_entry_t *me)
|
* Returns the number of required parameters and stores the maximum
|
||||||
|
* number of parameters in max, or UNLIMITED_ARGUMENTS
|
||||||
|
* if there is no maximum.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
rb_method_entry_min_max_arity(const rb_method_entry_t *me, int *max)
|
||||||
{
|
{
|
||||||
const rb_method_definition_t *def = me->def;
|
const rb_method_definition_t *def = me->def;
|
||||||
if (!def) return 0;
|
if (!def) return *max = 0;
|
||||||
switch (def->type) {
|
switch (def->type) {
|
||||||
case VM_METHOD_TYPE_CFUNC:
|
case VM_METHOD_TYPE_CFUNC:
|
||||||
if (def->body.cfunc.argc < 0)
|
if (def->body.cfunc.argc < 0) {
|
||||||
return -1;
|
*max = UNLIMITED_ARGUMENTS;
|
||||||
return check_argc(def->body.cfunc.argc);
|
return 0;
|
||||||
|
}
|
||||||
|
return *max = check_argc(def->body.cfunc.argc);
|
||||||
case VM_METHOD_TYPE_ZSUPER:
|
case VM_METHOD_TYPE_ZSUPER:
|
||||||
return -1;
|
*max = UNLIMITED_ARGUMENTS;
|
||||||
case VM_METHOD_TYPE_ATTRSET:
|
|
||||||
return 1;
|
|
||||||
case VM_METHOD_TYPE_IVAR:
|
|
||||||
return 0;
|
return 0;
|
||||||
|
case VM_METHOD_TYPE_ATTRSET:
|
||||||
|
return *max = 1;
|
||||||
|
case VM_METHOD_TYPE_IVAR:
|
||||||
|
return *max = 0;
|
||||||
case VM_METHOD_TYPE_BMETHOD:
|
case VM_METHOD_TYPE_BMETHOD:
|
||||||
return rb_proc_arity(def->body.proc);
|
return rb_proc_min_max_arity(def->body.proc, max);
|
||||||
case VM_METHOD_TYPE_ISEQ: {
|
case VM_METHOD_TYPE_ISEQ: {
|
||||||
rb_iseq_t *iseq = def->body.iseq;
|
rb_iseq_t *iseq = def->body.iseq;
|
||||||
if (iseq->arg_rest == -1 && iseq->arg_opts == 0) {
|
return rb_iseq_min_max_arity(iseq, max);
|
||||||
return iseq->argc;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return -(iseq->argc + 1 + iseq->arg_post_len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case VM_METHOD_TYPE_UNDEF:
|
case VM_METHOD_TYPE_UNDEF:
|
||||||
case VM_METHOD_TYPE_NOTIMPLEMENTED:
|
case VM_METHOD_TYPE_NOTIMPLEMENTED:
|
||||||
return 0;
|
return *max = 0;
|
||||||
case VM_METHOD_TYPE_MISSING:
|
case VM_METHOD_TYPE_MISSING:
|
||||||
return -1;
|
*max = UNLIMITED_ARGUMENTS;
|
||||||
|
return 0;
|
||||||
case VM_METHOD_TYPE_OPTIMIZED: {
|
case VM_METHOD_TYPE_OPTIMIZED: {
|
||||||
switch (def->body.optimize_type) {
|
switch (def->body.optimize_type) {
|
||||||
case OPTIMIZED_METHOD_TYPE_SEND:
|
case OPTIMIZED_METHOD_TYPE_SEND:
|
||||||
return -1;
|
*max = UNLIMITED_ARGUMENTS;
|
||||||
|
return 0;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case VM_METHOD_TYPE_REFINED:
|
case VM_METHOD_TYPE_REFINED:
|
||||||
return -1;
|
*max = UNLIMITED_ARGUMENTS;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
rb_bug("rb_method_entry_arity: invalid method entry type (%d)", def->type);
|
rb_bug("rb_method_entry_min_max_arity: invalid method entry type (%d)", def->type);
|
||||||
|
|
||||||
UNREACHABLE;
|
UNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_method_entry_arity(const rb_method_entry_t *me)
|
||||||
|
{
|
||||||
|
int max, min = rb_method_entry_min_max_arity(me, &max);
|
||||||
|
return min == max ? min : -min-1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* meth.arity -> fixnum
|
* meth.arity -> fixnum
|
||||||
|
@ -1758,6 +1791,15 @@ original_method_entry(VALUE mod, ID id)
|
||||||
return me;
|
return me;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
method_min_max_arity(VALUE method, int *max)
|
||||||
|
{
|
||||||
|
struct METHOD *data;
|
||||||
|
|
||||||
|
TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
|
||||||
|
return rb_method_entry_min_max_arity(data->me, max);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rb_mod_method_arity(VALUE mod, ID id)
|
rb_mod_method_arity(VALUE mod, ID id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,7 +64,7 @@ class TestProc < Test::Unit::TestCase
|
||||||
assert_equal(1, proc{|x|}.arity)
|
assert_equal(1, proc{|x|}.arity)
|
||||||
assert_equal(0, proc{|x=1|}.arity)
|
assert_equal(0, proc{|x=1|}.arity)
|
||||||
assert_equal(2, proc{|x, y|}.arity)
|
assert_equal(2, proc{|x, y|}.arity)
|
||||||
assert_equal(0, proc{|x=0, y|}.arity)
|
assert_equal(1, proc{|x=0, y|}.arity)
|
||||||
assert_equal(0, proc{|x=0, y=0|}.arity)
|
assert_equal(0, proc{|x=0, y=0|}.arity)
|
||||||
assert_equal(1, proc{|x, y=0|}.arity)
|
assert_equal(1, proc{|x, y=0|}.arity)
|
||||||
assert_equal(-2, proc{|x, *y|}.arity)
|
assert_equal(-2, proc{|x, *y|}.arity)
|
||||||
|
|
Loading…
Reference in a new issue