[前][次][番号順一覧][スレッド一覧]

ruby-changes:48471

From: yui-knk <ko1@a...>
Date: Tue, 31 Oct 2017 09:46:37 +0900 (JST)
Subject: [ruby-changes:48471] yui-knk:r60585 (trunk): Use NODE_CASE2 if case expressions don't exist

yui-knk	2017-10-31 09:46:30 +0900 (Tue, 31 Oct 2017)

  New Revision: 60585

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=60585

  Log:
    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.

  Modified files:
    trunk/compile.c
    trunk/ext/objspace/objspace.c
    trunk/node.c
    trunk/node.h
    trunk/parse.y
Index: parse.y
===================================================================
--- parse.y	(revision 60584)
+++ parse.y	(revision 60585)
@@ -2866,7 +2866,7 @@ primary		: literal https://github.com/ruby/ruby/blob/trunk/parse.y#L2866
 		| 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);
Index: ext/objspace/objspace.c
===================================================================
--- ext/objspace/objspace.c	(revision 60584)
+++ ext/objspace/objspace.c	(revision 60585)
@@ -376,6 +376,7 @@ count_nodes(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/ext/objspace/objspace.c#L376
 		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);
Index: node.c
===================================================================
--- node.c	(revision 60584)
+++ node.c	(revision 60585)
@@ -219,6 +219,14 @@ dump_node(VALUE buf, VALUE indent, int c https://github.com/ruby/ruby/blob/trunk/node.c#L219
 	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) https://github.com/ruby/ruby/blob/trunk/node.c#L1133
       case NODE_AND:
       case NODE_OR:
       case NODE_CASE:
+      case NODE_CASE2:
       case NODE_SCLASS:
       case NODE_DOT2:
       case NODE_DOT3:
Index: compile.c
===================================================================
--- compile.c	(revision 60584)
+++ compile.c	(revision 60585)
@@ -4406,10 +4406,6 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHO https://github.com/ruby/ruby/blob/trunk/compile.c#L4406
 
     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_ANCHO https://github.com/ruby/ruby/blob/trunk/compile.c#L4502
 }
 
 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_ANCHO https://github.com/ruby/ruby/blob/trunk/compile.c#L4554
 	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 https://github.com/ruby/ruby/blob/trunk/compile.c#L5166
       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:
Index: node.h
===================================================================
--- node.h	(revision 60584)
+++ node.h	(revision 60585)
@@ -30,6 +30,8 @@ enum node_type { https://github.com/ruby/ruby/blob/trunk/node.h#L30
 #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 { https://github.com/ruby/ruby/blob/trunk/node.h#L357
 #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)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]