 ChangeLog |   26 ++++
 eval.c    |    5 +-
 parse.y   |  433 +++++++++++++++++++++++++++++++++++++++++++++----------------
 3 files changed, 350 insertions(+), 114 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 40005b6..ae7ae84 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Fri Aug 21 00:39:17 2009  URABE Shyouhei  <shyouhei@ruby-lang.org>
+
+	* parse.y (opt_call_args): fix to pass "make test-all".
+
+	* parse.y (arg_value): fix to pass "make test".
+
 Fri Aug 14 19:57:28 2009  Nobuyoshi Nakada  <nobu@ruby-lang.org>
 
 	* ext/curses/curses.c ({curses,window}_addstr),
@@ -124,6 +130,26 @@ Sun Aug  2 06:08:17 2009  URABE Shyouhei  <shyouhei@ruby-lang.org>
 
 	* parse.y (string_type): ditto.
 
+Sun Aug  2 11:58:22 2009  URABE Shyouhei  <shyouhei@ruby-lang.org>
+
+	* parse.y: looser splatting in arguments.
+
+Sun Aug  2 06:51:41 2009  URABE Shyouhei  <shyouhei@ruby-lang.org>
+
+	* parse.y (when_args): no longer needed.
+
+Sun Aug  2 05:06:12 2009  URABE Shyouhei  <shyouhei@ruby-lang.org>
+
+	* parse.y (mlhs_basic): looser splatting in multi-assignment.
+
+Sun Aug  2 04:54:01 2009  URABE Shyouhei  <shyouhei@ruby-lang.org>
+
+	* parse.y (f_args): looser formal optional / rest argumets.
+
+	* parse.y (new_args): raise syntax error for unsupported synax.
+
+	* eval.c (rb_call0): ditto.
+
 Sat Aug  1 07:51:32 2009  URABE Shyouhei  <shyouhei@ruby-lang.org>
 
 	* lex.c: update.
diff --git a/eval.c b/eval.c
index 9aaf969..1423a4c 100644
--- a/eval.c
+++ b/eval.c
@@ -6084,7 +6084,10 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
 		    body = body->nd_next;
 		}
 		if (node) {
-		    if (nd_type(node) != NODE_ARGS) {
+                    if (nd_type(node) == NODE_FCALL) {
+                        eval_node(recv, node);
+                    }
+		    else if (nd_type(node) != NODE_ARGS) {
 			rb_bug("no argument-node");
 		    }
 
diff --git a/parse.y b/parse.y
index 4180ae1..23f2b0f 100644
--- a/parse.y
+++ b/parse.y
@@ -126,6 +126,9 @@ static ID cur_mid = 0;
 static int command_start = Qtrue;
 
 static NODE *deferred_nodes;
+static NODE *NEW_POSTARG();
+
+static NODE *new_args();
 
 static NODE *cond();
 static NODE *logop();
@@ -144,11 +147,13 @@ static NODE *remove_begin();
 static NODE *block_append();
 static NODE *list_append();
 static NODE *list_concat();
+static NODE *arg_append();
 static NODE *arg_concat();
 static NODE *arg_prepend();
 static NODE *literal_concat();
 static NODE *new_evstr();
 static NODE *evstr2dstr();
+static NODE *splat_array();
 static NODE *call_op();
 static int in_defined = 0;
 
@@ -280,14 +285,15 @@ static void fixup_nodes();
 %type <node> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
 %type <node> expr_value arg_value primary_value
 %type <node> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
-%type <node> args when_args call_args call_args2 open_args paren_args opt_paren_args
+%type <node> args args2 call_args call_args2 opt_call_args
+%type <node> open_args paren_args opt_paren_args
 %type <node> command_args aref_args opt_block_arg block_arg var_ref var_lhs
 %type <node> mrhs superclass block_call block_command
 %type <node> f_arglist f_args f_optarg f_opt f_rest_arg f_block_arg opt_f_block_arg
 %type <node> assoc_list assocs assoc undef_list backref string_dvar
 %type <node> for_var block_var opt_block_var block_par
 %type <node> brace_block cmd_brace_block do_block lhs none fitem
-%type <node> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node
+%type <node> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node mlhs_post
 %type <id>   fsym variable sym symbol operation operation2 operation3
 %type <id>   cname fname op
 %type <num>  f_norm_arg f_arg
@@ -547,12 +553,11 @@ stmt		: kALIAS fitem {lex_state = EXPR_FNAME;} fitem
 			    $$ = 0;
 			}
 		    }
