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:
parent
588e79f768
commit
ed4e57690c
7 changed files with 156 additions and 83 deletions
10
ChangeLog
10
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.
|
||||
|
|
25
compile.c
25
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;
|
||||
}
|
||||
|
||||
|
|
172
insnhelper.ci
172
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);
|
||||
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 */
|
||||
|
|
15
insns.def
15
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;
|
||||
|
|
4
parse.y
4
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)
|
||||
|
|
|
@ -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
7
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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue