зеркало из https://github.com/github/ruby.git
Implement BREAK, NEXT and REDO NODE locations
This commit is contained in:
Родитель
f7ffa76377
Коммит
d03e0d1c35
12
ast.c
12
ast.c
|
@ -783,10 +783,22 @@ node_locations(VALUE ast_value, const NODE *node)
|
|||
return rb_ary_new_from_args(2,
|
||||
location_new(nd_code_loc(node)),
|
||||
location_new(&RNODE_AND(node)->operator_loc));
|
||||
case NODE_BREAK:
|
||||
return rb_ary_new_from_args(2,
|
||||
location_new(nd_code_loc(node)),
|
||||
location_new(&RNODE_BREAK(node)->keyword_loc));
|
||||
case NODE_NEXT:
|
||||
return rb_ary_new_from_args(2,
|
||||
location_new(nd_code_loc(node)),
|
||||
location_new(&RNODE_NEXT(node)->keyword_loc));
|
||||
case NODE_OR:
|
||||
return rb_ary_new_from_args(2,
|
||||
location_new(nd_code_loc(node)),
|
||||
location_new(&RNODE_OR(node)->operator_loc));
|
||||
case NODE_REDO:
|
||||
return rb_ary_new_from_args(2,
|
||||
location_new(nd_code_loc(node)),
|
||||
location_new(&RNODE_REDO(node)->keyword_loc));
|
||||
case NODE_UNDEF:
|
||||
return rb_ary_new_from_args(2,
|
||||
location_new(nd_code_loc(node)),
|
||||
|
|
|
@ -352,15 +352,17 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
|
|||
ANN("break statement");
|
||||
ANN("format: break [nd_stts]");
|
||||
ANN("example: break 1");
|
||||
LAST_NODE;
|
||||
F_NODE(nd_stts, RNODE_BREAK, "value");
|
||||
LAST_NODE;
|
||||
F_LOC(keyword_loc, RNODE_REDO);
|
||||
return;
|
||||
case NODE_NEXT:
|
||||
ANN("next statement");
|
||||
ANN("format: next [nd_stts]");
|
||||
ANN("example: next 1");
|
||||
LAST_NODE;
|
||||
F_NODE(nd_stts, RNODE_NEXT, "value");
|
||||
LAST_NODE;
|
||||
F_LOC(keyword_loc, RNODE_REDO);
|
||||
return;
|
||||
case NODE_RETURN:
|
||||
ANN("return statement");
|
||||
|
@ -374,6 +376,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
|
|||
ANN("redo statement");
|
||||
ANN("format: redo");
|
||||
ANN("example: redo");
|
||||
F_LOC(keyword_loc, RNODE_REDO);
|
||||
return;
|
||||
|
||||
case NODE_RETRY:
|
||||
|
|
31
parse.y
31
parse.y
|
@ -1313,15 +1313,15 @@ struct RNode_DEF_TEMP {
|
|||
|
||||
#define RNODE_DEF_TEMP(node) ((struct RNode_DEF_TEMP *)(node))
|
||||
|
||||
static rb_node_break_t *rb_node_break_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc);
|
||||
static rb_node_next_t *rb_node_next_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc);
|
||||
static rb_node_redo_t *rb_node_redo_new(struct parser_params *p, const YYLTYPE *loc);
|
||||
static rb_node_break_t *rb_node_break_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc);
|
||||
static rb_node_next_t *rb_node_next_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc);
|
||||
static rb_node_redo_t *rb_node_redo_new(struct parser_params *p, const YYLTYPE *loc, const YYLTYPE *keyword_loc);
|
||||
static rb_node_def_temp_t *rb_node_def_temp_new(struct parser_params *p, const YYLTYPE *loc);
|
||||
static rb_node_def_temp_t *def_head_save(struct parser_params *p, rb_node_def_temp_t *n);
|
||||
|
||||
#define NEW_BREAK(s,loc) (NODE *)rb_node_break_new(p,s,loc)
|
||||
#define NEW_NEXT(s,loc) (NODE *)rb_node_next_new(p,s,loc)
|
||||
#define NEW_REDO(loc) (NODE *)rb_node_redo_new(p,loc)
|
||||
#define NEW_BREAK(s,loc,k_loc) (NODE *)rb_node_break_new(p,s,loc,k_loc)
|
||||
#define NEW_NEXT(s,loc,k_loc) (NODE *)rb_node_next_new(p,s,loc,k_loc)
|
||||
#define NEW_REDO(loc,k_loc) (NODE *)rb_node_redo_new(p,loc,k_loc)
|
||||
#define NEW_DEF_TEMP(loc) rb_node_def_temp_new(p,loc)
|
||||
|
||||
/* Make a new internal node, which should not be appeared in the
|
||||
|
@ -3538,14 +3538,14 @@ command : fcall command_args %prec tLOWEST
|
|||
{
|
||||
NODE *args = 0;
|
||||
args = ret_args(p, $2);
|
||||
$$ = add_block_exit(p, NEW_BREAK(args, &@$));
|
||||
$$ = add_block_exit(p, NEW_BREAK(args, &@$, &@1));
|
||||
/*% ripper: break!($:2) %*/
|
||||
}
|
||||
| keyword_next call_args
|
||||
{
|
||||
NODE *args = 0;
|
||||
args = ret_args(p, $2);
|
||||
$$ = add_block_exit(p, NEW_NEXT(args, &@$));
|
||||
$$ = add_block_exit(p, NEW_NEXT(args, &@$, &@1));
|
||||
/*% ripper: next!($:2) %*/
|
||||
}
|
||||
;
|
||||
|
@ -4701,17 +4701,17 @@ primary : literal
|
|||
}
|
||||
| keyword_break
|
||||
{
|
||||
$$ = add_block_exit(p, NEW_BREAK(0, &@$));
|
||||
$$ = add_block_exit(p, NEW_BREAK(0, &@$, &@1));
|
||||
/*% ripper: break!(args_new!) %*/
|
||||
}
|
||||
| keyword_next
|
||||
{
|
||||
$$ = add_block_exit(p, NEW_NEXT(0, &@$));
|
||||
$$ = add_block_exit(p, NEW_NEXT(0, &@$, &@1));
|
||||
/*% ripper: next!(args_new!) %*/
|
||||
}
|
||||
| keyword_redo
|
||||
{
|
||||
$$ = add_block_exit(p, NEW_REDO(&@$));
|
||||
$$ = add_block_exit(p, NEW_REDO(&@$, &@1));
|
||||
/*% ripper: redo! %*/
|
||||
}
|
||||
| keyword_retry
|
||||
|
@ -12468,30 +12468,33 @@ rb_node_error_new(struct parser_params *p, const YYLTYPE *loc)
|
|||
}
|
||||
|
||||
static rb_node_break_t *
|
||||
rb_node_break_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc)
|
||||
rb_node_break_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc)
|
||||
{
|
||||
rb_node_break_t *n = NODE_NEWNODE(NODE_BREAK, rb_node_break_t, loc);
|
||||
n->nd_stts = nd_stts;
|
||||
n->nd_chain = 0;
|
||||
n->keyword_loc = *keyword_loc;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static rb_node_next_t *
|
||||
rb_node_next_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc)
|
||||
rb_node_next_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc)
|
||||
{
|
||||
rb_node_next_t *n = NODE_NEWNODE(NODE_NEXT, rb_node_next_t, loc);
|
||||
n->nd_stts = nd_stts;
|
||||
n->nd_chain = 0;
|
||||
n->keyword_loc = *keyword_loc;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static rb_node_redo_t *
|
||||
rb_node_redo_new(struct parser_params *p, const YYLTYPE *loc)
|
||||
rb_node_redo_new(struct parser_params *p, const YYLTYPE *loc, const YYLTYPE *keyword_loc)
|
||||
{
|
||||
rb_node_redo_t *n = NODE_NEWNODE(NODE_REDO, rb_node_redo_t, loc);
|
||||
n->nd_chain = 0;
|
||||
n->keyword_loc = *keyword_loc;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -345,6 +345,7 @@ typedef struct RNode_EXITS {
|
|||
|
||||
struct RNode *nd_chain;
|
||||
struct RNode *nd_stts;
|
||||
rb_code_location_t keyword_loc;
|
||||
} rb_node_exits_t, rb_node_break_t, rb_node_next_t, rb_node_redo_t;
|
||||
|
||||
typedef struct RNode_RETRY {
|
||||
|
|
|
@ -1343,6 +1343,16 @@ dummy
|
|||
assert_locations(node.children[-1].locations, [[1, 0, 1, 6], [1, 2, 1, 4]])
|
||||
end
|
||||
|
||||
def test_break_locations
|
||||
node = RubyVM::AbstractSyntaxTree.parse("loop { break 1 }")
|
||||
assert_locations(node.children[-1].children[-1].children[-1].locations, [[1, 7, 1, 14], [1, 7, 1, 12]])
|
||||
end
|
||||
|
||||
def test_next_locations
|
||||
node = RubyVM::AbstractSyntaxTree.parse("loop { next 1 }")
|
||||
assert_locations(node.children[-1].children[-1].children[-1].locations, [[1, 7, 1, 13], [1, 7, 1, 11]])
|
||||
end
|
||||
|
||||
def test_or_locations
|
||||
node = RubyVM::AbstractSyntaxTree.parse("1 or 2")
|
||||
assert_locations(node.children[-1].locations, [[1, 0, 1, 6], [1, 2, 1, 4]])
|
||||
|
@ -1351,6 +1361,11 @@ dummy
|
|||
assert_locations(node.children[-1].locations, [[1, 0, 1, 6], [1, 2, 1, 4]])
|
||||
end
|
||||
|
||||
def test_redo_locations
|
||||
node = RubyVM::AbstractSyntaxTree.parse("loop { redo }")
|
||||
assert_locations(node.children[-1].children[-1].children[-1].locations, [[1, 7, 1, 11], [1, 7, 1, 11]])
|
||||
end
|
||||
|
||||
def test_unless_locations
|
||||
node = RubyVM::AbstractSyntaxTree.parse("unless cond then 1 else 2 end")
|
||||
assert_locations(node.children[-1].locations, [[1, 0, 1, 29], [1, 0, 1, 6], [1, 12, 1, 16], [1, 26, 1, 29]])
|
||||
|
|
Загрузка…
Ссылка в новой задаче