Feature #10481 » rescue-conditions.diff
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
|