diff --git a/docs/samples/сумма_ряда.lyng.md b/docs/samples/сумма_ряда.lyng.md index b270005..0606e23 100644 --- a/docs/samples/сумма_ряда.lyng.md +++ b/docs/samples/сумма_ряда.lyng.md @@ -48,6 +48,7 @@ $$ \ln(1+x)=x-{\dfrac {x^{2}}{2}}+{\dfrac {x^{3}}{3}}-\cdots =\sum \limits _{n=0 } assert( почти_равны( 0.0005, 0.000501 ) ) -Во многих случаях вычисление $n+1$ члена значительно проще cчитается от предыдущего члена, в нашем случае это можно было бы записать через итератор, что мы вскоре добавим. +Во многих случаях вычисление $n+1$ члена значительно проще cчитается от предыдущего члена, в нашем случае это можно было бы записать через итератор, см [Iterable] и `flow` в [parallelism]. -(продолжение следует) +[Iterable]: ../Iterable.md +[parallelism]: ../parallelism.md diff --git a/docs/tutorial.md b/docs/tutorial.md index da148ad..9c517ac 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -1259,7 +1259,19 @@ String literal could be multiline: "Hello World" -though multiline literals is yet work in progress. +In this case, it will be passed literally ot "hello\n World". But, if there are +several lines with common left indent, it will be removed, also, forst and last lines, +if blank, will be removed too, for example: + + println(" + This is a multiline text. + This is a second line. + ") + >>> This is a multiline text. + >>> This is a second line. + >>> void + +- as expected, empty lines and common indent were removed. It is much like kotlin's `""" ... """.trimIndent()` technique, but simpler ;) # Built-in functions diff --git a/lynglib/build.gradle.kts b/lynglib/build.gradle.kts index 76bf224..58a331f 100644 --- a/lynglib/build.gradle.kts +++ b/lynglib/build.gradle.kts @@ -4,7 +4,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.dsl.JvmTarget group = "net.sergeych" -version = "0.8.4-SNAPSHOT" +version = "0.8.5-SNAPSHOT" buildscript { repositories { diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Parser.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Parser.kt index cb7cc00..10e8a68 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Parser.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Parser.kt @@ -375,6 +375,32 @@ private class Parser(fromPos: Pos) { private val currentChar: Char get() = pos.currentChar + private fun fixMultilineStringLiteral(source: String): String { + val sizes = mutableListOf() + val lines = source.lines().toMutableList() + if( lines.size == 0 ) return "" + if( lines[0].isBlank() ) lines.removeFirst() + if( lines.isEmpty()) return "" + if( lines.last().isBlank() ) lines.removeLast() + + val normalized = lines.map { l -> + if( l.isBlank() ) { + sizes.add(-1) + "" + } + else { + val margin = leftMargin(l) + sizes += margin + " ".repeat(margin) + l.trim() + } + } + val commonMargin = sizes.filter { it >= 0 }.min() + val fixed = if( commonMargin < 1 ) lines else normalized.map { + if( it.isBlank() ) "" else it.drop(commonMargin) + } + return fixed.joinToString("\n") + } + private fun loadStringToken(): Token { val start = currentPos @@ -383,6 +409,7 @@ private class Parser(fromPos: Pos) { // start = start.back() val sb = StringBuilder() + var newlineDetected = false while (currentChar != '"') { if (pos.end) throw ScriptError(start, "unterminated string started there") when (currentChar) { @@ -397,6 +424,12 @@ private class Parser(fromPos: Pos) { } } + '\n', '\r'-> { + newlineDetected = true + sb.append(currentChar) + pos.advance() + } + else -> { sb.append(currentChar) pos.advance() @@ -404,7 +437,10 @@ private class Parser(fromPos: Pos) { } } pos.advance() - return Token(sb.toString(), start, Token.Type.STRING) + + val result = sb.toString().let { if( newlineDetected ) fixMultilineStringLiteral(it) else it } + + return Token(result, start, Token.Type.STRING) } /** diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/text_tools.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/text_tools.kt new file mode 100644 index 0000000..799420a --- /dev/null +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/text_tools.kt @@ -0,0 +1,13 @@ +package net.sergeych.lyng + +fun leftMargin(s: String): Int { + var cnt = 0 + for (c in s) { + when (c) { + ' ' -> cnt++ + '\t' -> cnt = (cnt / 4.0 + 0.9).toInt() * 4 + else -> break + } + } + return cnt +} diff --git a/lynglib/src/commonTest/kotlin/ScriptTest.kt b/lynglib/src/commonTest/kotlin/ScriptTest.kt index c9fd15a..8ab03c6 100644 --- a/lynglib/src/commonTest/kotlin/ScriptTest.kt +++ b/lynglib/src/commonTest/kotlin/ScriptTest.kt @@ -2794,4 +2794,45 @@ class ScriptTest { println(y.list) } + @Test + fun testMultilineStrings() = runTest { + assertEquals( + """ + This is a multiline text. + This is a second line. + """.trimIndent(), eval( + """ + " + This is a multiline text. + This is a second line. + " + """.trimIndent() + ).toString() + ) + assertEquals( + """ + This is a multiline text. + """.trimIndent(), eval( + """ + " + This is a multiline text. + " + """.trimIndent() + ).toString() + ) + assertEquals( + """ + + This is a multiline text. + """.trimIndent(), eval( + """ + " + + This is a multiline text. + " + """.trimIndent() + ).toString() + ) + } + } \ No newline at end of file diff --git a/lynglib/src/jvmTest/kotlin/BookTest.kt b/lynglib/src/jvmTest/kotlin/BookTest.kt index 3617060..fdf49a0 100644 --- a/lynglib/src/jvmTest/kotlin/BookTest.kt +++ b/lynglib/src/jvmTest/kotlin/BookTest.kt @@ -6,6 +6,7 @@ import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest import net.sergeych.lyng.Scope import net.sergeych.lyng.Script +import net.sergeych.lyng.leftMargin import net.sergeych.lyng.obj.ObjVoid import java.nio.file.Files import java.nio.file.Files.readAllLines @@ -16,18 +17,6 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.fail -fun leftMargin(s: String): Int { - var cnt = 0 - for (c in s) { - when (c) { - ' ' -> cnt++ - '\t' -> cnt = (cnt / 4.0 + 0.9).toInt() * 4 - else -> break - } - } - return cnt -} - data class DocTest( val fileName: String, val line: Int, diff --git a/settings.gradle.kts b/settings.gradle.kts index 5a5a11f..82fa23d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -13,7 +13,6 @@ dependencyResolutionManagement { maven("https://maven.universablockchain.com/") maven("https://gitea.sergeych.net/api/packages/SergeychWorks/maven") mavenLocal() - maven("https://gitea.sergeych.net/api/packages/SergeychWorks/maven") } }