diff options
author | ydah <[email protected]> | 2024-09-10 00:13:24 +0900 |
---|---|---|
committer | Yuichiro Kaneko <[email protected]> | 2024-09-11 09:28:55 +0900 |
commit | 4e6091ce09154d735cca025a4d0130eecebbbc19 (patch) | |
tree | cea93508f61b03a15b6f28b402ecaea980426aeb | |
parent | 1adcc41b94d49899b1809fba119f74501fc992b1 (diff) |
Implement WHILE and UNTIL NODE locations
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/11579
-rw-r--r-- | ast.c | 10 | ||||
-rw-r--r-- | node_dump.c | 4 | ||||
-rw-r--r-- | parse.y | 30 | ||||
-rw-r--r-- | rubyparser.h | 2 | ||||
-rw-r--r-- | test/ruby/test_ast.rb | 16 |
5 files changed, 48 insertions, 14 deletions
@@ -806,6 +806,16 @@ node_locations(VALUE ast_value, const NODE *node) location_new(nd_code_loc(node)), location_new(&RNODE_WHEN(node)->keyword_loc), location_new(&RNODE_WHEN(node)->then_keyword_loc)); + case NODE_WHILE: + return rb_ary_new_from_args(3, + location_new(nd_code_loc(node)), + location_new(&RNODE_WHILE(node)->keyword_loc), + location_new(&RNODE_WHILE(node)->closing_loc)); + case NODE_UNTIL: + return rb_ary_new_from_args(3, + location_new(nd_code_loc(node)), + location_new(&RNODE_UNTIL(node)->keyword_loc), + location_new(&RNODE_UNTIL(node)->closing_loc)); case NODE_ARGS_AUX: case NODE_LAST: break; diff --git a/node_dump.c b/node_dump.c index d97a400a97..64b0cb8b7f 100644 --- a/node_dump.c +++ b/node_dump.c @@ -319,8 +319,10 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) A((RNODE_WHILE(node)->nd_state == 1) ? " (while-end)" : " (begin-end-while)"); } F_NODE(nd_cond, RNODE_WHILE, "condition"); - LAST_NODE; F_NODE(nd_body, RNODE_WHILE, "body"); + F_LOC(keyword_loc, RNODE_WHILE); + LAST_NODE; + F_LOC(closing_loc, RNODE_WHILE); return; case NODE_ITER: @@ -1068,8 +1068,8 @@ static rb_node_case2_t *rb_node_case2_new(struct parser_params *p, NODE *nd_body static rb_node_case3_t *rb_node_case3_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc); static rb_node_when_t *rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *then_keyword_loc); static rb_node_in_t *rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc); -static rb_node_while_t *rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc); -static rb_node_until_t *rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc); +static rb_node_while_t *rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *closing_loc); +static rb_node_until_t *rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *closing_loc); static rb_node_iter_t *rb_node_iter_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc); static rb_node_for_t *rb_node_for_new(struct parser_params *p, NODE *nd_iter, NODE *nd_body, const YYLTYPE *loc); static rb_node_for_masgn_t *rb_node_for_masgn_new(struct parser_params *p, NODE *nd_var, const YYLTYPE *loc); @@ -1176,8 +1176,8 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE #define NEW_CASE3(h,b,loc) (NODE *)rb_node_case3_new(p,h,b,loc) #define NEW_WHEN(c,t,e,loc,k_loc,t_loc) (NODE *)rb_node_when_new(p,c,t,e,loc,k_loc,t_loc) #define NEW_IN(c,t,e,loc) (NODE *)rb_node_in_new(p,c,t,e,loc) -#define NEW_WHILE(c,b,n,loc) (NODE *)rb_node_while_new(p,c,b,n,loc) -#define NEW_UNTIL(c,b,n,loc) (NODE *)rb_node_until_new(p,c,b,n,loc) +#define NEW_WHILE(c,b,n,loc,k_loc,c_loc) (NODE *)rb_node_while_new(p,c,b,n,loc,k_loc,c_loc) +#define NEW_UNTIL(c,b,n,loc,k_loc,c_loc) (NODE *)rb_node_until_new(p,c,b,n,loc,k_loc,c_loc) #define NEW_ITER(a,b,loc) (NODE *)rb_node_iter_new(p,a,b,loc) #define NEW_FOR(i,b,loc) (NODE *)rb_node_for_new(p,i,b,loc) #define NEW_FOR_MASGN(v,loc) (NODE *)rb_node_for_masgn_new(p,v,loc) @@ -3176,10 +3176,10 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem { clear_block_exit(p, false); if ($1 && nd_type_p($1, NODE_BEGIN)) { - $$ = NEW_WHILE(cond(p, $3, &@3), RNODE_BEGIN($1)->nd_body, 0, &@$); + $$ = NEW_WHILE(cond(p, $3, &@3), RNODE_BEGIN($1)->nd_body, 0, &@$, &@2, &NULL_LOC); } else { - $$ = NEW_WHILE(cond(p, $3, &@3), $1, 1, &@$); + $$ = NEW_WHILE(cond(p, $3, &@3), $1, 1, &@$, &@2, &NULL_LOC); } /*% ripper: while_mod!($:3, $:1) %*/ } @@ -3187,10 +3187,10 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem { clear_block_exit(p, false); if ($1 && nd_type_p($1, NODE_BEGIN)) { - $$ = NEW_UNTIL(cond(p, $3, &@3), RNODE_BEGIN($1)->nd_body, 0, &@$); + $$ = NEW_UNTIL(cond(p, $3, &@3), RNODE_BEGIN($1)->nd_body, 0, &@$, &@2, &NULL_LOC); } else { - $$ = NEW_UNTIL(cond(p, $3, &@3), $1, 1, &@$); + $$ = NEW_UNTIL(cond(p, $3, &@3), $1, 1, &@$, &@2, &NULL_LOC); } /*% ripper: until_mod!($:3, $:1) %*/ } @@ -4527,7 +4527,7 @@ primary : literal k_end { restore_block_exit(p, $1); - $$ = NEW_WHILE(cond(p, $2, &@2), $3, 1, &@$); + $$ = NEW_WHILE(cond(p, $2, &@2), $3, 1, &@$, &@1, &@4); fixpos($$, $2); /*% ripper: while!($:2, $:3) %*/ } @@ -4536,7 +4536,7 @@ primary : literal k_end { restore_block_exit(p, $1); - $$ = NEW_UNTIL(cond(p, $2, &@2), $3, 1, &@$); + $$ = NEW_UNTIL(cond(p, $2, &@2), $3, 1, &@$, &@1, &@4); fixpos($$, $2); /*% ripper: until!($:2, $:3) %*/ } @@ -11667,23 +11667,27 @@ rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_n } static rb_node_while_t * -rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc) +rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *closing_loc) { rb_node_while_t *n = NODE_NEWNODE(NODE_WHILE, rb_node_while_t, loc); n->nd_cond = nd_cond; n->nd_body = nd_body; n->nd_state = nd_state; + n->keyword_loc = *keyword_loc; + n->closing_loc = *closing_loc; return n; } static rb_node_until_t * -rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc) +rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *closing_loc) { rb_node_until_t *n = NODE_NEWNODE(NODE_UNTIL, rb_node_until_t, loc); n->nd_cond = nd_cond; n->nd_body = nd_body; n->nd_state = nd_state; + n->keyword_loc = *keyword_loc; + n->closing_loc = *closing_loc; return n; } @@ -15528,7 +15532,7 @@ parser_append_options(struct parser_params *p, NODE *node) irs = list_append(p, irs, NEW_HASH(chomp, LOC)); } - node = NEW_WHILE((NODE *)NEW_FCALL(idGets, irs, LOC), node, 1, LOC); + node = NEW_WHILE((NODE *)NEW_FCALL(idGets, irs, LOC), node, 1, LOC, &NULL_LOC, &NULL_LOC); } return node; diff --git a/rubyparser.h b/rubyparser.h index 5728844827..fe134c0bb7 100644 --- a/rubyparser.h +++ b/rubyparser.h @@ -323,6 +323,8 @@ typedef struct RNode_LOOP { struct RNode *nd_cond; struct RNode *nd_body; long nd_state; + rb_code_location_t keyword_loc; + rb_code_location_t closing_loc; } rb_node_while_t, rb_node_until_t; typedef struct RNode_ITER { diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb index 8ecd384d58..8fcd2415a5 100644 --- a/test/ruby/test_ast.rb +++ b/test/ruby/test_ast.rb @@ -1380,6 +1380,22 @@ dummy assert_locations(node.children[-1].children[1].locations, [[1, 8, 1, 22], [1, 8, 1, 12], [1, 15, 1, 19]]) end + def test_while_locations + node = RubyVM::AbstractSyntaxTree.parse("while cond do 1 end") + assert_locations(node.children[-1].locations, [[1, 0, 1, 19], [1, 0, 1, 5], [1, 16, 1, 19]]) + + node = RubyVM::AbstractSyntaxTree.parse("1 while 2") + assert_locations(node.children[-1].locations, [[1, 0, 1, 9], [1, 2, 1, 7], nil]) + end + + def test_until_locations + node = RubyVM::AbstractSyntaxTree.parse("until cond do 1 end") + assert_locations(node.children[-1].locations, [[1, 0, 1, 19], [1, 0, 1, 5], [1, 16, 1, 19]]) + + node = RubyVM::AbstractSyntaxTree.parse("1 until 2") + assert_locations(node.children[-1].locations, [[1, 0, 1, 9], [1, 2, 1, 7], nil]) + end + private def assert_locations(locations, expected) ary = locations.map {|loc| loc && [loc.first_lineno, loc.first_column, loc.last_lineno, loc.last_column] } |