summaryrefslogtreecommitdiff
path: root/proc.c
diff options
context:
space:
mode:
authornagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-08-04 14:31:52 +0000
committernagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-08-04 14:31:52 +0000
commit568472906b178607ee569bff0d3074c27515719e (patch)
tree2aa58a2e021f7a30b7091f5b1417782ec0d3e485 /proc.c
parent91b51140d7f2b79f8fb7d0ea8901de89fa0304d6 (diff)
merge revision(s) 59357,59358: [Backport #13391] [Backport #13404]
proc.c: rb_block_min_max_arity * proc.c (rb_block_min_max_arity): new function to get arity range from the current block. vm_eval.c: rb_lambda_call * enum.c (enum_collect): make the block arity same as the given block. [Bug #13391] * internal.h (vm_ifunc): store arity instead of unused id. * proc.c (rb_vm_block_min_max_arity): return ifunc arity. * vm_eval.c (rb_lambda_call): call method with lambda block. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_4@59500 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'proc.c')
-rw-r--r--proc.c66
1 files changed, 57 insertions, 9 deletions
diff --git a/proc.c b/proc.c
index ba8242e01a..da8c763799 100644
--- a/proc.c
+++ b/proc.c
@@ -635,16 +635,47 @@ sym_proc_new(VALUE klass, VALUE sym)
return procval;
}
+struct vm_ifunc *
+rb_vm_ifunc_new(VALUE (*func)(ANYARGS), const void *data, int min_argc, int max_argc)
+{
+ union {
+ struct vm_ifunc_argc argc;
+ VALUE packed;
+ } arity;
+
+ if (min_argc < UNLIMITED_ARGUMENTS ||
+#if SIZEOF_INT * 2 > SIZEOF_VALUE
+ min_argc >= (int)(1U << (SIZEOF_VALUE * CHAR_BIT) / 2) ||
+#endif
+ 0) {
+ rb_raise(rb_eRangeError, "minimum argument number out of range: %d",
+ min_argc);
+ }
+ if (max_argc < UNLIMITED_ARGUMENTS ||
+#if SIZEOF_INT * 2 > SIZEOF_VALUE
+ max_argc >= (int)(1U << (SIZEOF_VALUE * CHAR_BIT) / 2) ||
+#endif
+ 0) {
+ rb_raise(rb_eRangeError, "maximum argument number out of range: %d",
+ max_argc);
+ }
+ arity.argc.min = min_argc;
+ arity.argc.max = max_argc;
+ return IFUNC_NEW(func, data, arity.packed);
+}
+
VALUE
rb_func_proc_new(rb_block_call_func_t func, VALUE val)
{
- return cfunc_proc_new(rb_cProc, (VALUE)IFUNC_NEW(func, val, 0), 0);
+ struct vm_ifunc *ifunc = rb_vm_ifunc_proc_new(func, (void *)val);
+ return cfunc_proc_new(rb_cProc, (VALUE)ifunc, 0);
}
VALUE
-rb_func_lambda_new(rb_block_call_func_t func, VALUE val)
+rb_func_lambda_new(rb_block_call_func_t func, VALUE val, int min_argc, int max_argc)
{
- return cfunc_proc_new(rb_cProc, (VALUE)IFUNC_NEW(func, val, 0), 1);
+ struct vm_ifunc *ifunc = rb_vm_ifunc_new(func, (void *)val, min_argc, max_argc);
+ return cfunc_proc_new(rb_cProc, (VALUE)ifunc, 1);
}
static const char proc_without_block[] = "tried to create Proc object without a block";
@@ -928,13 +959,13 @@ rb_iseq_min_max_arity(const rb_iseq_t *iseq, int *max)
}
static int
-rb_block_min_max_arity(const struct rb_block *block, int *max)
+rb_vm_block_min_max_arity(const struct rb_block *block, int *max)
{
switch (vm_block_type(block)) {
case block_type_iseq:
return rb_iseq_min_max_arity(block->as.captured.code.iseq, max);
case block_type_proc:
- return rb_block_min_max_arity(vm_proc_block(block->as.proc), max);
+ return rb_vm_block_min_max_arity(vm_proc_block(block->as.proc), max);
case block_type_ifunc:
{
const struct vm_ifunc *ifunc = block->as.captured.code.ifunc;
@@ -942,8 +973,9 @@ rb_block_min_max_arity(const struct rb_block *block, int *max)
/* e.g. method(:foo).to_proc.arity */
return method_min_max_arity((VALUE)ifunc->data, max);
}
+ *max = ifunc->argc.max;
+ return ifunc->argc.min;
}
- /* fall through */
case block_type_symbol:
break;
}
@@ -962,7 +994,7 @@ rb_proc_min_max_arity(VALUE self, int *max)
{
rb_proc_t *proc;
GetProcPtr(self, proc);
- return rb_block_min_max_arity(&proc->block, max);
+ return rb_vm_block_min_max_arity(&proc->block, max);
}
int
@@ -971,7 +1003,7 @@ rb_proc_arity(VALUE self)
rb_proc_t *proc;
int max, min;
GetProcPtr(self, proc);
- min = rb_block_min_max_arity(&proc->block, &max);
+ min = rb_vm_block_min_max_arity(&proc->block, &max);
return (proc->is_lambda ? min == max : max != UNLIMITED_ARGUMENTS) ? min : -min-1;
}
@@ -1011,7 +1043,7 @@ rb_block_arity(void)
}
block_setup(&block, block_handler);
- min = rb_block_min_max_arity(&block, &max);
+ min = rb_vm_block_min_max_arity(&block, &max);
switch (vm_block_type(&block)) {
case block_handler_type_symbol:
@@ -1031,6 +1063,22 @@ rb_block_arity(void)
}
}
+int
+rb_block_min_max_arity(int *max)
+{
+ rb_thread_t *th = GET_THREAD();
+ rb_control_frame_t *cfp = th->cfp;
+ VALUE block_handler = rb_vm_frame_block_handler(cfp);
+ struct rb_block block;
+
+ if (block_handler == VM_BLOCK_HANDLER_NONE) {
+ rb_raise(rb_eArgError, "no block given");
+ }
+
+ block_setup(&block, block_handler);
+ return rb_vm_block_min_max_arity(&block, max);
+}
+
const rb_iseq_t *
rb_proc_get_iseq(VALUE self, int *is_proc)
{