Endless method definition including `rescue` modifier

This commit is contained in:
Nobuyoshi Nakada 2020-05-14 17:27:48 +09:00
Родитель 634eeb4353
Коммит d7d0d01401
2 изменённых файлов: 40 добавлений и 2 удалений

36
parse.y
Просмотреть файл

@ -920,6 +920,17 @@ set_defun_body(struct parser_params *p, NODE *n, NODE *args, NODE *body, const Y
set_line_body(body, loc->beg_pos.lineno);
return n;
}
static NODE *
rescued_expr(struct parser_params *p, NODE *arg, NODE *rescue,
const YYLTYPE *arg_loc, const YYLTYPE *mod_loc, const YYLTYPE *res_loc)
{
YYLTYPE loc = code_loc_gen(mod_loc, res_loc);
rescue = NEW_RESBODY(0, remove_begin(rescue), 0, &loc);
loc.beg_pos = arg_loc->beg_pos;
return NEW_RESCUE(arg, rescue, 0, &loc);
}
#endif /* RIPPER */
static void
@ -2455,6 +2466,16 @@ arg : lhs '=' arg_rhs
/*% ripper: def!(get_value($1), $2, $4) %*/
local_pop(p);
}
| defn_head f_paren_args '=' arg modifier_rescue arg
{
restore_defun(p, $<node>1->nd_defn);
/*%%%*/
$4 = rescued_expr(p, $4, $6, &@4, &@5, &@6);
$$ = set_defun_body(p, $1, $2, $4, &@$);
/*% %*/
/*% ripper: def!(get_value($1), $2, rescue_mod!($4, $6)) %*/
local_pop(p);
}
| defs_head f_paren_args '=' arg
{
restore_defun(p, $<node>1->nd_defn);
@ -2466,6 +2487,18 @@ arg : lhs '=' arg_rhs
/*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, $4) %*/
local_pop(p);
}
| defs_head f_paren_args '=' arg modifier_rescue arg
{
restore_defun(p, $<node>1->nd_defn);
/*%%%*/
$4 = rescued_expr(p, $4, $6, &@4, &@5, &@6);
$$ = set_defun_body(p, $1, $2, $4, &@$);
/*%
$1 = get_value($1);
%*/
/*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, rescue_mod!($4, $6)) %*/
local_pop(p);
}
| primary
{
$$ = $1;
@ -2525,9 +2558,8 @@ arg_rhs : arg %prec tOP_ASGN
| arg modifier_rescue arg
{
/*%%%*/
YYLTYPE loc = code_loc_gen(&@2, &@3);
value_expr($1);
$$ = NEW_RESCUE($1, NEW_RESBODY(0, remove_begin($3), 0, &loc), 0, &@$);
$$ = rescued_expr(p, $1, $3, &@1, &@2, &@3);
/*% %*/
/*% ripper: rescue_mod!($1, $3) %*/
}

Просмотреть файл

@ -1423,6 +1423,12 @@ eom
assert_valid_syntax('private def obj.inc(x) = x + 1')
eval('def self.inc(x) = x + 1 => @x')
assert_equal(:inc, @x)
k = Class.new do
class_eval('def rescued(x) = raise("to be caught") rescue "instance #{x}"')
class_eval('def self.rescued(x) = raise("to be caught") rescue "class #{x}"')
end
assert_equal("class ok", k.rescued("ok"))
assert_equal("instance ok", k.new.rescued("ok"))
end
def test_methoddef_in_cond