From 0fe72040e4c278bfafe232dc44551de2dfac85e2 Mon Sep 17 00:00:00 2001 From: ko1 Date: Sat, 24 Feb 2007 02:07:05 +0000 Subject: [PATCH] * parse.y, node.h, compile.c: change node tree structure. a purpose of this change is to unify argument structure of method and block. this change prohibits duplicate block parameter name. 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*] optarg information: NODE_OPT_ARGS [idx, expr, ->] * vm_macro.def: ditto. * gc.c: ditto. * iseq.c: ditto. * compile.h: fix debug function name. * test/ripper/test_scanner_events.rb: |_,_,foo| -> |_1,_2,foo| * test/ruby/test_lambda.rb: disalbe test temporarily. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11840 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 24 +++++ compile.c | 115 +++++++++++++++++++++-- compile.h | 18 ++-- gc.c | 4 +- iseq.c | 11 ++- node.h | 14 ++- parse.y | 141 ++++++++++------------------- test/ripper/test_scanner_events.rb | 2 +- test/ruby/test_lambda.rb | 2 + vm_macro.def | 81 ++++++++--------- 10 files changed, 251 insertions(+), 161 deletions(-) diff --git a/ChangeLog b/ChangeLog index f58fd7af76..92fa655fc7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +Sat Feb 24 10:49:55 2007 Koichi Sasada + + * parse.y, node.h, compile.c: change node tree structure. a purpose + of this change is to unify argument structure of method and block. + this change prohibits duplicate block parameter name. + 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*] + optarg information: + NODE_OPT_ARGS [idx, expr, ->] + + * vm_macro.def: ditto. + + * gc.c: ditto. + + * iseq.c: ditto. + + * compile.h: fix debug function name. + + * test/ripper/test_scanner_events.rb: |_,_,foo| -> |_1,_2,foo| + + * test/ruby/test_lambda.rb: disalbe test temporarily. + Sat Feb 24 10:46:28 2007 Koichi Sasada * test/testunit/test_testcase.rb: catch up with current instance diff --git a/compile.c b/compile.c index ffc9510691..d498f4a3e2 100644 --- a/compile.c +++ b/compile.c @@ -147,7 +147,6 @@ iseq_compile(VALUE self, NODE *narg) debugs("[compile step 1 (traverse each node)]\n"); - iseq->node = node; if (iseq->type == ISEQ_TYPE_BLOCK) { @@ -1035,7 +1034,7 @@ set_block_local_tbl(rb_iseq_t *iseq, NODE * node, LINK_ANCHOR *anchor) } } - if (iseq->arg_opts || iseq->arg_rest) { + if (iseq->arg_opts || iseq->arg_rest || iseq->arg_block) { iseq->arg_simple = 0; } else { @@ -1077,9 +1076,96 @@ get_dyna_var_idx(rb_iseq_t *iseq, ID id, int *level, int *ls) return -1; } -/** +#if 1 + +static int +set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_arg) +{ + NODE *node_aux = node_arg->nd_next; + int mandatory_len = 0; + NODE *node_opt = 0; + ID rest_id = 0; + ID block_id = 0; + ID post_start_id = 0; + int post_len = 0; + NODE *node_init = 0; + + iseq->argc = node_arg->nd_frml; + node_opt = node_arg->nd_opt; + + if (node_aux) { + rest_id = node_aux->nd_rest; + block_id = (ID)node_aux->nd_body; + node_aux = node_aux->nd_next; + + if (node_aux) { + post_start_id = node_aux->nd_pid; + post_len = node_aux->nd_plen; + node_init = node_aux->nd_next; + } + } + + if (node_init) { + COMPILE(optargs, "arguments", node_init); + } + + if (node_opt) { + NODE *node = node_opt; + LABEL *label; + VALUE labels = rb_ary_new(); + int i = 0, j; + + while (node) { + label = NEW_LABEL(nd_line(node)); + rb_ary_push(labels, (VALUE)label | 1); + ADD_LABEL(optargs, label); + COMPILE_POPED(optargs, "optarg", node->nd_body); + + node = node->nd_next; + i += 1; + } + /* last label */ + label = NEW_LABEL(nd_line(node_arg)); + rb_ary_push(labels, (VALUE)label | 1); + ADD_LABEL(optargs, label); + i += 1; + + iseq->arg_opts = i; + iseq->arg_opt_tbl = ALLOC_N(VALUE, i); + MEMCPY(iseq->arg_opt_tbl, RARRAY_PTR(labels), VALUE, i); + for (j = 0; j < i; j++) { + iseq->arg_opt_tbl[j] &= ~1; + } + } + else { + iseq->arg_opts = 0; + } + + if ((long)rest_id == -1) { + iseq->arg_rest = get_dyna_var_idx_at_raw(iseq, 0 /* dummy var */); + } + else if (rest_id) { + iseq->arg_rest = get_dyna_var_idx_at_raw(iseq, rest_id); + } + if (iseq->arg_rest == -1) rb_bug("arg_rest: -1"); + + + if (block_id) { + iseq->arg_block = get_dyna_var_idx_at_raw(iseq, block_id); + } + + if (iseq->arg_rest != 0 || iseq->arg_opts != 0 || iseq->arg_block != 0) { + iseq->arg_simple = 0; + } + else { + iseq->arg_simple = 1; + } + + return COMPILE_OK; +} + +#else - */ static int set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE * node) { @@ -1121,7 +1207,9 @@ set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE * node) iseq->arg_opts = i; iseq->arg_opt_tbl = ALLOC_N(VALUE, i); + MEMCPY(iseq->arg_opt_tbl, RARRAY_PTR(labels), VALUE, i); + for (j = 0; j < i; j++) { iseq->arg_opt_tbl[j] &= ~1; } @@ -1144,6 +1232,7 @@ set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE * node) } return COMPILE_OK; } +#endif static int set_localtbl(rb_iseq_t *iseq, ID *tbl) @@ -3681,6 +3770,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) int idx = liseq->local_size - i; ADD_INSN1(args, nd_line(node), getlocal, INT2FIX(idx)); } + if (!liseq->arg_simple) { if (liseq->arg_opts) { /* optional arguments */ @@ -3693,13 +3783,20 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) i += j; argc = INT2FIX(i); } + if (liseq->arg_rest) { /* rest arguments */ - int idx = liseq->local_size - liseq->arg_rest + 1; - ADD_INSN1(args, nd_line(node), getlocal, - INT2FIX(idx)); - argc = INT2FIX(liseq->arg_rest); - flag |= VM_CALL_ARGS_SPLAT_BIT; + + if (liseq->arg_rest == -1) { + /* TODO */ + } + else { + int idx = liseq->local_size - liseq->arg_rest + 1; + ADD_INSN1(args, nd_line(node), getlocal, + INT2FIX(idx)); + argc = INT2FIX(liseq->arg_rest); + flag |= VM_CALL_ARGS_SPLAT_BIT; + } } } } diff --git a/compile.h b/compile.h index 9d4ba5baf6..f1e7bfa86a 100644 --- a/compile.h +++ b/compile.h @@ -41,27 +41,27 @@ #if CPDEBUG > 0 #define debugp(header, value) \ - (debug_indent(0, CPDEBUG, gl_node_level * 2), \ + (ruby_debug_indent(0, CPDEBUG, gl_node_level * 2), \ ruby_debug_value(0, CPDEBUG, header, value)) #define debugi(header, id) \ - (debug_indent(0, CPDEBUG, gl_node_level * 2), \ - debug_id(0, CPDEBUG, header, id)) + (ruby_debug_indent(0, CPDEBUG, gl_node_level * 2), \ + ruby_debug_id(0, CPDEBUG, header, id)) #define debugp_param(header, value) \ - (debug_indent(1, CPDEBUG, gl_node_level * 2), \ + (ruby_debug_indent(1, CPDEBUG, gl_node_level * 2), \ ruby_debug_value(1, CPDEBUG, header, value)) #define debugp_verbose(header, value) \ - (debug_indent(2, CPDEBUG, gl_node_level * 2), \ + (ruby_debug_indent(2, CPDEBUG, gl_node_level * 2), \ ruby_debug_value(2, CPDEBUG, header, value)) #define debugp_verbose_node(header, value) \ - (debug_indent(10, CPDEBUG, gl_node_level * 2), \ + (ruby_debug_indent(10, CPDEBUG, gl_node_level * 2), \ ruby_debug_value(10, CPDEBUG, header, value)) #define debug_nodeprint(node) \ - debug_indent(-1, CPDEBUG, gl_node_level*2); \ + ruby_debug_indent(-1, CPDEBUG, gl_node_level*2); \ printf("node: %s (%d)\n", ruby_node_name(nd_type(node)), nd_line(node)); \ gl_node_level ++; @@ -91,8 +91,8 @@ r_value(VALUE value) #endif #if CPDEBUG > 1 -#define debugs debug_indent(-1, CPDEBUG, gl_node_level*2), printf -#define debug_compile(msg, v) (debug_indent(-1, CPDEBUG, gl_node_level*2), printf("%s", msg), (v)) +#define debugs ruby_debug_indent(-1, CPDEBUG, gl_node_level*2), printf +#define debug_compile(msg, v) (ruby_debug_indent(-1, CPDEBUG, gl_node_level*2), printf("%s", msg), (v)) #else #define debugs if(0)printf #define debug_compile(msg, v) (v) diff --git a/gc.c b/gc.c index bbf3694ff9..987a5f842e 100644 --- a/gc.c +++ b/gc.c @@ -844,7 +844,6 @@ gc_mark_children(VALUE ptr, int lev) case NODE_RESCUE: case NODE_RESBODY: case NODE_CLASS: - case NODE_ARGS: case NODE_BLOCK_PASS: gc_mark((VALUE)obj->as.node.u2.node, lev); /* fall through */ @@ -859,11 +858,13 @@ gc_mark_children(VALUE ptr, int lev) case NODE_CALL: case NODE_DEFS: case NODE_OP_ASGN1: + case NODE_ARGS: gc_mark((VALUE)obj->as.node.u1.node, lev); /* fall through */ case NODE_SUPER: /* 3 */ case NODE_FCALL: case NODE_DEFN: + case NODE_ARGS_AUX: ptr = (VALUE)obj->as.node.u3.node; goto again; @@ -922,6 +923,7 @@ gc_mark_children(VALUE ptr, int lev) case NODE_SCOPE: /* 2,3 */ case NODE_CDECL: + case NODE_OPT_ARG: gc_mark((VALUE)obj->as.node.u3.node, lev); ptr = (VALUE)obj->as.node.u2.node; goto again; diff --git a/iseq.c b/iseq.c index 1680aa4aa5..1fc0cff963 100644 --- a/iseq.c +++ b/iseq.c @@ -542,10 +542,15 @@ insn_operand_intern(rb_iseq_t *iseq, case TS_LINDEX: { rb_iseq_t *ip = iseq->local_iseq; + int lidx = ip->local_size - op + 1; + ID id = ip->local_tbl[lidx]; - ret = - rb_str_new2( - rb_id2name(ip->local_tbl[ip->local_size - op + 1])); + if (id) { + ret = rb_str_new2(rb_id2name(id)); + } + else { + ret = rb_str_new2("*"); + } break; } case TS_DINDEX:{ diff --git a/node.h b/node.h index cf051c096b..c21158f9da 100644 --- a/node.h +++ b/node.h @@ -87,6 +87,8 @@ enum node_type { NODE_DREGX, NODE_DREGX_ONCE, NODE_ARGS, + NODE_ARGS_AUX, + NODE_OPT_ARG, NODE_POSTARG, NODE_ARGSCAT, NODE_ARGSPUSH, @@ -209,9 +211,11 @@ typedef struct RNode { #define nd_lit u1.value -#define nd_frml u3.value -#define nd_rest u2.node +#define nd_frml u2.argc +#define nd_rest u1.id #define nd_opt u1.node +#define nd_pid u1.id +#define nd_plen u2.argc #define nd_recv u1.node #define nd_mid u2.id @@ -315,8 +319,10 @@ typedef struct RNode { #define NEW_VCALL(m) NEW_NODE(NODE_VCALL,0,m,0) #define NEW_SUPER(a) NEW_NODE(NODE_SUPER,0,0,a) #define NEW_ZSUPER() NEW_NODE(NODE_ZSUPER,0,0,0) -#define NEW_ARGS(f,o,r) NEW_NODE(NODE_ARGS,o,r,f) -#define NEW_POSTARG(r,m) NEW_NODE(NODE_POSTARG,m,0,r) +#define NEW_ARGS(m,o) NEW_NODE(NODE_ARGS,o,m,0) +#define NEW_ARGS_AUX(r,b) NEW_NODE(NODE_ARGS_AUX,r,b,0) +#define NEW_OPT_ARG(i,v) NEW_NODE(NODE_OPT_ARG,i,v,0) +#define NEW_POSTARG(i,v) NEW_NODE(NODE_POSTARG,i,v,0) #define NEW_ARGSCAT(a,b) NEW_NODE(NODE_ARGSCAT,a,b,0) #define NEW_ARGSPUSH(a,b) NEW_NODE(NODE_ARGSPUSH,a,b,0) #define NEW_SPLAT(a) NEW_NODE(NODE_SPLAT,a,0,0) diff --git a/parse.y b/parse.y index e4958888f2..dfba404da5 100644 --- a/parse.y +++ b/parse.y @@ -346,7 +346,7 @@ static NODE *evstr2dstr(NODE*); static NODE *call_op_gen(struct parser_params*,NODE*,ID,int,NODE*); #define call_op(recv,id,narg,arg1) call_op_gen(parser, recv,id,narg,arg1) -static NODE *new_args_gen(struct parser_params*,VALUE,NODE*,NODE*,NODE*,NODE*); +static NODE *new_args_gen(struct parser_params*,int,NODE*,ID,NODE*,ID); #define new_args(f,o,r,p,b) new_args_gen(parser, f,o,r,p,b) static void shadowing_lvar_gen(struct parser_params*,ID); #define shadowing_lvar(name) shadowing_lvar_gen(parser, name) @@ -617,15 +617,15 @@ static void ripper_compile_error(struct parser_params*, const char *fmt, ...); %type open_args paren_args opt_paren_args %type command_args aref_args opt_block_arg block_arg var_ref var_lhs %type mrhs superclass block_call block_command -%type f_arglist f_args f_rest_arg f_post_arg -%type f_optarg f_opt f_block_arg opt_f_block_arg +%type f_arglist f_args f_post_arg +%type f_optarg f_opt %type assoc_list assocs assoc undef_list backref string_dvar for_var %type block_param opt_block_param block_param_def bparam_list bparam_item %type opt_bv_decl bv_decls bvar lambda f_larglist lambda_body %type brace_block cmd_brace_block do_block lhs none fitem %type mlhs mlhs_head mlhs_basic mlhs_item mlhs_node mlhs_post %type fsym variable sym symbol operation operation2 operation3 -%type cname fname op f_norm_arg +%type cname fname op f_norm_arg f_rest_arg f_block_arg opt_f_block_arg %type f_arg /*%%%*/ /*% @@ -4151,13 +4151,7 @@ f_norm_arg : tCONSTANT /*%%%*/ if (!is_local_id($1)) yyerror("formal argument must be local variable"); - if (dyna_in_block()) { - shadowing_lvar($1); - dyna_var($1); - } - else { - local_cnt($1); - } + shadowing_lvar($1); $$ = $1; /*% $$ = $1; @@ -4167,32 +4161,18 @@ f_norm_arg : tCONSTANT f_arg : f_norm_arg { - /*%%%*/ - VALUE arg = ID2SYM($1); - /*% - VALUE arg = $1; - %*/ - $$ = rb_ary_new3(1, arg); + $$ = 1; } | f_arg ',' f_norm_arg { - /*%%%*/ - VALUE arg = ID2SYM($3); - $$ = $1; - if (rb_ary_includes($$, arg)) { - yyerror("duplicated argument name"); - } - rb_ary_push($$, arg); - /*% - rb_ary_push($$, $3); - %*/ + $$ = $1 + 1; } ; f_post_arg : f_norm_arg { /*%%%*/ - $$ = NEW_LIST(assignable($1, 0)); + $$ = NEW_ARGS_AUX($1, 1); /*% $$ = mlhs_add(mlhs_new(), $1); %*/ @@ -4200,7 +4180,8 @@ f_post_arg : f_norm_arg | f_post_arg ',' f_norm_arg { /*%%%*/ - $$ = list_append($1, assignable($3, 0)); + $1->nd_alen++; + $$ = $1; /*% $$ = mlhs_add($1, $3); %*/ @@ -4212,11 +4193,8 @@ f_opt : tIDENTIFIER '=' arg_value /*%%%*/ if (!is_local_id($1)) yyerror("formal argument must be local variable"); - if (dyna_in_block()) { - shadowing_lvar($1); - dyna_var($1); - } - $$ = assignable($1, $3); + shadowing_lvar($1); + $$ = NEW_OPT_ARG(0, assignable($1, $3)); /*% $$ = rb_assoc_new($1, $3); %*/ @@ -4226,8 +4204,7 @@ f_opt : tIDENTIFIER '=' arg_value f_optarg : f_opt { /*%%%*/ - $$ = NEW_BLOCK($1); - $$->nd_end = $$; + $$ = $1; /*% $$ = rb_ary_new3(1, $1); %*/ @@ -4235,7 +4212,13 @@ f_optarg : f_opt | f_optarg ',' f_opt { /*%%%*/ - $$ = block_append($1, $3); + NODE *opts = $1; + + while (opts->nd_next) { + opts = opts->nd_next; + } + opts->nd_next = $3; + $$ = $1; /*% $$ = rb_ary_push($1, $3); %*/ @@ -4251,11 +4234,8 @@ f_rest_arg : restarg_mark tIDENTIFIER /*%%%*/ if (!is_local_id($2)) yyerror("rest argument must be local variable"); - if (dyna_in_block()) { - shadowing_lvar($2); - dyna_var($2); - } - $$ = assignable($2, 0); + shadowing_lvar($2); + $$ = $2; /*% $$ = dispatch1(restparam, $2); %*/ @@ -4264,10 +4244,11 @@ f_rest_arg : restarg_mark tIDENTIFIER { /*%%%*/ if (dyna_in_block()) { - $$ = NEW_DASGN_CURR(internal_id(), 0); + $$ = internal_id(); } else { - $$ = NEW_NODE(NODE_LASGN,0,0,local_append(0)); + local_append(0); + $$ = -1; } /*% $$ = dispatch1(restparam, Qnil); @@ -4286,14 +4267,8 @@ f_block_arg : blkarg_mark tIDENTIFIER yyerror("block argument must be local variable"); else if (!dyna_in_block() && local_id($2)) yyerror("duplicated block argument name"); - if (dyna_in_block()) { - shadowing_lvar($2); - dyna_var($2); - $$ = assignable($2, 0); - } - else { - $$ = NEW_BLOCK_ARG($2); - } + shadowing_lvar($2); + $$ = $2; /*% $$ = $2; %*/ @@ -4305,6 +4280,9 @@ opt_f_block_arg : ',' f_block_arg $$ = $2; } | none + { + $$ = 0 ; + } ; singleton : var_ref @@ -7314,9 +7292,21 @@ assignable_gen(struct parser_params *parser, ID id, NODE *val) static void shadowing_lvar_gen(struct parser_params *parser, ID name) { - if (dvar_defined(name) || local_id(name)) { - rb_warningS("shadowing outer local variable - %s", rb_id2name(name)); - } + if (dyna_in_block()) { + if (dvar_curr(name)) { + yyerror("duplicated argument name"); + } + else if (dvar_defined(name) || local_id(name)) { + rb_warningS("shadowing outer local variable - %s", rb_id2name(name)); + } + dyna_var(name); + } + else { + if (local_id(name)) { + yyerror("duplicated argument name"); + } + local_cnt(name); + } } static NODE* @@ -7966,47 +7956,14 @@ arg_dup_check(ID vid, VALUE m, VALUE list, NODE *node) } static NODE* -new_args_gen(struct parser_params *parser, VALUE m, NODE *o, NODE *r, NODE *p, NODE *b) +new_args_gen(struct parser_params *parser, int m, NODE *o, ID r, NODE *p, ID b) { int saved_line = ruby_sourceline; - NODE *node; - VALUE list; + NODE *node = NEW_ARGS(m, o); - list = rb_ary_new(); - node = o; - while (node) { - if (!node->nd_head) break; - if (arg_dup_check(node->nd_head->nd_vid, m, list, node)) { - yyerror("duplicated optional argument name"); - return 0; - } - node = node->nd_next; - } - if (RTEST(r)) { - if (arg_dup_check(r->nd_vid, m, list, r)) { - yyerror("duplicated rest argument name"); - return 0; - } - } + node->nd_next = NEW_ARGS_AUX(r, b); if (p) { - node = p; - while (node) { - if (!node->nd_head) break; - if (arg_dup_check(node->nd_head->nd_vid, m, list, node)) { - yyerror("duplicated argument name"); - return 0; - } - node = node->nd_next; - } - r = NEW_POSTARG(r, p); - } - node = NEW_ARGS(m, o, r); - if (b) { - if (arg_dup_check(b->nd_vid, m, list, b)) { - yyerror("duplicated block argument name"); - return 0; - } - node = block_append(node, b); + node->nd_next->nd_next = p; } ruby_sourceline = saved_line; return node; diff --git a/test/ripper/test_scanner_events.rb b/test/ripper/test_scanner_events.rb index 644f9edb29..4389946104 100644 --- a/test/ripper/test_scanner_events.rb +++ b/test/ripper/test_scanner_events.rb @@ -17,7 +17,7 @@ class TestRipper_ScannerEvents < Test::Unit::TestCase def scan(target, str) sym = "on_#{target}".intern - Ripper.lex(str).select {|_,type,_| type == sym }.map {|_,_,tok| tok } + Ripper.lex(str).select {|_1,type,_2| type == sym }.map {|_1,_2,tok| tok } end def test_tokenize diff --git a/test/ruby/test_lambda.rb b/test/ruby/test_lambda.rb index b4f0dac658..6105f5d122 100644 --- a/test/ruby/test_lambda.rb +++ b/test/ruby/test_lambda.rb @@ -1,5 +1,7 @@ require 'test/unit' +__END__ + class TestLambdaParameters < Test::Unit::TestCase def test_call_simple assert_equal(1, ->(a){ a }.call(1)) diff --git a/vm_macro.def b/vm_macro.def index 28f0ed7e4d..3d6c66402c 100644 --- a/vm_macro.def +++ b/vm_macro.def @@ -86,7 +86,8 @@ MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num) GetISeqPtr(niseqval, niseq); clear_local_size = niseq->local_size - num; - /* set arguments */ + + /* simple (only mandatory) arguments */ if (niseq->arg_simple) { if (niseq->argc != num) { rb_raise(rb_eArgError, "wrong number of arguments (%lu for %d)", @@ -94,7 +95,7 @@ MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num) } } else { - /* check optional arguments */ + /* optional arguments */ if (niseq->arg_opts) { int iseq_argc = niseq->argc; int opts = niseq->arg_opts - 1; @@ -110,10 +111,9 @@ MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num) (unsigned long)num, iseq_argc); } - if (0) { - printf("num: %lu, opts: %d, iseq_argc: %d\n", - (unsigned long)num, opts, iseq_argc); - } + if (0) printf("num: %lu, opts: %d, iseq_argc: %d\n", + (unsigned long)num, opts, iseq_argc); + if (num - iseq_argc < opts) { opt_pc = niseq->arg_opt_tbl[num - iseq_argc]; sp += opts - (num - iseq_argc); @@ -124,23 +124,17 @@ MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num) opt_pc = niseq->arg_opt_tbl[opts]; } } - /* check rest */ - if (niseq->arg_rest == -1) { - if (niseq->arg_opts) { - num = niseq->argc + niseq->arg_opts; - } - else { - num = niseq->argc; - } - sp = &rsp[1 + num + 1]; - } - else if (niseq->arg_rest != 0) { + + /* rest argument */ + if (niseq->arg_rest != 0) { int rest = niseq->arg_rest - 1; int pack_size = num - rest; + if (0) { printf("num: %lu, rest: %d, ps: %d\n", (unsigned long)num, niseq->arg_rest, pack_size); } + if (pack_size < 0) { rb_raise(rb_eArgError, "wrong number of arguments (%lu for %d)", @@ -165,6 +159,10 @@ MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num) (niseq->arg_opts && num == niseq->argc + niseq->arg_opts - 1) || num == niseq->argc)) { + + if (0) printf("num: %d, rest: %d, opts: %d, argc: %d\n", + num, niseq->arg_rest, niseq->arg_opts, niseq->argc); + rb_raise(rb_eArgError, "wrong number of arguments (%lu for %d)", (unsigned long)num, niseq->argc); @@ -189,6 +187,7 @@ MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num) clear_local_size--; } } + /* stack overflow check */ if (CHECK_STACK_OVERFLOW(th, GET_CFP(), niseq->stack_max + 0x100)) { rb_exc_raise(sysstack_error); @@ -198,32 +197,30 @@ MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num) *sp++ = Qnil; } - { - if (0 && (flag & VM_CALL_TAILCALL_BIT)) { - th->cfp++; - push_frame(th, niseq, FRAME_MAGIC_METHOD, - recv, (VALUE) blockptr, - niseq->iseq_encoded + opt_pc, sp, 0, 0); - } - else if (0 && - (flag & VM_CALL_TAILRECURSION_BIT) && niseq == GET_ISEQ()) { - /* do nothing */ - GET_CFP()->self = recv; - SET_LFP(sp); - SET_DFP(sp); - *sp++ = (VALUE) blockptr; - reg_cfp->sp = sp; - reg_cfp->bp = sp; - SET_PC(niseq->iseq_encoded + opt_pc); - } - else { - push_frame(th, niseq, - FRAME_MAGIC_METHOD, recv, (VALUE) blockptr, - niseq->iseq_encoded + opt_pc, sp, 0, 0); - reg_cfp->sp = rsp; - } - RESTORE_REGS(); + if (0 && (flag & VM_CALL_TAILCALL_BIT)) { + th->cfp++; + push_frame(th, niseq, FRAME_MAGIC_METHOD, + recv, (VALUE) blockptr, + niseq->iseq_encoded + opt_pc, sp, 0, 0); } + else if (0 && + (flag & VM_CALL_TAILRECURSION_BIT) && niseq == GET_ISEQ()) { + /* do nothing */ + GET_CFP()->self = recv; + SET_LFP(sp); + SET_DFP(sp); + *sp++ = (VALUE) blockptr; + reg_cfp->sp = sp; + reg_cfp->bp = sp; + SET_PC(niseq->iseq_encoded + opt_pc); + } + else { + push_frame(th, niseq, + FRAME_MAGIC_METHOD, recv, (VALUE) blockptr, + niseq->iseq_encoded + opt_pc, sp, 0, 0); + reg_cfp->sp = rsp; + } + RESTORE_REGS(); } MACRO macro_eval_invoke_method(recv, klass, id, num, mn, blockptr)