summaryrefslogtreecommitdiff
path: root/vm.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-06-05 17:26:00 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-06-05 17:26:00 +0000
commit78029f00d5e330ea7bb594d1abef54e490effc2d (patch)
treeeb64aff859d41df51655b33169b0e019892e3cf4 /vm.c
parentd686a73d917ef73bd969c2085b89114f1a2ed2ea (diff)
* parse.y (new_yield), compile.c (iseq_compile_each): fix
passing parameter. * eval.c, eval_jump.h: simplify rb_yield*. * proc.c (proc_mark): fix to mark proc->block.proc. * proc.c (Init_Proc): add Proc#lambda? * test/ruby/test_lambda.rb: add some tests. * vm.c (invoke_block): fix to check lambda block or not. * vm.c (th_yield_setup_args): fix to check arguments size when lambda block. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12441 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm.c')
-rw-r--r--vm.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/vm.c b/vm.c
index 4ec0a8f8ae..603d4d0743 100644
--- a/vm.c
+++ b/vm.c
@@ -51,6 +51,8 @@ VALUE th_eval_body(rb_thread_t *th);
static NODE *lfp_get_special_cref(VALUE *lfp);
static NODE *lfp_set_special_cref(VALUE *lfp, NODE * cref);
+static inline int block_proc_is_lambda(VALUE procval);
+
#if OPT_STACK_CACHING
static VALUE yarv_finish_insn_seq[1] = { BIN(finish_SC_ax_ax) };
#elif OPT_CALL_THREADED_CODE
@@ -738,6 +740,12 @@ th_yield_setup_args(rb_thread_t *th, rb_iseq_t *iseq,
th->mark_stack_len = argc = iseq->argc;
}
}
+ else if (iseq->argc > argc) {
+ if (lambda) {
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
+ argc, iseq->argc);
+ }
+ }
}
else {
int r = iseq->arg_rest;
@@ -777,18 +785,23 @@ th_yield_setup_args(rb_thread_t *th, rb_iseq_t *iseq,
}
static VALUE
-invoke_block(rb_thread_t *th, rb_block_t *block, VALUE self, int argc, VALUE *argv, int magic)
+invoke_block(rb_thread_t *th, rb_block_t *block, VALUE self, int argc, VALUE *argv)
{
VALUE val;
if (BUILTIN_TYPE(block->iseq) != T_NODE) {
rb_iseq_t *iseq = block->iseq;
int i;
+ int magic = block_proc_is_lambda(block->proc) ?
+ FRAME_MAGIC_LAMBDA : FRAME_MAGIC_BLOCK;
+
th_set_finish_env(th);
/* TODO: check overflow */
+
for (i=0; i<argc; i++) {
th->cfp->sp[i] = argv[i];
}
+
argc = th_yield_setup_args(th, iseq, argc, th->cfp->sp, magic == FRAME_MAGIC_LAMBDA);
th->cfp->sp += argc;
@@ -818,7 +831,7 @@ th_yield(rb_thread_t *th, int argc, VALUE *argv)
th_localjump_error("no block given", Qnil, 0);
}
- return invoke_block(th, block, block->self, argc, argv, FRAME_MAGIC_BLOCK);
+ return invoke_block(th, block, block->self, argc, argv);
}
VALUE
@@ -836,8 +849,7 @@ th_invoke_proc(rb_thread_t *th, rb_proc_t *proc,
if ((state = EXEC_TAG()) == 0) {
th->safe_level = proc->safe_level;
- val = invoke_block(th, &proc->block, self, argc, argv,
- proc->is_lambda ? FRAME_MAGIC_LAMBDA : FRAME_MAGIC_PROC);
+ val = invoke_block(th, &proc->block, self, argc, argv);
}
else {
if (state == TAG_BREAK ||