Improve string concatentation & string templates code generation

Reuse StringBuilder instances for nested subexpressions.
(NB StringBuilder instance for string template with a string
concatenation inside an expression entry, such as `"${"a" + "b"}"`,
will not be reused, although that doesn't seem to be a real-life issue).

 #KT-18558 Fixed Target versions 1.1.4
 #KT-13682 Fixed Target versions 1.1.4

Join adjacent strings literals, escaped strings, and constant values
(in a language version that supports const val inlining).
Use StringBuilder#append(char) for single-character constants
(e.g., " " in "$a $b").

 #KT-17280 Fixed Target versions 1.1.4
 #KT-15235 Fixed Target versions 1.1.4
This commit is contained in:
Dmitry Petrov
2017-06-20 17:08:39 +03:00
parent ae71833a12
commit a84c2a6f31
17 changed files with 313 additions and 56 deletions
+4 -5
View File
@@ -1,5 +1,4 @@
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
object A {
const val a: String = "$"
@@ -7,7 +6,7 @@ object A {
const val c = 10000
val bNonConst = "1234$a"
val bNullable: String = "1234$a"
val bNullable: String? = "1234$a"
}
object B {
@@ -16,7 +15,7 @@ object B {
const val c = 10000
val bNonConst = "1234$a"
val bNullable: String = "1234$a"
val bNullable: String? = "1234$a"
}
fun box(): String {
@@ -26,8 +25,8 @@ fun box(): String {
if (A.c !== B.c) return "Fail 3: A.c !== B.c"
if (A.bNonConst === B.bNonConst) return "Fail 5: A.bNonConst == B.bNonConst"
if (A.bNullable === B.bNullable) return "Fail 6: A.bNullable == B.bNullable"
if (A.bNonConst !== B.bNonConst) return "Fail 4: A.bNonConst !== B.bNonConst"
if (A.bNullable !== B.bNullable) return "Fail 5: A.bNullable !== B.bNullable"
return "OK"
}
+34
View File
@@ -0,0 +1,34 @@
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
// LANGUAGE_VERSION: 1.0
object A {
const val a: String = "$"
const val b = "1234$a"
const val c = 10000
val bNonConst = "1234$a"
val bNullable: String? = "1234$a"
}
object B {
const val a: String = "$"
const val b = "1234$a"
const val c = 10000
val bNonConst = "1234$a"
val bNullable: String? = "1234$a"
}
fun box(): String {
if (A.a !== B.a) return "Fail 1: A.a !== B.a"
if (A.b !== B.b) return "Fail 2: A.b !== B.b"
if (A.c !== B.c) return "Fail 3: A.c !== B.c"
if (A.bNonConst === B.bNonConst) return "Fail 4: A.bNonConst === B.bNonConst"
if (A.bNullable === B.bNullable) return "Fail 5: A.bNullable === B.bNullable"
return "OK"
}
@@ -0,0 +1,25 @@
// WITH_RUNTIME
import kotlin.test.assertEquals
const val constTrue = true
const val const42 = 42
const val constPiF = 3.14F
const val constPi = 3.1415926358
const val constString = "string"
fun box(): String {
assertEquals("true", "$constTrue")
assertEquals("42", "$const42")
assertEquals("3.14", "$constPiF")
assertEquals("3.1415926358", "$constPi")
assertEquals("string", "$constString")
assertEquals(constPi.toString(), "$constPi")
assertEquals((constPi * constPi).toString(), "${constPi * constPi}")
assertEquals("null", "${null}")
assertEquals("42", "${42}")
return "OK"
}
+21
View File
@@ -0,0 +1,21 @@
// WITH_RUNTIME
import kotlin.test.assertEquals
fun test1(s1: String, s2: String, s3: String) =
(s1 + s2) + s3
fun test2(s1: String, s2: String, s3: String) =
s1 + (s2 + s3)
fun test3(s1: String, s2: String, s3: String) =
"s1: $s1; " +
"s2: $s2; " +
"s3: $s3"
fun box(): String {
assertEquals("123", test1("1", "2", "3"))
assertEquals("123", test2("1", "2", "3"))
assertEquals("s1: 1; s2: 2; s3: 3", test3("1", "2", "3"))
return "OK"
}
+1 -1
View File
@@ -6,5 +6,5 @@ class kt5016 {
}
// 0 INVOKEVIRTUAL java/lang/StringBuilder.append \(Ljava/lang/Object;\)Ljava/lang/StringBuilder
// 3 INVOKEVIRTUAL java/lang/StringBuilder.append \(Ljava/lang/String;\)Ljava/lang/StringBuilder
// 2 INVOKEVIRTUAL java/lang/StringBuilder.append \(Ljava/lang/String;\)Ljava/lang/StringBuilder
// 1 INVOKEVIRTUAL java/lang/StringBuilder.toString
+1 -1
View File
@@ -6,6 +6,6 @@ class kt5016int {
}
// 0 INVOKEVIRTUAL java/lang/StringBuilder.append \(Ljava/lang/Object;\)Ljava/lang/StringBuilder
// 2 INVOKEVIRTUAL java/lang/StringBuilder.append \(Ljava/lang/String;\)Ljava/lang/StringBuilder
// 1 INVOKEVIRTUAL java/lang/StringBuilder.append \(Ljava/lang/String;\)Ljava/lang/StringBuilder
// 1 INVOKEVIRTUAL java/lang/StringBuilder.append \(I\)Ljava/lang/StringBuilder
// 1 INVOKEVIRTUAL java/lang/StringBuilder.toString
+1 -1
View File
@@ -6,5 +6,5 @@ class kt5016intOrNull {
}
// 1 INVOKEVIRTUAL java/lang/StringBuilder.append \(Ljava/lang/Object;\)Ljava/lang/StringBuilder
// 2 INVOKEVIRTUAL java/lang/StringBuilder.append \(Ljava/lang/String;\)Ljava/lang/StringBuilder
// 1 INVOKEVIRTUAL java/lang/StringBuilder.append \(Ljava/lang/String;\)Ljava/lang/StringBuilder
// 1 INVOKEVIRTUAL java/lang/StringBuilder.toString
@@ -0,0 +1,4 @@
val c = 1
fun foo() = "a\"($c)\"d"
// 3 INVOKEVIRTUAL java/lang/StringBuilder.append
@@ -0,0 +1,15 @@
fun test1(s1: String, s2: String, s3: String) =
(s1 + s2) + s3
fun test2(s1: String, s2: String, s3: String) =
s1 + (s2 + s3)
fun test3(s1: String, s2: String, s3: String, s4: String) =
((s1 + s2) + ((s3 + s4)))
fun test4(s1: String, s2: String, s3: String) =
"s1: $s1; " +
"s2: $s2; " +
"s3: $s3"
// 4 NEW java/lang/StringBuilder