summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compile.c19
-rw-r--r--ext/objspace/objspace.c1
-rw-r--r--node.c9
-rw-r--r--node.h3
-rw-r--r--parse.y2
5 files changed, 22 insertions, 12 deletions
diff --git a/compile.c b/compile.c
index b0a67e49ce..c5d079c904 100644
--- a/compile.c
+++ b/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:
diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c
index 38995d4af6..acc6231777 100644
--- a/ext/objspace/objspace.c
+++ b/ext/objspace/objspace.c
@@ -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);
diff --git a/node.c b/node.c
index c671884094..d64b6d282f 100644
--- a/node.c
+++ b/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:
diff --git a/node.h b/node.h
index 04434cb48c..29eaafd3ec 100644
--- a/node.h
+++ b/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)
diff --git a/parse.y b/parse.y
index d83586cf57..3607b5c39c 100644
--- a/parse.y
+++ b/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);