Project

General

Profile

Feature #1968 ยป looser_args.patch

shyouhei (Shyouhei Urabe), 08/21/2009 01:54 AM

View differences:

ChangeLog
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),
......
* 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.
eval.c
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");
}
parse.y
static int command_start = Qtrue;
static NODE *deferred_nodes;
static NODE *NEW_POSTARG();
static NODE *new_args();
static NODE *cond();
static NODE *logop();
......
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;
......
%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
......
$$ = 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;
......
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);
%*/
}
;
......
}
;
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);
}
......
{
$$ = assignable($1, 0);
}
| primary_value '[' aref_args ']'
| primary_value '[' opt_call_args ']'
{
$$ = aryset($1, $3);
}
......
$$ = 0;
}
}
| primary_value '[' aref_args ']' tOP_ASGN arg
| primary_value '[' opt_call_args ']' tOP_ASGN arg
{
NODE *args;
......
;
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
;
......
{
$$ = 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));
......
$$ = 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
;
......
| 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
......
{
$$ = 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) {
......
{
$$ = 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 : '{'
......
}
;
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
......
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);
%*/
}
;
......
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;
......
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;
......
}
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;
......
}
}
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;
    (1-1/1)