Project

General

Profile

Feature #6073 ยป 0001-extend-for-loop-syntax.patch

shouichi (Shouichi Kamiya), 02/24/2012 02:19 PM

View differences:

parse.y
#ifndef RIPPER
#define yyparse ruby_yyparse
static NODE *node_for(struct parser_params*,NODE*,NODE*,NODE*,NODE*);
#define rb_node_for(n1,n2,n3,n4) node_for(parser,(n1),(n2),(n3),(n4))
static NODE* node_newnode(struct parser_params *, enum node_type, VALUE, VALUE, VALUE);
#define rb_node_newnode(type, a1, a2, a3) node_newnode(parser, (type), (a1), (a2), (a3))
......
%type <node> command_asgn mrhs superclass block_call block_command
%type <node> f_block_optarg f_block_opt
%type <node> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs
%type <node> assoc_list assocs assoc undef_list backref string_dvar for_var
%type <node> assoc_list assocs assoc undef_list backref string_dvar for_var guarded_loops
%type <node> block_param opt_block_param block_param_def f_opt
%type <node> f_kwarg f_kw f_block_kwarg f_block_kw
%type <node> bv_decls opt_bv_decl bvar
......
$$ = dispatch2(case, Qnil, $3);
%*/
}
| k_for for_var keyword_in
{COND_PUSH(1);}
expr_value do
{COND_POP();}
compstmt
| k_for
guarded_loops
k_end
{
/*%%%*/
/*
* for a, b, c in e
* #=>
* e.each{|*x| a, b, c = x
*
* for a in e
* #=>
* e.each{|x| a, = x}
*/
ID id = internal_id();
ID *tbl = ALLOC_N(ID, 2);
NODE *m = NEW_ARGS_AUX(0, 0);
NODE *args, *scope;
if (nd_type($2) == NODE_MASGN) {
/* if args.length == 1 && args[0].kind_of?(Array)
* args = args[0]
* end
*/
NODE *one = NEW_LIST(NEW_LIT(INT2FIX(1)));
NODE *zero = NEW_LIST(NEW_LIT(INT2FIX(0)));
m->nd_next = block_append(
NEW_IF(
NEW_NODE(NODE_AND,
NEW_CALL(NEW_CALL(NEW_DVAR(id), rb_intern("length"), 0),
rb_intern("=="), one),
NEW_CALL(NEW_CALL(NEW_DVAR(id), rb_intern("[]"), zero),
rb_intern("kind_of?"), NEW_LIST(NEW_LIT(rb_cArray))),
0),
NEW_DASGN_CURR(id,
NEW_CALL(NEW_DVAR(id), rb_intern("[]"), zero)),
0),
node_assign($2, NEW_DVAR(id)));
args = new_args(m, 0, id, 0, 0, 0, 0);
}
else {
if (nd_type($2) == NODE_LASGN ||
nd_type($2) == NODE_DASGN ||
nd_type($2) == NODE_DASGN_CURR) {
$2->nd_value = NEW_DVAR(id);
m->nd_plen = 1;
m->nd_next = $2;
args = new_args(m, 0, 0, 0, 0, 0, 0);
}
else {
m->nd_next = node_assign(NEW_MASGN(NEW_LIST($2), 0), NEW_DVAR(id));
args = new_args(m, 0, id, 0, 0, 0, 0);
}
}
scope = NEW_NODE(NODE_SCOPE, tbl, $8, args);
tbl[0] = 1; tbl[1] = id;
$$ = NEW_FOR(0, $5, scope);
fixpos($$, $2);
/*%
$$ = dispatch3(for, $2, $5, $8);
%*/
$$ = $2;
/*% %*/
}
| k_class cpath superclass
{
......
| case_body
;
guarded_loops : for_var keyword_in expr_value keyword_when expr_value term compstmt
{
/*%%%*/
$$ = rb_node_for($1, $3, $5, $7);
/*% %*/
}
| for_var keyword_in expr_value term compstmt
{
/*%%%*/
$$ = rb_node_for($1, $3, 0, $5);
/*% %*/
}
| for_var keyword_in expr_value keyword_when expr_value term guarded_loops
{
/*%%%*/
$$ = rb_node_for($1, $3, $5, $7);
/*% %*/
}
| for_var keyword_in expr_value term guarded_loops
{
/*%%%*/
$$ = rb_node_for($1, $3, 0, $5);
/*% %*/
}
opt_rescue : keyword_rescue exc_list exc_var then
compstmt
opt_rescue
......
return t;
}
static NODE *
node_for(struct parser_params *parser, NODE *for_var, NODE *array, NODE *condition, NODE *compstmt)
{
ID id = internal_id();
ID *tbl = ALLOC_N(ID, 2);
NODE *m = NEW_ARGS_AUX(0, 0);
NODE *args, *scope, *node_for;
if (nd_type(for_var) == NODE_MASGN) {
/* if args.length == 1 && args[0].kind_of?(Array)
* args = args[0]
* end
*/
NODE *one = NEW_LIST(NEW_LIT(INT2FIX(1)));
NODE *zero = NEW_LIST(NEW_LIT(INT2FIX(0)));
m->nd_next = block_append(
NEW_IF(
NEW_NODE(NODE_AND,
NEW_CALL(NEW_CALL(NEW_DVAR(id), rb_intern("length"), 0),
rb_intern("=="), one),
NEW_CALL(NEW_CALL(NEW_DVAR(id), rb_intern("[]"), zero),
rb_intern("kind_of?"), NEW_LIST(NEW_LIT(rb_cArray))),
0),
NEW_DASGN_CURR(id,
NEW_CALL(NEW_DVAR(id), rb_intern("[]"), zero)),
0),
node_assign(for_var, NEW_DVAR(id)));
args = new_args(m, 0, id, 0, 0, 0, 0);
}
else {
if (nd_type(for_var) == NODE_LASGN ||
nd_type(for_var) == NODE_DASGN ||
nd_type(for_var) == NODE_DASGN_CURR) {
for_var->nd_value = NEW_DVAR(id);
m->nd_plen = 1;
m->nd_next = for_var;
args = new_args(m, 0, 0, 0, 0, 0, 0);
}
else {
m->nd_next = node_assign(NEW_MASGN(NEW_LIST(for_var), 0), NEW_DVAR(id));
args = new_args(m, 0, id, 0, 0, 0, 0);
}
}
if (condition == 0) {
scope = NEW_NODE(NODE_SCOPE, tbl, compstmt, args);
}
else {
scope = NEW_NODE(NODE_SCOPE, tbl, NEW_IF(cond(condition), compstmt, 0), args);
}
tbl[0] = 1; tbl[1] = id;
node_for = NEW_FOR(0, array, scope);
fixpos(node_for, for_var);
return node_for;
}
#ifndef RIPPER
static NODE*
node_newnode(struct parser_params *parser, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
    (1-1/1)