summaryrefslogtreecommitdiff
path: root/insnhelper.ci
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-06-25 16:05:17 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-06-25 16:05:17 +0000
commited4e57690c9cc782ab8675c4bf48153ce0a36896 (patch)
tree5cdf90849da2ef0e17458f17b2d8358929c7a7d2 /insnhelper.ci
parent588e79f7688c9b7f085cb8d46b9289e4769f4135 (diff)
* 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
Diffstat (limited to 'insnhelper.ci')
-rw-r--r--insnhelper.ci164
1 files changed, 104 insertions, 60 deletions
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 */