migrated stdlib to separate .lyng files and added build-time generation of Kotlin constants. reduced noise in plugin
This commit is contained in:
1 parent
6a6de83972
commit
b8f27c7a18
6 files changed
+334
-183
No files matched your search
@@ -110,6 +110,72 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Build-time generation of stdlib text from .lyng files into a Kotlin constant ----
|
||||
// The .lyng source of the stdlib lives here (module-relative path):
|
||||
val lyngStdlibDir = layout.projectDirectory.dir("stdlib/lyng")
|
||||
// The generated Kotlin source will be placed here and added to commonMain sources:
|
||||
val generatedLyngStdlibDir = layout.buildDirectory.dir("generated/source/lyngStdlib/commonMain/kotlin")
|
||||
|
||||
val generateLyngStdlib by tasks.registering {
|
||||
group = "build"
|
||||
description = "Generate Kotlin source with embedded lyng stdlib text"
|
||||
inputs.dir(lyngStdlibDir)
|
||||
outputs.dir(generatedLyngStdlibDir)
|
||||
// Simpler: opt out of configuration cache for this ad-hoc generator task
|
||||
notCompatibleWithConfigurationCache("Uses dynamic file IO in doLast; trivial generator")
|
||||
|
||||
doLast {
|
||||
val targetPkg = "net.sergeych.lyng.stdlib_included"
|
||||
val targetDir = generatedLyngStdlibDir.get().asFile.resolve(targetPkg.replace('.', '/'))
|
||||
targetDir.mkdirs()
|
||||
|
||||
val files = lyngStdlibDir.asFileTree.matching { include("**/*.lyng") }.files.sortedBy { it.name }
|
||||
val content = if (files.isEmpty()) "" else buildString {
|
||||
files.forEachIndexed { idx, f ->
|
||||
val text = f.readText()
|
||||
if (idx > 0) append("\n\n")
|
||||
append(text)
|
||||
}
|
||||
}
|
||||
|
||||
// Emit as a regular quoted Kotlin string to avoid triple-quote edge cases
|
||||
fun escapeForQuoted(s: String): String = buildString {
|
||||
for (ch in s) when (ch) {
|
||||
'\\' -> append("\\\\")
|
||||
'"' -> append("\\\"")
|
||||
'\n' -> append("\\n")
|
||||
'\r' -> {} // drop CR
|
||||
'\t' -> append("\\t")
|
||||
else -> append(ch)
|
||||
}
|
||||
}
|
||||
val body = escapeForQuoted(content)
|
||||
|
||||
val sb = StringBuilder()
|
||||
sb.append("package ").append(targetPkg).append("\n\n")
|
||||
sb.append("@Suppress(\"Unused\", \"MemberVisibilityCanBePrivate\")\n")
|
||||
sb.append("internal val rootLyng = \"")
|
||||
sb.append(body)
|
||||
sb.append("\"\n")
|
||||
|
||||
targetDir.resolve("root_lyng.generated.kt").writeText(sb.toString())
|
||||
}
|
||||
}
|
||||
|
||||
// Add the generated directory to commonMain sources
|
||||
kotlin.sourceSets.named("commonMain") {
|
||||
kotlin.srcDir(generatedLyngStdlibDir)
|
||||
}
|
||||
|
||||
// Ensure ALL Kotlin compilations (all targets/variants) depend on the generator
|
||||
kotlin.targets.configureEach {
|
||||
compilations.configureEach {
|
||||
compileTaskProvider.configure {
|
||||
dependsOn(generateLyngStdlib)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "org.jetbrains.kotlinx.multiplatform.library.template"
|
||||
compileSdk = libs.versions.android.compileSdk.get().toInt()
|
||||
|
||||
@@ -14,182 +14,11 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
package net.sergeych.lyng.stdlib_included
|
||||
|
||||
internal val rootLyng = """
|
||||
package lyng.stdlib
|
||||
|
||||
fun cached(builder) {
|
||||
var calculated = false
|
||||
var value = null
|
||||
{
|
||||
if( !calculated ) {
|
||||
value = builder()
|
||||
calculated = true
|
||||
}
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
fun Iterable.filter(predicate) {
|
||||
val list = this
|
||||
flow {
|
||||
for( item in list ) {
|
||||
if( predicate(item) ) {ln
|
||||
emit(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Iterable.drop(n) {
|
||||
var cnt = 0
|
||||
filter { cnt++ >= n }
|
||||
}
|
||||
|
||||
fun Iterable.first() {
|
||||
val i = iterator()
|
||||
if( !i.hasNext() ) throw NoSuchElementException()
|
||||
i.next().also { i.cancelIteration() }
|
||||
}
|
||||
|
||||
fun Iterable.last() {
|
||||
var found = false
|
||||
var element = null
|
||||
for( i in this ) {
|
||||
element = i
|
||||
found = true
|
||||
}
|
||||
if( !found ) throw NoSuchElementException()
|
||||
element
|
||||
}
|
||||
|
||||
fun Iterable.dropLast(n) {
|
||||
val list = this
|
||||
val buffer = RingBuffer(n)
|
||||
flow {
|
||||
for( item in list ) {
|
||||
if( buffer.size == n )
|
||||
emit( buffer.first() )
|
||||
buffer += item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Iterable.takeLast(n) {
|
||||
val buffer = RingBuffer(n)
|
||||
for( item in this ) buffer += item
|
||||
buffer
|
||||
}
|
||||
|
||||
fun Iterable.joinToString(prefix=" ", transformer=null) {
|
||||
var result = null
|
||||
for( part in this ) {
|
||||
val transformed = transformer?(part)?.toString() ?: part.toString()
|
||||
if( result == null ) result = transformed
|
||||
else result += prefix + transformed
|
||||
}
|
||||
result ?: ""
|
||||
}
|
||||
|
||||
fun Iterable.any(predicate): Bool {
|
||||
for( i in this ) {
|
||||
if( predicate(i) )
|
||||
break true
|
||||
} else false
|
||||
}
|
||||
|
||||
fun Iterable.all(predicate): Bool {
|
||||
!any { !predicate(it) }
|
||||
}
|
||||
|
||||
fun Iterable.sum() {
|
||||
val i = iterator()
|
||||
if( i.hasNext() ) {
|
||||
var result = i.next()
|
||||
while( i.hasNext() ) result += i.next()
|
||||
result
|
||||
}
|
||||
else null
|
||||
}
|
||||
|
||||
fun Iterable.sumOf(f) {
|
||||
val i = iterator()
|
||||
if( i.hasNext() ) {
|
||||
var result = f(i.next())
|
||||
while( i.hasNext() ) result += f(i.next())
|
||||
result
|
||||
}
|
||||
else null
|
||||
}
|
||||
|
||||
fun Iterable.minOf( lambda ) {
|
||||
val i = iterator()
|
||||
var minimum = lambda( i.next() )
|
||||
while( i.hasNext() ) {
|
||||
val x = lambda(i.next())
|
||||
if( x < minimum ) minimum = x
|
||||
}
|
||||
minimum
|
||||
}
|
||||
|
||||
/*
|
||||
Return maximum value of the given function applied to elements of the collection.
|
||||
*/
|
||||
fun Iterable.maxOf( lambda ) {
|
||||
val i = iterator()
|
||||
var maximum = lambda( i.next() )
|
||||
while( i.hasNext() ) {
|
||||
val x = lambda(i.next())
|
||||
if( x > maximum ) maximum = x
|
||||
}
|
||||
maximum
|
||||
}
|
||||
|
||||
fun Iterable.sorted() {
|
||||
sortedWith { a, b -> a <=> b }
|
||||
}
|
||||
|
||||
fun Iterable.sortedBy(predicate) {
|
||||
sortedWith { a, b -> predicate(a) <=> predicate(b) }
|
||||
}
|
||||
|
||||
fun Iterable.shuffled() {
|
||||
toList().apply { shuffle() }
|
||||
}
|
||||
|
||||
fun List.toString() {
|
||||
"[" + joinToString(",") + "]"
|
||||
}
|
||||
|
||||
fun List.sortBy(predicate) {
|
||||
sortWith { a, b -> predicate(a) <=> predicate(b) }
|
||||
}
|
||||
|
||||
fun List.sort() {
|
||||
sortWith { a, b -> a <=> b }
|
||||
}
|
||||
|
||||
class StackTraceEntry(
|
||||
val sourceName: String,
|
||||
val line: Int,
|
||||
val column: Int,
|
||||
val sourceString: String
|
||||
) {
|
||||
fun toString() {
|
||||
"%s:%d:%d: %s"(sourceName, line, column, sourceString.trim())
|
||||
}
|
||||
}
|
||||
|
||||
fun Exception.printStackTrace() {
|
||||
println(this)
|
||||
for( entry in stackTrace() ) {
|
||||
println("\tat "+entry)
|
||||
}
|
||||
}
|
||||
|
||||
fun String.re() { Regex(this) }
|
||||
|
||||
|
||||
""".trimIndent()
|
||||
This file used to contain an embedded stdlib text literal. It is now generated at build time
|
||||
from .lyng sources into build/generated/.../root_lyng.generated.kt. The file is intentionally
|
||||
left without declarations to avoid duplication across targets.
|
||||
*/
|
||||
package net.sergeych.lyng.stdlib_included
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
package lyng.stdlib
|
||||
|
||||
fun cached(builder) {
|
||||
var calculated = false
|
||||
var value = null
|
||||
{
|
||||
if( !calculated ) {
|
||||
value = builder()
|
||||
calculated = true
|
||||
}
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
fun Iterable.filter(predicate) {
|
||||
val list = this
|
||||
flow {
|
||||
for( item in list ) {
|
||||
if( predicate(item) ) {ln
|
||||
emit(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Iterable.drop(n) {
|
||||
var cnt = 0
|
||||
filter { cnt++ >= n }
|
||||
}
|
||||
|
||||
fun Iterable.first() {
|
||||
val i = iterator()
|
||||
if( !i.hasNext() ) throw NoSuchElementException()
|
||||
i.next().also { i.cancelIteration() }
|
||||
}
|
||||
|
||||
fun Iterable.last() {
|
||||
var found = false
|
||||
var element = null
|
||||
for( i in this ) {
|
||||
element = i
|
||||
found = true
|
||||
}
|
||||
if( !found ) throw NoSuchElementException()
|
||||
element
|
||||
}
|
||||
|
||||
fun Iterable.dropLast(n) {
|
||||
val list = this
|
||||
val buffer = RingBuffer(n)
|
||||
flow {
|
||||
for( item in list ) {
|
||||
if( buffer.size == n )
|
||||
emit( buffer.first() )
|
||||
buffer += item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Iterable.takeLast(n) {
|
||||
val buffer = RingBuffer(n)
|
||||
for( item in this ) buffer += item
|
||||
buffer
|
||||
}
|
||||
|
||||
fun Iterable.joinToString(prefix=" ", transformer=null) {
|
||||
var result = null
|
||||
for( part in this ) {
|
||||
val transformed = transformer?(part)?.toString() ?: part.toString()
|
||||
if( result == null ) result = transformed
|
||||
else result += prefix + transformed
|
||||
}
|
||||
result ?: ""
|
||||
}
|
||||
|
||||
fun Iterable.any(predicate): Bool {
|
||||
for( i in this ) {
|
||||
if( predicate(i) )
|
||||
break true
|
||||
} else false
|
||||
}
|
||||
|
||||
fun Iterable.all(predicate): Bool {
|
||||
!any { !predicate(it) }
|
||||
}
|
||||
|
||||
fun Iterable.sum() {
|
||||
val i = iterator()
|
||||
if( i.hasNext() ) {
|
||||
var result = i.next()
|
||||
while( i.hasNext() ) result += i.next()
|
||||
result
|
||||
}
|
||||
else null
|
||||
}
|
||||
|
||||
fun Iterable.sumOf(f) {
|
||||
val i = iterator()
|
||||
if( i.hasNext() ) {
|
||||
var result = f(i.next())
|
||||
while( i.hasNext() ) result += f(i.next())
|
||||
result
|
||||
}
|
||||
else null
|
||||
}
|
||||
|
||||
fun Iterable.minOf( lambda ) {
|
||||
val i = iterator()
|
||||
var minimum = lambda( i.next() )
|
||||
while( i.hasNext() ) {
|
||||
val x = lambda(i.next())
|
||||
if( x < minimum ) minimum = x
|
||||
}
|
||||
minimum
|
||||
}
|
||||
|
||||
/*
|
||||
Return maximum value of the given function applied to elements of the collection.
|
||||
*/
|
||||
fun Iterable.maxOf( lambda ) {
|
||||
val i = iterator()
|
||||
var maximum = lambda( i.next() )
|
||||
while( i.hasNext() ) {
|
||||
val x = lambda(i.next())
|
||||
if( x > maximum ) maximum = x
|
||||
}
|
||||
maximum
|
||||
}
|
||||
|
||||
fun Iterable.sorted() {
|
||||
sortedWith { a, b -> a <=> b }
|
||||
}
|
||||
|
||||
fun Iterable.sortedBy(predicate) {
|
||||
sortedWith { a, b -> predicate(a) <=> predicate(b) }
|
||||
}
|
||||
|
||||
fun Iterable.shuffled() {
|
||||
toList().apply { shuffle() }
|
||||
}
|
||||
|
||||
fun List.toString() {
|
||||
"[" + joinToString(",") + "]"
|
||||
}
|
||||
|
||||
fun List.sortBy(predicate) {
|
||||
sortWith { a, b -> predicate(a) <=> predicate(b) }
|
||||
}
|
||||
|
||||
fun List.sort() {
|
||||
sortWith { a, b -> a <=> b }
|
||||
}
|
||||
|
||||
class StackTraceEntry(
|
||||
val sourceName: String,
|
||||
val line: Int,
|
||||
val column: Int,
|
||||
val sourceString: String
|
||||
) {
|
||||
fun toString() {
|
||||
"%s:%d:%d: %s"(sourceName, line, column, sourceString.trim())
|
||||
}
|
||||
}
|
||||
|
||||
fun Exception.printStackTrace() {
|
||||
println(this)
|
||||
for( entry in stackTrace() ) {
|
||||
println("\tat "+entry)
|
||||
}
|
||||
}
|
||||
|
||||
fun String.re() { Regex(this) }
|
||||
|
||||
|
||||
Reference in new issue
Block a user