/*
 *  call-seq:
 *     prc.call(params,...)   => obj
 *     prc[params,...]        => obj
 *  
 *  Invokes the block, setting the block's parameters to the values in
 *  <i>params</i> using something close to method calling semantics.
 *  Generates a warning if multiple values are passed to a proc that
 *  expects just one (previously this silently converted the parameters
 *  to an array).
 *
 *  For procs created using <code>Kernel.proc</code>, generates an
 *  error if the wrong number of parameters
 *  are passed to a proc with multiple parameters. For procs created using
 *  <code>Proc.new</code>, extra parameters are silently discarded.
 *
 *  Returns the value of the last expression evaluated in the block. See
 *  also <code>Proc#yield</code>.
 *     
 *     a_proc = Proc.new {|a, *b| b.collect {|i| i*a }}
 *     a_proc.call(9, 1, 2, 3)   #=> [9, 18, 27]
 *     a_proc[9, 1, 2, 3]        #=> [9, 18, 27]
 *     a_proc = Proc.new {|a,b| a}
 *     a_proc.call(1,2,3)
 *     
 *  <em>produces:</em>
 *     
 *     prog.rb:5: wrong number of arguments (3 for 2) (ArgumentError)
 *      from prog.rb:4:in `call'
 *      from prog.rb:5
 */

static VALUE
proc_call(int argc, VALUE *argv, VALUE procval)
{
    rb_proc_t *proc;
    rb_block_t *blockptr = 0;
    GetProcPtr(procval, proc);

    if (BUILTIN_TYPE(proc->block.iseq) != T_NODE &&
        proc->block.iseq->arg_block != -1) {

        if (rb_block_given_p()) {
            rb_proc_t *proc;
            VALUE procval;
            procval = rb_block_proc();
            GetProcPtr(procval, proc);
            blockptr = &proc->block;
        }
    }

    return vm_invoke_proc(GET_THREAD(), proc, proc->block.self,
                          argc, argv, blockptr);
}