From ed4e57690c9cc782ab8675c4bf48153ce0a36896 Mon Sep 17 00:00:00 2001 From: ko1 Date: Mon, 25 Jun 2007 16:05:17 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12615 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 10 +++ compile.c | 25 ++++++-- insnhelper.ci | 172 +++++++++++++++++++++++++++++++------------------- insns.def | 15 +++-- parse.y | 4 +- version.h | 6 +- vm.c | 7 +- 7 files changed, 156 insertions(+), 83 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 + + * 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 * 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; iargc); + 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); + if (lambda) { + /* call as method */ + if (iseq->arg_block != -1) { + volatile VALUE procval = Qnil; - CHECK_STACK_OVERFLOW(th->cfp, argc); - - for (i=0; iarg_rest == -1) { - - 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; - } - } - else if (iseq->argc > argc) { - if (lambda) { - rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", - argc, iseq->argc); + 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 r = iseq->arg_rest; + int i; + const int m = iseq->argc; - if (argc < r) { - if (lambda) { - rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", - argc, iseq->argc); + th->mark_stack_len = 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; iarg_rest == -1) { + if (m < argc) { + /* + * yield 1, 2 + * => {|a|} # truncate + */ + th->mark_stack_len = argc = m; } } else { - argv[r] = rb_ary_new4(argc-r, &argv[r]); - } - th->mark_stack_len = argc = iseq->arg_rest + 1; - } + int r = iseq->arg_rest; - if (iseq->arg_block != -1) { - VALUE proc = Qnil; + 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 (rb_block_given_p()) { - proc = rb_block_proc(); + 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 {|a, b, *r|} + */ + for (i=argc; imark_stack_len = iseq->arg_size; } - argv[iseq->arg_block] = proc; - th->mark_stack_len = argc = iseq->arg_block + 1; - } + /* {|&b|} */ + if (iseq->arg_block != -1) { + VALUE proc = Qnil; - th->mark_stack_len = 0; - return argc; + if (rb_block_given_p()) { + proc = rb_block_proc(); + } + + argv[iseq->arg_block] = proc; + th->mark_stack_len = iseq->arg_block + 1; + } + + th->mark_stack_len = 0; + return 0; + } } /* 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); }