-		| primary_value '[' aref_args ']' tOP_ASGN command_call
+		| primary_value '[' opt_call_args ']' tOP_ASGN command_call
 		    {
-                        NODE *args;
+			NODE *args = $3;
 
 			value_expr($6);
-			if (!$3) $3 = NEW_ZARRAY();
 			args = arg_concat($6, $3);
 			if ($5 == tOROP) {
 			    $5 = 0;
@@ -769,27 +774,83 @@ mlhs_entry	: mlhs_basic
 
 mlhs_basic	: mlhs_head
 		    {
+		    /*%%%*/
 			$$ = NEW_MASGN($1, 0);
+		    /*%
+			$$ = $1;
+		    %*/
 		    }
 		| mlhs_head mlhs_item
 		    {
+		    /*%%%*/
 			$$ = NEW_MASGN(list_append($1,$2), 0);
+		    /*%
+			$$ = mlhs_add($1, $2);
+		    %*/
 		    }
 		| mlhs_head tSTAR mlhs_node
 		    {
+		    /*%%%*/
 			$$ = NEW_MASGN($1, $3);
+		    /*%
+			$$ = mlhs_add_star($1, $3);
+		    %*/
+		    }
+		| mlhs_head tSTAR mlhs_node ',' mlhs_post
+		    {
+		    /*%%%*/
+			$$ = NEW_MASGN($1, NEW_POSTARG($3,$5));
+		    /*%
+			$$ = mlhs_add_star($1, $3);
+		    %*/
 		    }
 		| mlhs_head tSTAR
 		    {
+		    /*%%%*/
 			$$ = NEW_MASGN($1, -1);
+		    /*%
+			$$ = mlhs_add_star($1, Qnil);
+		    %*/
+		    }
+		| mlhs_head tSTAR ',' mlhs_post
+		    {
+		    /*%%%*/
+			$$ = NEW_MASGN($1, NEW_POSTARG(-1, $4));
+		    /*%
+			$$ = mlhs_add_star($1, Qnil);
+		    %*/
 		    }
 		| tSTAR mlhs_node
 		    {
+		    /*%%%*/
 			$$ = NEW_MASGN(0, $2);
+		    /*%
+			$$ = mlhs_add_star(mlhs_new(), $2);
+		    %*/
+		    }
+		| tSTAR mlhs_node ',' mlhs_post
+		    {
+		    /*%%%*/
+			$$ = NEW_MASGN(0, NEW_POSTARG($2,$4));
+		    /*%
+			$$ = mlhs_add_star(mlhs_new(), $2);
+		    %*/
 		    }
 		| tSTAR
 		    {
+		    /*%%%*/
 			$$ = NEW_MASGN(0, -1);
+		    /*%
+			$$ = mlhs_add_star(mlhs_new(), Qnil);
+		    %*/
+		    }
+		| tSTAR ',' mlhs_post
+		    {
+		    /*%%%*/
+			$$ = NEW_MASGN(0, NEW_POSTARG(-1, $3));
+		    /*%
+			$$ = mlhs_add_star(mlhs_new(), Qnil);
+		    %*/
 		    }
 		;
 
@@ -810,11 +871,29 @@ mlhs_head	: mlhs_item ','
 		    }
 		;
 
+mlhs_post	: mlhs_item
+		    {
+		    /*%%%*/
+			$$ = NEW_LIST($1);
+		    /*%
+			$$ = mlhs_add(mlhs_new(), $1);
+		    %*/
+		    }
+		| mlhs_post ',' mlhs_item
+		    {
+		    /*%%%*/
+			$$ = list_append($1, $3);
+		    /*%
+			$$ = mlhs_add($1, $3);
+		    %*/
+		    }
+		;
+
 mlhs_node	: variable
 		    {
 			$$ = assignable($1, 0);
 		    }
-		| primary_value '[' aref_args ']'
+		| primary_value '[' opt_call_args ']'
 		    {
 			$$ = aryset($1, $3);
 		    }
@@ -853,7 +932,7 @@ lhs		: variable
 		    {
 			$$ = assignable($1, 0);
 		    }
-		| primary_value '[' aref_args ']'
+		| primary_value '[' opt_call_args ']'
 		    {
 			$$ = aryset($1, $3);
 		    }
@@ -1015,7 +1094,7 @@ arg		: lhs '=' arg
 			    $$ = 0;
 			}
 		    }
