summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--compile.c25
-rw-r--r--insnhelper.ci164
-rw-r--r--insns.def15
-rw-r--r--parse.y4
-rw-r--r--version.h6
-rw-r--r--vm.c7
7 files changed, 152 insertions, 79 deletions
diff --git a/ChangeLog b/ChangeLog
index b8130f5ea8..d9d30b3abd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Tue Jun 26 00:28:44 2007 Koichi Sasada <ko1@atdot.net>
+
+ * insnhelper.ci, vm.c: complete block parameter support.
+ post arguments, optional arguments, block argument.
+
+ * compile.c, parse.y: fix {|a|} parameter.
+
+ * insnshelper.ci, insns.def: revert caller_setup_args() option
+ (need_block_check) parameter.
+
Mon Jun 25 20:18:44 2007 NAKAMURA Usaku <usa@ruby-lang.org>
* gc.c (RVALUE): in RVALUE and RBasic, flags must be the same type.
diff --git a/compile.c b/compile.c
index e84cc827ad..5d4ed1b785 100644
--- a/compile.c
+++ b/compile.c
@@ -774,6 +774,7 @@ set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args)
NODE *node_aux = node_args->nd_next;
NODE *node_opt = node_args->nd_opt;
ID rest_id = 0;
+ int last_comma = 0;
ID block_id = 0;
NODE *node_init = 0;
@@ -784,13 +785,14 @@ set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args)
/*
* new argument infromation:
- * NODE_ARGS [m: int, o: NODE_OPT_ARG, ->]
- * NODE_ARGS_AUX [r: ID, b: ID, ->]
- * NODE_ARGS_AUX [Pst: id, Plen: int, init: NODE*]
+ * NODE_ARGS [m: int, o: NODE_OPT_ARG, ->]
+ * NODE_ARGS_AUX [r: ID, b: ID, ->]
+ * NODE_ARGS_AUX [Pst: id, Plen: int, init: NODE*]
* optarg information:
- * NODE_OPT_ARGS [idx, expr, ->]
+ * NODE_OPT_ARGS [idx, expr, next ->]
* init arg:
* NODE_AND(m_init, p_init)
+ * if "r" is 1, it's means "{|x,|}" type block parameter.
*/
iseq->argc = node_args->nd_frml;
@@ -798,6 +800,10 @@ set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args)
if (node_aux) {
rest_id = node_aux->nd_rest;
+ if (rest_id == 1) {
+ last_comma = 1;
+ rest_id = 0;
+ }
block_id = (ID)node_aux->nd_body;
node_aux = node_aux->nd_next;
@@ -891,7 +897,18 @@ set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args)
iseq->arg_simple = 1;
iseq->arg_size = iseq->argc;
}
+
+ if (iseq->type == ISEQ_TYPE_BLOCK) {
+ if (iseq->argc == 1 && iseq->arg_simple == 1 && last_comma == 0) {
+ /* {|a|} */
+ iseq->arg_simple = 2;
+ }
+ }
}
+ else {
+ iseq->arg_simple = 1;
+ }
+
return COMPILE_OK;
}
diff --git a/insnhelper.ci b/insnhelper.ci
index 8cb5eb5415..5c25a0e0bf 100644
--- a/insnhelper.ci
+++ b/insnhelper.ci
@@ -161,7 +161,7 @@ vm_callee_setup_arg(rb_thread_t *th, rb_iseq_t *iseq,
}
/* block arguments */
- if (iseq->arg_block != -1) {
+ if (block && iseq->arg_block != -1) {
VALUE blockval = Qnil;
rb_block_t * const blockptr = *block;
@@ -190,13 +190,12 @@ vm_callee_setup_arg(rb_thread_t *th, rb_iseq_t *iseq,
}
static inline int
-caller_setup_args(rb_thread_t *th, rb_control_frame_t *cfp,
- VALUE flag, int argc, rb_iseq_t *blockiseq,
- rb_block_t **block, int need_block_check)
+caller_setup_args(rb_thread_t *th, rb_control_frame_t *cfp, VALUE flag,
+ int argc, rb_iseq_t *blockiseq, rb_block_t **block)
{
rb_block_t *blockptr = 0;
- if (need_block_check) {
+ if (block) {
if (flag & VM_CALL_ARGS_BLOCKARG_BIT) {
rb_proc_t *po;
VALUE proc;
@@ -595,88 +594,133 @@ static inline int
vm_yield_setup_args(rb_thread_t *th, rb_iseq_t *iseq,
int argc, VALUE *argv, int lambda)
{
- int i, arg_n = iseq->argc + (iseq->arg_rest == -1 ? 0 : 1);
- th->mark_stack_len = argc;
-
if (0) { /* for debug */
- int i;
- GET_THREAD()->cfp->sp += argc;
- for(i=0; i<argc; i++){
- dp(argv[i]);
- }
-
printf(" argc: %d\n", argc);
printf("iseq argc: %d\n", iseq->argc);
+ printf("iseq opts: %d\n", iseq->arg_opts);
printf("iseq rest: %d\n", iseq->arg_rest);
+ printf("iseq post: %d\n", iseq->arg_post_len);
printf("iseq blck: %d\n", iseq->arg_block);
+ printf("iseq smpl: %d\n", iseq->arg_simple);
printf(" lambda: %s\n", lambda ? "true" : "false");
- GET_THREAD()->cfp->sp -= argc;
}
- if (lambda == 0 && argc == 1 && TYPE(argv[0]) == T_ARRAY && arg_n != 1) {
- VALUE ary = argv[0];
- th->mark_stack_len = argc = RARRAY_LEN(ary);
-
- CHECK_STACK_OVERFLOW(th->cfp, argc);
-
- for (i=0; i<argc; i++) {
- argv[i] = RARRAY_PTR(ary)[i];
+ if (lambda) {
+ /* call as method */
+ if (iseq->arg_block != -1) {
+ volatile VALUE procval = Qnil;
+
+ if (rb_block_given_p()) {
+ rb_block_t *blockptr;
+ rb_proc_t *proc;
+ procval = rb_block_proc();
+ GetProcPtr(procval, proc);
+ blockptr = &proc->block;
+ return vm_callee_setup_arg(th, iseq, argc, argv, &blockptr);
+ }
}
+ return vm_callee_setup_arg(th, iseq, argc, argv, 0);
}
+ else {
+ int i;
+ const int m = iseq->argc;
- if (iseq->arg_rest == -1) {
+ th->mark_stack_len = argc;
- if (iseq->argc < argc) {
- if (lambda) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
- argc, iseq->argc);
- }
- else {
- /* simple truncate */
- th->mark_stack_len = argc = iseq->argc;
+ /*
+ * yield [1, 2]
+ * => {|a|} => a = [1, 2]
+ * => {|a, b|} => a, b = [1, 2]
+ */
+ if (iseq->arg_simple != 2 && m > 0 && argc == 1 && TYPE(argv[0]) == T_ARRAY) {
+ VALUE ary = argv[0];
+ th->mark_stack_len = argc = RARRAY_LEN(ary);
+
+ CHECK_STACK_OVERFLOW(th->cfp, argc);
+
+ for (i=0; i<argc; i++) {
+ argv[i] = RARRAY_PTR(ary)[i];
}
}
- else if (iseq->argc > argc) {
- if (lambda) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
- argc, iseq->argc);
+
+ for (i=argc; i<m; i++) {
+ argv[i] = Qnil;
+ }
+
+ if (iseq->arg_rest == -1) {
+ if (m < argc) {
+ /*
+ * yield 1, 2
+ * => {|a|} # truncate
+ */
+ th->mark_stack_len = argc = m;
}
}
- }
- else {
- int r = iseq->arg_rest;
+ else {
+ int r = iseq->arg_rest;
- if (argc < r) {
- if (lambda) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
- argc, iseq->argc);
+ if (iseq->arg_post_len) {
+ int len = iseq->arg_post_len;
+ int start = iseq->arg_post_start;
+ int rsize = argc - m;
+ int psize = rsize;
+ VALUE ary;
+
+ if (rsize < 0) rsize = 0;
+ if (psize > len) psize = len;
+
+ ary = rb_ary_new4(rsize, &argv[r]);
+
+ if (0) {
+ printf(" argc: %d\n", argc);
+ printf(" len: %d\n", len);
+ printf("start: %d\n", start);
+ printf("rsize: %d\n", rsize);
+ }
+
+ /* copy post argument */
+ for (i=0; i<psize; i++) {
+ argv[start + psize - i - 1] = rb_ary_pop(ary);
+ }
+
+ for (; i<len; i++) {
+ argv[start + i] = Qnil;
+ }
+ argv[r] = ary;
}
else {
- for (i=argc; i<r; i++) {
- argv[i] = Qnil;
+ if (argc < r) {
+ /* yield 1
+ * => {|a, b, *r|}
+ */
+ for (i=argc; i<r; i++) {
+ argv[i] = Qnil;
+ }
+ argv[r] = rb_ary_new();
+ }
+ else {
+ argv[r] = rb_ary_new4(argc-r, &argv[r]);
}
- argv[r] = rb_ary_new();
}
+
+ th->mark_stack_len = iseq->arg_size;
}
- else {
- argv[r] = rb_ary_new4(argc-r, &argv[r]);
- }
- th->mark_stack_len = argc = iseq->arg_rest + 1;
- }
- if (iseq->arg_block != -1) {
- VALUE proc = Qnil;
+ /* {|&b|} */
+ if (iseq->arg_block != -1) {
+ VALUE proc = Qnil;
+
+ if (rb_block_given_p()) {
+ proc = rb_block_proc();
+ }
- if (rb_block_given_p()) {
- proc = rb_block_proc();
+ argv[iseq->arg_block] = proc;
+ th->mark_stack_len = iseq->arg_block + 1;
}
- argv[iseq->arg_block] = proc;
- th->mark_stack_len = argc = iseq->arg_block + 1;
+ th->mark_stack_len = 0;
+ return 0;
}
-
- th->mark_stack_len = 0;
- return argc;
}
/* cref */
diff --git a/insns.def b/insns.def
index 2fa8f1fae3..ea4afc39e9 100644
--- a/insns.def
+++ b/insns.def
@@ -1155,7 +1155,7 @@ send
NODE *mn;
VALUE recv, klass;
rb_block_t *blockptr = 0;
- rb_num_t num = caller_setup_args(th, GET_CFP(), op_flag, op_argc, blockiseq, &blockptr, 1);
+ rb_num_t num = caller_setup_args(th, GET_CFP(), op_flag, op_argc, blockiseq, &blockptr);
rb_num_t flag = op_flag;
ID id = op_id;
@@ -1216,7 +1216,7 @@ invokesuper
{
rb_block_t *blockptr = 0;
VALUE flag = op_flag;
- int num = caller_setup_args(th, GET_CFP(), flag, op_argc, blockiseq, &blockptr, 1);
+ int num = caller_setup_args(th, GET_CFP(), flag, op_argc, blockiseq, &blockptr);
rb_iseq_t *iseq = GET_ISEQ();
rb_iseq_t *ip = iseq;
VALUE recv, klass;
@@ -1292,18 +1292,21 @@ invokeblock
iseq = block->iseq;
if (BUILTIN_TYPE(iseq) != T_NODE) {
- argc = caller_setup_args(th, GET_CFP(), flag, argc, 0, 0, 0);
+ int opt_pc;
+
+ argc = caller_setup_args(th, GET_CFP(), flag, argc, 0, 0);
CHECK_STACK_OVERFLOW(GET_CFP(), iseq->stack_max);
DEC_SP(argc);
- argc = vm_yield_setup_args(th, iseq, argc, GET_SP(),
- block_proc_is_lambda(block->proc));
+ opt_pc = vm_yield_setup_args(th, iseq, argc, GET_SP(),
+ block_proc_is_lambda(block->proc));
+ argc = iseq->arg_size;
INC_SP(argc);
vm_push_frame(th, iseq,
FRAME_MAGIC_BLOCK, block->self, (VALUE) block->dfp,
- iseq->iseq_encoded, GET_SP(), block->lfp,
+ iseq->iseq_encoded + opt_pc, GET_SP(), block->lfp,
iseq->local_size - argc);
reg_cfp->sp -= argc;
diff --git a/parse.y b/parse.y
index bc60a39be8..be3a93d9f7 100644
--- a/parse.y
+++ b/parse.y
@@ -3091,9 +3091,7 @@ block_param : f_arg ',' f_rest_arg opt_f_block_arg
| f_arg ','
{
/*%%%*/
- ID id = internal_id();
- arg_var(id);
- $$ = new_args($1, 0, id, 0, 0);
+ $$ = new_args($1, 0, 1, 0, 0);
/*%
#if 0
TODO: check me (anonymous rest)
diff --git a/version.h b/version.h
index 6490eba3be..7a1ddf5f85 100644
--- a/version.h
+++ b/version.h
@@ -1,7 +1,7 @@
#define RUBY_VERSION "1.9.0"
-#define RUBY_RELEASE_DATE "2007-06-25"
+#define RUBY_RELEASE_DATE "2007-06-26"
#define RUBY_VERSION_CODE 190
-#define RUBY_RELEASE_CODE 20070625
+#define RUBY_RELEASE_CODE 20070626
#define RUBY_PATCHLEVEL 0
#define RUBY_VERSION_MAJOR 1
@@ -9,7 +9,7 @@
#define RUBY_VERSION_TEENY 0
#define RUBY_RELEASE_YEAR 2007
#define RUBY_RELEASE_MONTH 6
-#define RUBY_RELEASE_DAY 25
+#define RUBY_RELEASE_DAY 26
#ifdef RUBY_EXTERN
RUBY_EXTERN const char ruby_version[];
diff --git a/vm.c b/vm.c
index 59ca0ee6c6..6fe5cdcb8b 100644
--- a/vm.c
+++ b/vm.c
@@ -539,7 +539,7 @@ invoke_block(rb_thread_t *th, rb_block_t *block, VALUE self, int argc, VALUE *ar
VALUE val;
if (BUILTIN_TYPE(block->iseq) != T_NODE) {
rb_iseq_t *iseq = block->iseq;
- int i;
+ int i, opt_pc;
int magic = block_proc_is_lambda(block->proc) ?
FRAME_MAGIC_LAMBDA : FRAME_MAGIC_BLOCK;
@@ -552,12 +552,13 @@ invoke_block(rb_thread_t *th, rb_block_t *block, VALUE self, int argc, VALUE *ar
th->cfp->sp[i] = argv[i];
}
- argc = vm_yield_setup_args(th, iseq, argc, th->cfp->sp, magic == FRAME_MAGIC_LAMBDA);
+ opt_pc = vm_yield_setup_args(th, iseq, argc, th->cfp->sp, magic == FRAME_MAGIC_LAMBDA);
+ argc = iseq->arg_size;
th->cfp->sp += argc;
vm_push_frame(th, iseq, magic,
self, GC_GUARDED_PTR(block->dfp),
- iseq->iseq_encoded, th->cfp->sp, block->lfp,
+ iseq->iseq_encoded + opt_pc, th->cfp->sp, block->lfp,
iseq->local_size - argc);
val = vm_eval_body(th);
}