mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Use NODE_CASE2 if case expressions don't exist
When NODE_WHEN is compiled by iseq_compile_each0, the node passed to compile_when is NODE_WHEN (not NODE_CASE). So we can not handle the location of NODE_CASE of case statements which don't have case expressions. e.g. : ``` case; when 1; foo; when 2; bar; else baz; end ``` This commit adds NODE_CASE2, and compiles it by iseq_compile_each0. * compile.c (compile_case): Does not call COMPILE_ when NODE_CASE does not have case expressions. * compile.c (compile_case2): Compile NODE_CASE2 by compile_case2. * compile.c (compile_when): Delete an obsoleted function. * compile.c (iseq_compile_each0): Compile NODE_CASE2. * ext/objspace/objspace.c (count_nodes): Add NODE_CASE2 case. * node.c (dump_node, rb_gc_mark_node): Add NODE_CASE2 case. * node.h (node_type): Add NODE_CASE2. * node.h (NEW_CASE2): Add a macro which generates NODE_CASE2. * parse.y: Generate NODE_CASE2 if case expressions don't exist. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60585 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
bb88b1aab8
commit
a09e175068
5 changed files with 22 additions and 12 deletions
19
compile.c
19
compile.c
|
@ -4406,10 +4406,6 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
|
|||
|
||||
rb_hash_tbl_raw(literals)->type = &cdhash_type;
|
||||
|
||||
if (node->nd_head == 0) {
|
||||
CHECK(COMPILE_(ret, "when", node->nd_body, popped));
|
||||
return COMPILE_OK;
|
||||
}
|
||||
CHECK(COMPILE(head, "case base", node->nd_head));
|
||||
|
||||
DECL_BRANCH_BASE(branches, nd_lineno(node), nd_column(node), "case");
|
||||
|
@ -4506,26 +4502,27 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
|
|||
}
|
||||
|
||||
static int
|
||||
compile_when(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_node, int popped)
|
||||
compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_node, int popped)
|
||||
{
|
||||
const NODE *vals;
|
||||
const NODE *val;
|
||||
const NODE *node = orig_node;
|
||||
const NODE *node = orig_node->nd_body;
|
||||
LABEL *endlabel;
|
||||
DECL_ANCHOR(body_seq);
|
||||
VALUE branches = 0;
|
||||
|
||||
DECL_BRANCH_BASE(branches, nd_line(node), nd_column(node), "case");
|
||||
DECL_BRANCH_BASE(branches, nd_lineno(orig_node), nd_column(orig_node), "case");
|
||||
|
||||
INIT_ANCHOR(body_seq);
|
||||
endlabel = NEW_LABEL(nd_line(node));
|
||||
|
||||
while (node && nd_type(node) == NODE_WHEN) {
|
||||
const int line = nd_line(node);
|
||||
const int lineno = nd_lineno(node);
|
||||
const int column = nd_column(node);
|
||||
LABEL *l1 = NEW_LABEL(line);
|
||||
ADD_LABEL(body_seq, l1);
|
||||
ADD_TRACE_BRANCH_COVERAGE(body_seq, node->nd_body ? nd_line(node->nd_body) : line, node->nd_body ? nd_column(node->nd_body) : column, "when", branches);
|
||||
ADD_TRACE_BRANCH_COVERAGE(body_seq, node->nd_body ? nd_lineno(node->nd_body) : lineno, node->nd_body ? nd_column(node->nd_body) : column, "when", branches);
|
||||
CHECK(COMPILE_(body_seq, "when", node->nd_body, popped));
|
||||
ADD_INSNL(body_seq, line, jump, endlabel);
|
||||
|
||||
|
@ -4557,7 +4554,7 @@ compile_when(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
|
|||
node = node->nd_next;
|
||||
}
|
||||
/* else */
|
||||
ADD_TRACE_BRANCH_COVERAGE(ret, node ? nd_line(node) : nd_line(orig_node), node ? nd_column(node) : nd_column(orig_node), "else", branches);
|
||||
ADD_TRACE_BRANCH_COVERAGE(ret, node ? nd_lineno(node) : nd_lineno(orig_node), node ? nd_column(node) : nd_column(orig_node), "else", branches);
|
||||
CHECK(COMPILE_(ret, "else", node, popped));
|
||||
ADD_INSNL(ret, nd_line(orig_node), jump, endlabel);
|
||||
|
||||
|
@ -5169,8 +5166,8 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
|
|||
case NODE_CASE:
|
||||
CHECK(compile_case(iseq, ret, node, popped));
|
||||
break;
|
||||
case NODE_WHEN:
|
||||
CHECK(compile_when(iseq, ret, node, popped));
|
||||
case NODE_CASE2:
|
||||
CHECK(compile_case2(iseq, ret, node, popped));
|
||||
break;
|
||||
case NODE_WHILE:
|
||||
case NODE_UNTIL:
|
||||
|
|
|
@ -376,6 +376,7 @@ count_nodes(int argc, VALUE *argv, VALUE os)
|
|||
COUNT_NODE(NODE_IF);
|
||||
COUNT_NODE(NODE_UNLESS);
|
||||
COUNT_NODE(NODE_CASE);
|
||||
COUNT_NODE(NODE_CASE2);
|
||||
COUNT_NODE(NODE_WHEN);
|
||||
COUNT_NODE(NODE_WHILE);
|
||||
COUNT_NODE(NODE_UNTIL);
|
||||
|
|
9
node.c
9
node.c
|
@ -219,6 +219,14 @@ dump_node(VALUE buf, VALUE indent, int comment, NODE *node)
|
|||
LAST_NODE;
|
||||
F_NODE(nd_body, "when clauses");
|
||||
return;
|
||||
case NODE_CASE2:
|
||||
ANN("case statement");
|
||||
ANN("format: case; [nd_body]; end");
|
||||
ANN("example: case; when 1; foo; when 2; bar; else baz; end");
|
||||
F_NODE(nd_head, "case expr");
|
||||
LAST_NODE;
|
||||
F_NODE(nd_body, "when clauses");
|
||||
return;
|
||||
|
||||
case NODE_WHEN:
|
||||
ANN("if statement");
|
||||
|
@ -1125,6 +1133,7 @@ rb_gc_mark_node(NODE *obj)
|
|||
case NODE_AND:
|
||||
case NODE_OR:
|
||||
case NODE_CASE:
|
||||
case NODE_CASE2:
|
||||
case NODE_SCLASS:
|
||||
case NODE_DOT2:
|
||||
case NODE_DOT3:
|
||||
|
|
3
node.h
3
node.h
|
@ -30,6 +30,8 @@ enum node_type {
|
|||
#define NODE_UNLESS NODE_UNLESS
|
||||
NODE_CASE,
|
||||
#define NODE_CASE NODE_CASE
|
||||
NODE_CASE2,
|
||||
#define NODE_CASE2 NODE_CASE2
|
||||
NODE_WHEN,
|
||||
#define NODE_WHEN NODE_WHEN
|
||||
NODE_WHILE,
|
||||
|
@ -355,6 +357,7 @@ typedef struct RNode {
|
|||
#define NEW_IF(c,t,e) NEW_NODE(NODE_IF,c,t,e)
|
||||
#define NEW_UNLESS(c,t,e) NEW_NODE(NODE_UNLESS,c,t,e)
|
||||
#define NEW_CASE(h,b) NEW_NODE(NODE_CASE,h,b,0)
|
||||
#define NEW_CASE2(h,b) NEW_NODE(NODE_CASE2,h,b,0)
|
||||
#define NEW_WHEN(c,t,e) NEW_NODE(NODE_WHEN,c,t,e)
|
||||
#define NEW_WHILE(c,b,n) NEW_NODE(NODE_WHILE,c,b,n)
|
||||
#define NEW_UNTIL(c,b,n) NEW_NODE(NODE_UNTIL,c,b,n)
|
||||
|
|
2
parse.y
2
parse.y
|
@ -2866,7 +2866,7 @@ primary : literal
|
|||
| k_case opt_terms case_body k_end
|
||||
{
|
||||
/*%%%*/
|
||||
$$ = NEW_CASE(0, $3);
|
||||
$$ = NEW_CASE2(0, $3);
|
||||
nd_set_line($3, $<num>1);
|
||||
nd_set_lineno($$, @1.first_line);
|
||||
nd_set_column($$, @1.first_column);
|
||||
|
|
Loading…
Reference in a new issue