-		| primary_value '[' aref_args ']' tOP_ASGN arg
+		| primary_value '[' opt_call_args ']' tOP_ASGN arg
 		    {
                         NODE *args;
 
@@ -1247,90 +1326,62 @@ arg_value	: arg
 		;
 
 aref_args	: none
-		| command opt_nl
-		    {
-			$$ = NEW_LIST($1);
-		    }
 		| args trailer
 		    {
 			$$ = $1;
 		    }
-		| args ',' tSTAR arg opt_nl
+		| args ',' assocs trailer
 		    {
-			value_expr($4);
-			$$ = arg_concat($1, $4);
+		    /*%%%*/
+			$$ = arg_append($1, NEW_HASH($3));
+		    /*%
+			$$ = arg_add_assocs($1, $3);
+		    %*/
 		    }
 		| assocs trailer
 		    {
 			$$ = NEW_LIST(NEW_HASH($1));
 		    }
-		| tSTAR arg opt_nl
-		    {
-			value_expr($2);
-			$$ = NEW_NEWLINE(NEW_SPLAT($2));
-		    }
 		;
 
-paren_args	: '(' none ')'
+paren_args	: '(' opt_call_args ')'
 		    {
 			$$ = $2;
 		    }
-		| '(' call_args opt_nl ')'
-		    {
-			$$ = $2;
-		    }
-		| '(' block_call opt_nl ')'
-		    {
-			$$ = NEW_LIST($2);
-		    }
-		| '(' args ',' block_call opt_nl ')'
-		    {
-			$$ = list_append($2, $4);
-		    }
 		;
 
 opt_paren_args	: none
 		| paren_args
 		;
 
+opt_call_args	: opt_nl
+		    {
+			$$ = 0;
+		    }
+		| call_args opt_nl
+		    {
+			$$ = $1;
+		    }
+		;
+
 call_args	: command
 		    {
 			$$ = NEW_LIST($1);
 		    }
-		| args opt_block_arg
+		| args2 opt_block_arg
 		    {
 			$$ = arg_blk_pass($1, $2);
 		    }
-		| args ',' tSTAR arg_value opt_block_arg
-		    {
-			$$ = arg_concat($1, $4);
-			$$ = arg_blk_pass($$, $5);
-		    }
 		| assocs opt_block_arg
 		    {
 			$$ = NEW_LIST(NEW_HASH($1));
 			$$ = arg_blk_pass($$, $2);
 		    }
-		| assocs ',' tSTAR arg_value opt_block_arg
-		    {
-			$$ = arg_concat(NEW_LIST(NEW_HASH($1)), $4);
-			$$ = arg_blk_pass($$, $5);
-		    }
-		| args ',' assocs opt_block_arg
+		| args2 ',' assocs opt_block_arg
 		    {
 			$$ = list_append($1, NEW_HASH($3));
 			$$ = arg_blk_pass($$, $4);
 		    }
-		| args ',' assocs ',' tSTAR arg opt_block_arg
-		    {
-			value_expr($6);
-			$$ = arg_concat(list_append($1, NEW_HASH($3)), $6);
-			$$ = arg_blk_pass($$, $7);
-		    }
-		| tSTAR arg_value opt_block_arg
-		    {
-			$$ = arg_blk_pass(NEW_SPLAT($2), $3);
-		    }
 		| block_arg
 		;
 
@@ -1342,26 +1393,11 @@ call_args2	: arg_value ',' args opt_block_arg
 		    {
                         $$ = arg_blk_pass($1, $3);
                     }
-		| arg_value ',' tSTAR arg_value opt_block_arg
-		    {
-			$$ = arg_concat(NEW_LIST($1), $4);
-			$$ = arg_blk_pass($$, $5);
-		    }
-		| arg_value ',' args ',' tSTAR arg_value opt_block_arg
-		    {
-                       $$ = arg_concat(list_concat(NEW_LIST($1),$3), $6);
-			$$ = arg_blk_pass($$, $7);
-		    }
 		| assocs opt_block_arg
 		    {
 			$$ = NEW_LIST(NEW_HASH($1));
 			$$ = arg_blk_pass($$, $2);
 		    }
-		| assocs ',' tSTAR arg_value opt_block_arg
-		    {
-			$$ = arg_concat(NEW_LIST(NEW_HASH($1)), $4);
-			$$ = arg_blk_pass($$, $5);
-		    }
 		| arg_value ',' assocs opt_block_arg
 		    {
 			$$ = list_append(NEW_LIST($1), NEW_HASH($3));
@@ -1372,20 +1408,6 @@ call_args2	: arg_value ',' args opt_block_arg
 			$$ = list_append(list_concat(NEW_LIST($1),$3), NEW_HASH($5));
 			$$ = arg_blk_pass($$, $6);
 		    }
-		| arg_value ',' assocs ',' tSTAR arg_value opt_block_arg
-		    {
-			$$ = arg_concat(list_append(NEW_LIST($1), NEW_HASH($3)), $6);
-			$$ = arg_blk_pass($$, $7);
-		    }
-		| arg_value ',' args ',' assocs ',' tSTAR arg_value opt_block_arg
-		    {
-			$$ = arg_concat(list_append(list_concat(NEW_LIST($1), $3), NEW_HASH($5)), $8);
-			$$ = arg_blk_pass($$, $9);
-		    }
-		| tSTAR arg_value opt_block_arg
-		    {
-			$$ = arg_blk_pass(NEW_SPLAT($2), $3);
-		    }
 		| block_arg
 		;
 
@@ -1427,14 +1449,68 @@ opt_block_arg	: ',' block_arg
 		| none
 		;
 
-args 		: arg_value
+args		: arg_value
 		    {
 			$$ = NEW_LIST($1);
 		    }
+		| tSTAR arg_value
+		    {
+		    /*%%%*/
+			$$ = NEW_TO_ARY($2);
+		    /*%
+			$$ = arg_add_star(arg_new(), $2);
+		    %*/
+		    }
 		| args ',' arg_value
 		    {
 			$$ = list_append($1, $3);
 		    }
+		| args ',' tSTAR arg_value
+		    {
+		    /*%%%*/
+			NODE *n1;
+			if ((nd_type($4) == NODE_ARRAY) && (n1 = splat_array($1)) != 0) {
+			    $$ = list_concat(n1, $4);
+			}
+			else {
+			    $$ = arg_concat($1, $4);
+			}
+		    /*%
+			$$ = arg_add_star($1, $4);
+		    %*/
+		    }
+		;
+
+args2		: arg_value
+		    {
+			$$ = NEW_LIST($1);
+		    }
+		| tSTAR arg_value
+		    {
+		    /*%%%*/
+			$$ = NEW_SPLAT($2);
+		    /*%
+			$$ = arg_add_star(arg_new(), $2);
+		    %*/
+		    }
+		| args2 ',' arg_value
+		    {
+			$$ = list_append($1, $3);
+		    }
+		| args2 ',' tSTAR arg_value
+		    {
+		    /*%%%*/
+			NODE *n1;
+			if ((nd_type($4) == NODE_ARRAY) && (n1 = splat_array($1)) != 0) {
+			    $$ = list_concat(n1, $4);
+			}
+			else {
+			    $$ = arg_concat($1, $4);
+			}
+		    /*%
+			$$ = arg_add_star($1, $4);
+		    %*/
+		    }
 		;
 
 mrhs		: args ',' arg_value
@@ -1494,14 +1570,6 @@ primary		: literal
 		    {
 			$$ = NEW_COLON3($2);
 		    }
-		| primary_value '[' aref_args ']'
-		    {
-			if ($1 && nd_type($1) == NODE_SELF)
-			    $$ = NEW_FCALL(tAREF, $3);
-			else
-			    $$ = NEW_CALL($1, tAREF, $3);
-			fixpos($$, $1);
-		    }
 		| tLBRACK aref_args ']'
 		    {
 		        if ($2 == 0) {
@@ -1909,6 +1977,18 @@ method_call	: operation paren_args
 		    {
 			$$ = NEW_ZSUPER();
 		    }
+		| primary_value '[' opt_call_args ']'
+		    {
+		    /*%%%*/
+			if ($1 && nd_type($1) == NODE_SELF)
+			    $$ = NEW_FCALL(tAREF, $3);
+			else
+			    $$ = NEW_CALL($1, tAREF, $3);
+			fixpos($$, $1);
+		    /*%
+			$$ = dispatch2(aref, $1, escape_Qundef($3));
+		    %*/
+		    }
 		;
 
 brace_block	: '{'
@@ -1937,23 +2017,13 @@ brace_block	: '{'
 		    }
 		;
 
-case_body	: kWHEN when_args then
+case_body	: kWHEN args then
 		  compstmt
 		  cases
 		    {
 			$$ = NEW_WHEN($2, $4, $5);
 		    }
 		;
-when_args	: args
-		| args ',' tSTAR arg_value
-		    {
-			$$ = list_append($1, NEW_WHEN($4, 0, 0));
-		    }
-		| tSTAR arg_value
-		    {
-			$$ = NEW_LIST(NEW_WHEN($2, 0, 0));
-		    }
-		;
 
 cases		: opt_else
 		| case_body
@@ -2312,39 +2382,123 @@ f_arglist	: '(' f_args opt_nl ')'
 
 f_args		: f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
 		    {
-			$$ = block_append(NEW_ARGS($1, $3, $5), $6);
+		    /*%%%*/
+			$$ = new_args($1, $3, $5, 0, $6);
+		    /*%
+			$$ = params_new($1, $3, $5, Qnil, escape_Qundef($6));
+		    %*/
+		    }
+		| f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
+		    {
+		    /*%%%*/
+			$$ = new_args($1, $3, $5, $7, $8);
+		    /*%
+			$$ = params_new($1, $3, $5, $7, escape_Qundef($8));
+		    %*/
 		    }
 		| f_arg ',' f_optarg opt_f_block_arg
 		    {
-			$$ = block_append(NEW_ARGS($1, $3, 0), $4);
+		    /*%%%*/
+			$$ = new_args($1, $3, 0, 0, $4);
+		    /*%
+			$$ = params_new($1, $3, Qnil, Qnil, escape_Qundef($4));
+		    %*/
+		    }
+		| f_arg ',' f_optarg ',' f_arg opt_f_block_arg
+		    {
+		    /*%%%*/
+			$$ = new_args($1, $3, 0, $5, $6);
+		    /*%
+			$$ = params_new($1, $3, Qnil, $5, escape_Qundef($6));
+		    %*/
 		    }
 		| f_arg ',' f_rest_arg opt_f_block_arg
 		    {
-			$$ = block_append(NEW_ARGS($1, 0, $3), $4);
+		    /*%%%*/
+			$$ = new_args($1, 0, $3, 0, $4);
+		    /*%
+			$$ = params_new($1, Qnil, $3, Qnil, escape_Qundef($4));
+		    %*/
+		    }
+		| f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
+		    {
+		    /*%%%*/
+			$$ = new_args($1, 0, $3, $5, $6);
+		    /*%
+			$$ = params_new($1, Qnil, $3, $5, escape_Qundef($6));
+		    %*/
 		    }
 		| f_arg opt_f_block_arg
 		    {
-			$$ = block_append(NEW_ARGS($1, 0, 0), $2);
+		    /*%%%*/
+			$$ = new_args($1, 0, 0, 0, $2);
+		    /*%
+			$$ = params_new($1, Qnil, Qnil, Qnil,escape_Qundef($2));
+		    %*/
 		    }
 		| f_optarg ',' f_rest_arg opt_f_block_arg
 		    {
-			$$ = block_append(NEW_ARGS(0, $1, $3), $4);
+		    /*%%%*/
+			$$ = new_args(0, $1, $3, 0, $4);
+		    /*%
+			$$ = params_new(Qnil, $1, $3, Qnil, escape_Qundef($4));
+		    %*/
+		    }
+		| f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
+		    {
+		    /*%%%*/
+			$$ = new_args(0, $1, $3, $5, $6);
+		    /*%
+			$$ = params_new(Qnil, $1, $3, $5, escape_Qundef($6));
+		    %*/
 		    }
 		| f_optarg opt_f_block_arg
 		    {
-			$$ = block_append(NEW_ARGS(0, $1, 0), $2);
+		    /*%%%*/
+			$$ = new_args(0, $1, 0, 0, $2);
+		    /*%
+			$$ = params_new(Qnil, $1, Qnil, Qnil,escape_Qundef($2));
+		    %*/
+		    }
+		| f_optarg ',' f_arg opt_f_block_arg
+		    {
+		    /*%%%*/
+			$$ = new_args(0, $1, 0, $3, $4);
+		    /*%
+			$$ = params_new(Qnil, $1, Qnil, $3, escape_Qundef($4));
+		    %*/
 		    }
 		| f_rest_arg opt_f_block_arg
 		    {
-			$$ = block_append(NEW_ARGS(0, 0, $1), $2);
+		    /*%%%*/
+			$$ = new_args(0, 0, $1, 0, $2);
+		    /*%
+			$$ = params_new(Qnil, Qnil, $1, Qnil,escape_Qundef($2));
+		    %*/
+		    }
+		| f_rest_arg ',' f_arg opt_f_block_arg
+		    {
+		    /*%%%*/
+			$$ = new_args(0, 0, $1, $3, $4);
+		    /*%
+			$$ = params_new(Qnil, Qnil, $1, $3, escape_Qundef($4));
+		    %*/
 		    }
 		| f_block_arg
 		    {
-			$$ = block_append(NEW_ARGS(0, 0, 0), $1);
+		    /*%%%*/
+			$$ = new_args(0, 0, 0, 0, $1);
+		    /*%
+			$$ = params_new(Qnil, Qnil, Qnil, Qnil, $1);
+		    %*/
 		    }
 		| /* none */
 		    {
-			$$ = NEW_ARGS(0, 0, 0);
+		    /*%%%*/
+			$$ = new_args(0, 0, 0, 0, 0);
+		    /*%
+			$$ = params_new(Qnil, Qnil, Qnil, Qnil, Qnil);
+		    %*/
 		    }
 		;
 
@@ -4846,6 +5000,23 @@ literal_concat(head, tail)
     return head;
 }
 
+static NODE*
+new_args(m, o, r, p, b)
+    NODE *m, *o, *p, *b;
+    ID r;
+{
+    if (p) {
+        ID i = rb_intern("raise");
+        VALUE e = rb_eSyntaxError; /* or maybe a subclass of it? */
+        VALUE s = rb_str_new2("Unsupported 1.9-ism: loose formal opt/rest args");
+        NODE *n = NEW_FCALL(i, list_append(NEW_LIST(NEW_LIT(e)), NEW_LIT(s)));
+        NODE *b = NEW_BLOCK(n);
+        b->nd_end = b;
+        return b;
+    }
+    return block_append(NEW_ARGS(m, o, r), b);
+}
+                                  
 static NODE *
 evstr2dstr(node)
     NODE *node;
@@ -4875,6 +5046,24 @@ new_evstr(node)
     return NEW_EVSTR(head);
 }
 
