Project

General

Profile

Feature #10481 » rescue-conditions.diff

javawizard (Alex Boyd), 11/20/2014 12:13 PM

View differences:

compile.c
ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, lend, lcont, 0, lstart);
break;
}
case NODE_RESCOND:
case NODE_RESBODY:{
NODE *resq = node;
NODE *narg;
LABEL *label_miss, *label_hit;
NODE *narg, *cond;
LABEL *label_miss, *label_hit, *label_pass;
while (resq) {
label_miss = NEW_LABEL(line);
label_hit = NEW_LABEL(line);
if (nd_type(resq) == NODE_RESCOND) {
label_pass = NEW_LABEL(line);
cond = resq->nd_cond;
resq = resq->nd_resq;
}
narg = resq->nd_args;
if (narg) {
switch (nd_type(narg)) {
......
}
ADD_INSNL(ret, line, jump, label_miss);
ADD_LABEL(ret, label_hit);
if (cond) {
switch (nd_type(cond)) {
case NODE_RESCOND_IF:
compile_branch_condition(iseq, ret, cond->nd_cond, label_pass, label_miss);
break;
case NODE_RESCOND_UNLESS:
compile_branch_condition(iseq, ret, cond->nd_cond, label_miss, label_pass);
break;
default:
rb_bug("NODE_RESCOND: unknown node (%s)",
ruby_node_name(nd_type(cond)));
}
ADD_LABEL(ret, label_pass);
}
COMPILE(ret, "resbody body", resq->nd_body);
if (iseq->compile_data->option->tailcall_optimization) {
ADD_INSN(ret, line, nop);
......
ADD_INSN(ret, line, leave);
ADD_LABEL(ret, label_miss);
resq = resq->nd_head;
cond = 0;
}
break;
}
ext/objspace/objspace.c
COUNT_NODE(NODE_BEGIN);
COUNT_NODE(NODE_RESCUE);
COUNT_NODE(NODE_RESBODY);
COUNT_NODE(NODE_RESCOND);
COUNT_NODE(NODE_RESCOND_IF);
COUNT_NODE(NODE_RESCOND_UNLESS);
COUNT_NODE(NODE_ENSURE);
COUNT_NODE(NODE_AND);
COUNT_NODE(NODE_OR);
gc.c
case NODE_ALIAS:
case NODE_VALIAS:
case NODE_ARGSCAT:
case NODE_RESCOND:
gc_mark(objspace, (VALUE)obj->as.node.u1.node);
/* fall through */
case NODE_GASGN: /* 2 */
......
case NODE_COLON2:
case NODE_SPLAT:
case NODE_TO_ARY:
case NODE_RESCOND_IF:
case NODE_RESCOND_UNLESS:
ptr = (VALUE)obj->as.node.u1.node;
goto again;
node.c
F_NODE(nd_head, "next rescue clause");
break;
case NODE_RESCOND:
ANN("conditional rescue");
ANN("format: (rescue) [nd_body] (if or unless) [nd_cond]");
F_NODE(nd_cond, "rescue condition");
LAST_NODE;
F_NODE(nd_resq, "rescue clause");
break;
case NODE_RESCOND_IF:
ANN("conditional rescue if modifier");
ANN("format: if [nd_cond]");
LAST_NODE;
F_NODE(nd_cond, "condition");
break;
case NODE_RESCOND_UNLESS:
ANN("conditional rescue unless modifier");
ANN("format: unless [nd_cond]");
LAST_NODE;
F_NODE(nd_cond, "condition");
break;
case NODE_ENSURE:
ANN("ensure clause");
ANN("format: begin; [nd_head]; ensure; [nd_ensr]; end");
node.h
#define NODE_RESCUE NODE_RESCUE
NODE_RESBODY,
#define NODE_RESBODY NODE_RESBODY
NODE_RESCOND,
#define NODE_RESCOND NODE_RESCOND
NODE_RESCOND_IF,
#define NODE_RESCOND_IF NODE_RESCOND_IF
NODE_RESCOND_UNLESS,
#define NODE_RESCOND_UNLESS NODE_RESCOND_UNLESS
NODE_ENSURE,
#define NODE_ENSURE NODE_ENSURE
NODE_AND,
......
#define NEW_BEGIN(b) NEW_NODE(NODE_BEGIN,0,b,0)
#define NEW_RESCUE(b,res,e) NEW_NODE(NODE_RESCUE,b,res,e)
#define NEW_RESBODY(a,ex,n) NEW_NODE(NODE_RESBODY,n,ex,a)
#define NEW_RESCOND(c,b) NEW_NODE(NODE_RESCOND,c,b,0)
#define NEW_RESCOND_IF(c) NEW_NODE(NODE_RESCOND_IF,c,0,0)
#define NEW_RESCOND_UNLESS(c) NEW_NODE(NODE_RESCOND_UNLESS,c,0,0)
#define NEW_ENSURE(b,en) NEW_NODE(NODE_ENSURE,b,0,en)
#define NEW_RETURN(s) NEW_NODE(NODE_RETURN,s,0,0)
#define NEW_YIELD(a) NEW_NODE(NODE_YIELD,a,0,0)
parse.y
%type <node> top_compstmt top_stmts top_stmt
%type <node> bodystmt compstmt stmts stmt_or_begin stmt expr arg primary command command_call method_call
%type <node> expr_value arg_value primary_value fcall
%type <node> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
%type <node> if_tail opt_else case_body cases opt_rescue exc_cond exc_list exc_var opt_ensure
%type <node> args call_args opt_call_args
%type <node> paren_args opt_paren_args args_tail opt_args_tail block_args_tail opt_block_args_tail
%type <node> command_args aref_args opt_block_arg block_arg var_ref var_lhs
......
| case_body
;
opt_rescue : keyword_rescue exc_list exc_var then
opt_rescue : keyword_rescue exc_list exc_var exc_cond then
compstmt
opt_rescue
{
/*%%%*/
if ($3) {
$3 = node_assign($3, NEW_ERRINFO());
$5 = block_append($3, $5);
if ($4) {
$4->nd_cond = block_append($3, $4->nd_cond);
}
else {
$6 = block_append($3, $6);
}
}
$$ = NEW_RESBODY($2, $6, $7);
if ($4) {
$$ = NEW_RESCOND($4, $$);
}
$$ = NEW_RESBODY($2, $5, $6);
fixpos($$, $2?$2:$5);
fixpos($$, $2?$2:$6);
/*%
$$ = dispatch4(rescue,
$$ = dispatch5(rescue,
escape_Qundef($2),
escape_Qundef($3),
escape_Qundef($5),
escape_Qundef($6));
escape_Qundef($4),
escape_Qundef($6),
escape_Qundef($7));
%*/
}
| none
;
exc_cond : modifier_if expr_value
{
/*%%%*/
$$ = NEW_RESCOND_IF(cond($2));
/*%
$$ = dispatch1(rescond_if, $2);
%*/
}
| modifier_unless expr_value
{
/*%%%*/
$$ = NEW_RESCOND_UNLESS(cond($2));
/*%
$$ = dispatch1(rescond_unless, $2);
%*/
}
| none
(1-1/3)