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

ruby-changes:63219

From: Nobuyoshi <ko1@a...>
Date: Wed, 30 Sep 2020 23:49:56 +0900 (JST)
Subject: [ruby-changes:63219] 7b2bea42a2 (master): Unfreeze string-literal-only interpolated string-literal

https://git.ruby-lang.org/ruby.git/commit/?id=7b2bea42a2

From 7b2bea42a245f2e80b5d2700963fd6b143f6d6b8 Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Wed, 2 Sep 2020 23:12:22 +0900
Subject: Unfreeze string-literal-only interpolated string-literal

[Feature #17104]

diff --git a/ast.c b/ast.c
index 87c3665..2af0b3e 100644
--- a/ast.c
+++ b/ast.c
@@ -485,9 +485,15 @@ node_children(rb_ast_t *ast, const NODE *node) https://github.com/ruby/ruby/blob/trunk/ast.c#L485
       case NODE_DXSTR:
       case NODE_DREGX:
       case NODE_DSYM:
-        return rb_ary_new_from_args(3, node->nd_lit,
-                                    NEW_CHILD(ast, node->nd_next->nd_head),
-                                    NEW_CHILD(ast, node->nd_next->nd_next));
+        {
+            NODE *n = node->nd_next;
+            VALUE head = Qnil, next = Qnil;
+            if (n) {
+                head = NEW_CHILD(ast, n->nd_head);
+                next = NEW_CHILD(ast, n->nd_next);
+            }
+            return rb_ary_new_from_args(3, node->nd_lit, head, next);
+        }
       case NODE_EVSTR:
         return rb_ary_new_from_node_args(ast, 1, node->nd_body);
       case NODE_ARGSCAT:
diff --git a/compile.c b/compile.c
index 797a170..0d2d7fb 100644
--- a/compile.c
+++ b/compile.c
@@ -3828,8 +3828,16 @@ static int https://github.com/ruby/ruby/blob/trunk/compile.c#L3828
 compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node)
 {
     int cnt;
-    CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
-    ADD_INSN1(ret, nd_line(node), concatstrings, INT2FIX(cnt));
+    if (!node->nd_next) {
+        VALUE lit = rb_fstring(node->nd_lit);
+        const int line = (int)nd_line(node);
+        ADD_INSN1(ret, line, putstring, lit);
+        RB_OBJ_WRITTEN(iseq, Qundef, lit);
+    }
+    else {
+        CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
+        ADD_INSN1(ret, nd_line(node), concatstrings, INT2FIX(cnt));
+    }
     return COMPILE_OK;
 }
 
diff --git a/node.c b/node.c
index 7c291a8..9360437 100644
--- a/node.c
+++ b/node.c
@@ -741,6 +741,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) https://github.com/ruby/ruby/blob/trunk/node.c#L741
 	ANN("example: :\"foo#{ bar }baz\"");
       dlit:
 	F_LIT(nd_lit, "preceding string");
+	if (!node->nd_next) return;
 	F_NODE(nd_next->nd_head, "interpolation");
 	LAST_NODE;
 	F_NODE(nd_next->nd_next, "tailing strings");
diff --git a/parse.y b/parse.y
index 93bc2ef..f8441e8 100644
--- a/parse.y
+++ b/parse.y
@@ -9871,12 +9871,24 @@ literal_concat0(struct parser_params *p, VALUE head, VALUE tail) https://github.com/ruby/ruby/blob/trunk/parse.y#L9871
     return 1;
 }
 
