1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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
This commit is contained in:
ko1 2007-06-25 16:05:17 +00:00
parent 588e79f768
commit ed4e57690c
7 changed files with 156 additions and 83 deletions

View file

@ -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.

View file

@ -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;
}

View file

@ -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);
if (lambda) {
/* call as method */
if (iseq->arg_block != -1) {
volatile VALUE procval = Qnil;
CHECK_STACK_OVERFLOW(th->cfp, argc);
for (i=0; i<argc; i++) {
argv[i] = RARRAY_PTR(ary)[i];
}
}
if (iseq->arg_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; i<argc; i++) {
argv[i] = RARRAY_PTR(ary)[i];
}
else {
for (i=argc; i<r; i++) {
argv[i] = Qnil;
}
argv[r] = rb_ary_new();
}
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 {
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<psize; i++) {
argv[start + psize - i - 1] = rb_ary_pop(ary);
}
for (; i<len; i++) {
argv[start + i] = Qnil;
}
argv[r] = ary;
}
else {
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]);
}
}
th->mark_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 */

View file

@ -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;

View file

@ -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)

View file

@ -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[];

7
vm.c
View file

@ -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);
}