- rewritten/fixed buildconfig

- less noise
- cosmetics in CLI tool
This commit is contained in:
Sergey Chernov 2025-06-10 02:06:03 +04:00
parent 323c455a50
commit fffa3d31bb
8 changed files with 103 additions and 86 deletions

View File

@ -1,6 +1,40 @@
# OO implementation in Lyng
Basic principles:
Short introduction
class Point(x,y) {
fun length() { sqrt(x*x + y*y) }
}
assert( Point is Class )
val p = Point(3,4)
assert(p is Point)
assertEquals(5, p.length())
// we can access the fields:
assert( p.x == 3 )
assert( p.y == 4 )
// we can assign new values to fields:
p.x = 1
p.y = 1
assertEquals(sqrt(2), p.length())
>>> void
Let's see in details. The statement `class Point(x,y)` creates a class,
with two field, which are mutable and publicly visible.`(x,y)` here
is the [argument list], same as when defining a function. All together creates a class with
a _constructor_ that requires two parameters for fields. So when creating it with
`Point(10, 20)` we say _calling Point constructor_ with these parameters.
Form now on `Point` is a class, it's type is `Class`, and we can create instances with it as in the
example above.
Class point has a _method_, or a _member function_ `length()` that uses its _fields_ `x` and `y` to
calculate the magnitude.
## Basic principles:
- Everything is an instance of some class
- Every class except Obj has at least one parent
@ -71,41 +105,6 @@ Regular methods are called on instances as usual `instance.method()`. The method
2. parents method: no guarantee but we enumerate parents in order of appearance;
3. possible extension methods (scoped)
# Defining a new class
The class is a some data record with named fields and fixed order, in fact. To define a class,
just Provide a name and a record like this:
// creating new class with main constructor
// with all fields public and mutable:
struct Point(x,y)
assert( Point is Class )
// now we can create instance
val p1 = Point(3,4)
// is is of the newly created type:
assert( p1 is Point )
// we can read and write its fields:
assert( p1.x == 3 )
assert( p1.y == 4 )
p1.y++
assert( p1.y == 5 )
>>> void
Let's see in details. The statement `struct Point(x,y)` creates a struct, or public class,
with two field, which are mutable and publicly visible, because it is _struct_. `(x,y)` here
is the [argument list], same as when defining a function. All together creates a class with
a _constructor_ that requires two parameters for fields. So when creating it with
`Point(10, 20)` we say _calling Point constructor_ with these parameters.
Such declaration is identical to `class Point(var x,var y)` which does exactly the same.
TBD
[argument list](declaring_arguments.md)

View File