+static VALUE
+new_postarg_internal_raise(argc, argv)
+    int argc;
+    VALUE *argv;
+{
+    rb_raise(rb_eSyntaxError, "Unsupported 1.9-ism: loose multiple assignment (LHS)");
+    return Qundef; /* NOTREACHED */
+}
+
+static NODE *
+NEW_POSTARG(n1, n2)
+    NODE *n1, *n2;
+{
+    VALUE obj = rb_obj_alloc(rb_cObject);
+    rb_define_singleton_method(obj, "raise", new_postarg_internal_raise, -1);
+    return NEW_CALL(NEW_LIT(obj), rb_intern("raise"), NEW_LIST(0));
+}
+
 static NODE *
 call_op(recv, id, narg, arg1)
     NODE *recv;
@@ -5089,6 +5278,15 @@ rb_backref_error(node)
 }
 
 static NODE *
+arg_append(node1, node2)
+    NODE *node1;
+    NODE *node2;
+{
+    if (!node1) return NEW_LIST(node2);
+    return NEW_ARGSPUSH(node1, node2);
+}
+
+static NODE *
 arg_concat(node1, node2)
     NODE *node1;
     NODE *node2;
@@ -5111,6 +5309,15 @@ arg_add(node1, node2)
     }
 }
 
+static NODE *
+splat_array(node)
+    NODE* node;
+{
+    if (nd_type(node) == NODE_SPLAT) node = node->nd_head;
+    if (nd_type(node) == NODE_ARRAY) return node;
+    return 0;
+}
+
 static NODE*
 node_assign(lhs, rhs)
     NODE *lhs, *rhs;