+static VALUE
+string_literal_head(enum node_type htype, NODE *head)
+{
+    if (htype != NODE_DSTR) return Qfalse;
+    if (head->nd_next) {
+	head = head->nd_next->nd_end->nd_head;
+	if (!head || nd_type(head) != NODE_STR) return Qfalse;
+    }
+    const VALUE lit = head->nd_lit;
+    ASSUME(lit != Qfalse);
+    return lit;
+}
+
 /* concat two string literals */
 static NODE *
 literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *loc)
 {
     enum node_type htype;
-    NODE *headlast;
     VALUE lit;
 
     if (!head) return tail;
@@ -9899,10 +9911,8 @@ literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *l https://github.com/ruby/ruby/blob/trunk/parse.y#L9911
     }
     switch (nd_type(tail)) {
       case NODE_STR:
-	if (htype == NODE_DSTR && (headlast = head->nd_next->nd_end->nd_head) &&
-	    nd_type(headlast) == NODE_STR) {
+	if ((lit = string_literal_head(htype, head)) != Qfalse) {
 	    htype = NODE_STR;
-	    lit = headlast->nd_lit;
 	}
 	else {
 	    lit = head->nd_lit;
@@ -9932,13 +9942,16 @@ literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *l https://github.com/ruby/ruby/blob/trunk/parse.y#L9942
 	else if (NIL_P(tail->nd_lit)) {
 	  append:
 	    head->nd_alen += tail->nd_alen - 1;
-	    head->nd_next->nd_end->nd_next = tail->nd_next;
-	    head->nd_next->nd_end = tail->nd_next->nd_end;
+	    if (!head->nd_next) {
+		head->nd_next = tail->nd_next;
+	    }
+	    else if (tail->nd_next) {
+		head->nd_next->nd_end->nd_next = tail->nd_next;
+		head->nd_next->nd_end = tail->nd_next->nd_end;
+	    }
 	    rb_discard_node(p, tail);
 	}
-	else if (htype == NODE_DSTR && (headlast = head->nd_next->nd_end->nd_head) &&
-		 nd_type(headlast) == NODE_STR) {
-	    lit = headlast->nd_lit;
+	else if ((lit = string_literal_head(htype, head)) != Qfalse) {
 	    if (!literal_concat0(p, lit, tail->nd_lit))
 		goto error;
 	    tail->nd_lit = Qnil;
@@ -9976,7 +9989,9 @@ new_evstr(struct parser_params *p, NODE *node, const YYLTYPE *loc) https://github.com/ruby/ruby/blob/trunk/parse.y#L9989
 
     if (node) {
 	switch (nd_type(node)) {
-	  case NODE_STR: case NODE_DSTR: case NODE_EVSTR:
+	  case NODE_STR:
+	    nd_set_type(node, NODE_DSTR);
+	  case NODE_DSTR: case NODE_EVSTR:
 	    return node;
 	}
     }
@@ -10273,8 +10288,10 @@ new_regexp(struct parser_params *p, NODE *node, int options, const YYLTYPE *loc) https://github.com/ruby/ruby/blob/trunk/parse.y#L10288
 	node->nd_cflag = options & RE_OPTION_MASK;
 	if (!NIL_P(node->nd_lit)) reg_fragment_check(p, node->nd_lit, options);
 	for (list = (prev = node)->nd_next; list; list = list->nd_next) {
-	    if (nd_type(list->nd_head) == NODE_STR) {
-		VALUE tail = list->nd_head->nd_lit;
+	    NODE *frag = list->nd_head;
+	    enum node_type type = nd_type(frag);
+	    if (type == NODE_STR || (type == NODE_DSTR && !frag->nd_next)) {
+		VALUE tail = frag->nd_lit;
 		if (reg_fragment_check(p, tail, options) && prev && !NIL_P(prev->nd_lit)) {
 		    VALUE lit = prev == node ? prev->nd_lit : prev->nd_head->nd_lit;
 		    if (!literal_concat0(p, lit, tail)) {
diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb
index 7fb6268..51e3fd0 100644
--- a/test/ruby/test_iseq.rb
+++ b/test/ruby/test_iseq.rb
@@ -188,7 +188,7 @@ class TestISeq < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_iseq.rb#L188
     assert_predicate(s1, :frozen?)
     assert_predicate(s2, :frozen?)
     assert_not_predicate(s3, :frozen?)
-    assert_predicate(s4, :frozen?) # should probably not be frozen, but unrealistic code
+    assert_not_predicate(s4, :frozen?)
   end
 
   # Safe call chain is not optimized when Coverage is running.
-- 
cgit v0.10.2


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

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