@ -1,17 +1,40 @@
import com.codingfeline.buildkonfig.compiler.FieldSpec.Type.STRING
import com.vanniktech.maven.publish.SonatypeHost
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
group = "net.sergeych"
version = "0.2.1-SNAPSHOT"
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.0")
classpath("com.codingfeline.buildkonfig:buildkonfig-gradle-plugin:latest_version")
}
}
plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidLibrary)
alias(libs.plugins.vanniktech.mavenPublish)
kotlin("plugin.serialization") version "2.1.20"
id("com.codingfeline.buildkonfig") version "0.17.1"
}
group = "net.sergeych"
version = "0.2.0-SNAPSHOT"
buildkonfig {
packageName = "net.sergeych.lyng"
// objectName = "YourAwesomeConfig"
// exposeObjectWithName = "YourAwesomePublicConfig"
defaultConfigs {
buildConfigField(STRING, "bcprovider", "codingfeline")
buildConfigField(STRING, "version", version.toString())
}
}
kotlin {
jvm()
@ -110,40 +133,40 @@ mavenPublishing {
}
}
}
val projectVersion by project.extra(provider {
// Compute value lazily
(version as String)
})
val generateBuildConfig by tasks.registering {
// Declare outputs safely
val outputDir = layout.buildDirectory.dir("generated/buildConfig/commonMain/kotlin")
outputs.dir(outputDir)
val version = projectVersion.get()
// Inputs: Version is tracked as an input
inputs.property("version", version)
doLast {
val packageName = "net.sergeych.lyng.buildconfig"
val packagePath = packageName.replace('.', '/')
val buildConfigFile = outputDir.get().file("$packagePath/BuildConfig.kt").asFile
buildConfigFile.parentFile?.mkdirs()
buildConfigFile.writeText(
"""
|package $packageName
|
|object BuildConfig {
| const val VERSION = "$version"
|}
""".trimMargin()
)
}
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
dependsOn(generateBuildConfig)
}
//
//val projectVersion by project.extra(provider {
// // Compute value lazily
// (version as String)
//})
//
//val generateBuildConfig by tasks.registering {
// // Declare outputs safely
// val outputDir = layout.buildDirectory.dir("generated/buildConfig/commonMain/kotlin")
// outputs.dir(outputDir)
//
// val version = projectVersion.get()
//
// // Inputs: Version is tracked as an input
// inputs.property("version", version)
//
// doLast {
// val packageName = "net.sergeych.lyng.buildconfig"
// val packagePath = packageName.replace('.', '/')
// val buildConfigFile = outputDir.get().file("$packagePath/BuildConfig.kt").asFile
//
// buildConfigFile.parentFile?.mkdirs()
// buildConfigFile.writeText(
// """
// |package $packageName
// |
// |object BuildConfig {
// | const val VERSION = "$version"
// |}
// """.trimMargin()
// )
// }
//}
//
//tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
// dependsOn(generateBuildConfig)
//}

View File

@ -745,7 +745,6 @@ class Compiler(
bodyInit?.execute(this)
// export public
for( (name,record) in objects ) {
println("-- $name $record")
when(record.visibility) {
Visibility.Public -> {
thisObj.publicFields += name
@ -770,7 +769,6 @@ class Compiler(
f.name,
statement {
val context = (thisObj as ObjInstance).instanceContext
println("called on $thisObj")
context[f.name]?.value ?: raiseError("field is not initialized: ${f.name}")
},
true,

View File

@ -23,8 +23,6 @@ class ObjClass(
override suspend fun compareTo(context: Context, other: Obj): Int = if (other === this) 0 else -1
override suspend fun callOn(context: Context): Obj {
println("callOn $this constructing....")
println("on context: $context")
val instance = ObjInstance(this)
instance.instanceContext = context.copy(newThisObj = instance,args = context.args)
if (instanceConstructor != null) {

View File

@ -1,5 +1,4 @@
package net.sergeych.lyng
import net.sergeych.lyng.buildconfig.BuildConfig
val LyngVersion = BuildConfig.VERSION
val LyngVersion = BuildKonfig.version

View File

@ -24,7 +24,7 @@ val baseContext = Context().apply {
}
}
class LyngCLI(val launcher: (suspend () -> Unit) -> Unit) : CliktCommand() {
class Lyng(val launcher: (suspend () -> Unit) -> Unit) : CliktCommand() {
override val printHelpOnEmptyArgs = true

View File

@ -2,8 +2,8 @@ package net.sergeych.lyng_cli
import com.github.ajalt.clikt.core.main
import kotlinx.coroutines.runBlocking
import net.sergeych.LyngCLI
import net.sergeych.Lyng
fun main(args: Array<String>) {
LyngCLI({ runBlocking { it() } }).main(args)
Lyng({ runBlocking { it() } }).main(args)
}

View File

@ -1,7 +1,7 @@
import com.github.ajalt.clikt.core.main
import kotlinx.coroutines.runBlocking
import net.sergeych.LyngCLI
import net.sergeych.Lyng
fun main(args: Array<String>) {
LyngCLI( { runBlocking { it() } }).main(args)
Lyng( { runBlocking { it() } }).main(args)
}