working CLI tool, versioning support, etc
This commit is contained in:
		
							parent
							
								
									7b76b7d80f
								
							
						
					
					
						commit
						953e0e696b
					
				
							
								
								
									
										10
									
								
								bin/local_release
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										10
									
								
								bin/local_release
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
file=./lyng/build/bin/linuxX64/releaseExecutable/lyng.kexe
 | 
			
		||||
 | 
			
		||||
./gradlew :lyng:linkReleaseExecutableLinuxX64
 | 
			
		||||
strip $file
 | 
			
		||||
upx   $file
 | 
			
		||||
cp $file ~/bin/lyng
 | 
			
		||||
@ -16,4 +16,6 @@ fun naiveCountHappyNumbers() {
 | 
			
		||||
    count
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
assert( naiveCountHappyNumbers() == 55252 )
 | 
			
		||||
val found = naiveCountHappyNumbers()
 | 
			
		||||
println("Found happy numbers: "+found)
 | 
			
		||||
assert( found == 55252 )
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								docs/samples/helloworld.lyng
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								docs/samples/helloworld.lyng
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
 | 
			
		||||
println("Hello, world!");
 | 
			
		||||
@ -4,9 +4,11 @@ org.gradle.caching=true
 | 
			
		||||
org.gradle.configuration-cache=true
 | 
			
		||||
#Kotlin
 | 
			
		||||
kotlin.code.style=official
 | 
			
		||||
kotlin.js.compiler=ir
 | 
			
		||||
#MPP
 | 
			
		||||
kotlin.mpp.enableCInteropCommonization=true
 | 
			
		||||
#Android
 | 
			
		||||
android.useAndroidX=true
 | 
			
		||||
android.nonTransitiveRClass=true
 | 
			
		||||
 | 
			
		||||
# other
 | 
			
		||||
kotlin.native.cacheKind.linuxX64=none
 | 
			
		||||
@ -1,18 +1,24 @@
 | 
			
		||||
[versions]
 | 
			
		||||
agp = "8.5.2"
 | 
			
		||||
clikt = "5.0.3"
 | 
			
		||||
kotlin = "2.1.21"
 | 
			
		||||
android-minSdk = "24"
 | 
			
		||||
android-compileSdk = "34"
 | 
			
		||||
kotlinx-coroutines = "1.10.1"
 | 
			
		||||
mp_bintools = "0.1.12"
 | 
			
		||||
firebaseCrashlyticsBuildtools = "3.0.3"
 | 
			
		||||
okioVersion = "3.10.2"
 | 
			
		||||
 | 
			
		||||
[libraries]
 | 
			
		||||
clikt = { module = "com.github.ajalt.clikt:clikt", version.ref = "clikt" }
 | 
			
		||||
clikt-markdown = { module = "com.github.ajalt.clikt:clikt-markdown", version.ref = "clikt" }
 | 
			
		||||
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
 | 
			
		||||
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
 | 
			
		||||
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
 | 
			
		||||
mp_bintools = { module = "net.sergeych:mp_bintools", version.ref = "mp_bintools" }
 | 
			
		||||
firebase-crashlytics-buildtools = { group = "com.google.firebase", name = "firebase-crashlytics-buildtools", version.ref = "firebaseCrashlyticsBuildtools" }
 | 
			
		||||
okio = { module = "com.squareup.okio:okio", version.ref = "okioVersion" }
 | 
			
		||||
okio-fakefilesystem = { module = "com.squareup.okio:okio-fakefilesystem", version.ref = "okioVersion" }
 | 
			
		||||
 | 
			
		||||
[plugins]
 | 
			
		||||
androidLibrary = { id = "com.android.library", version.ref = "agp" }
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@ plugins {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
group = "net.sergeych"
 | 
			
		||||
version = "0.0.1-SNAPSHOT"
 | 
			
		||||
version = "0.0.5-SNAPSHOT"
 | 
			
		||||
 | 
			
		||||
kotlin {
 | 
			
		||||
    jvm()
 | 
			
		||||
@ -26,7 +26,7 @@ kotlin {
 | 
			
		||||
//    iosArm64()
 | 
			
		||||
//    iosSimulatorArm64()
 | 
			
		||||
    linuxX64()
 | 
			
		||||
    js(IR) {
 | 
			
		||||
    js {
 | 
			
		||||
        browser()
 | 
			
		||||
        nodejs()
 | 
			
		||||
    }
 | 
			
		||||
@ -44,12 +44,13 @@ kotlin {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val commonMain by getting {
 | 
			
		||||
            kotlin.srcDir("$buildDir/generated/buildConfig/commonMain/kotlin")
 | 
			
		||||
            dependencies {
 | 
			
		||||
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1")
 | 
			
		||||
                //put your multiplatform dependencies here
 | 
			
		||||
                implementation(libs.kotlinx.coroutines.core)
 | 
			
		||||
                implementation(libs.mp.bintools)
 | 
			
		||||
                implementation("net.sergeych:mp_stools:1.5.2")
 | 
			
		||||
                api(libs.kotlinx.coroutines.core)
 | 
			
		||||
                api(libs.mp.bintools)
 | 
			
		||||
                api("net.sergeych:mp_stools:1.5.2")
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        val commonTest by getting {
 | 
			
		||||
@ -109,3 +110,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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -21,7 +21,6 @@ class Script(
 | 
			
		||||
    companion object {
 | 
			
		||||
        val defaultContext: Context = Context().apply {
 | 
			
		||||
            addFn("println") {
 | 
			
		||||
                print("yn: ")
 | 
			
		||||
                for ((i, a) in args.withIndex()) {
 | 
			
		||||
                    if (i > 0) print(' ' + a.asStr.value)
 | 
			
		||||
                    else print(a.asStr.value)
 | 
			
		||||
 | 
			
		||||
@ -5,6 +5,7 @@ package net.sergeych.lyng
 | 
			
		||||
open class ScriptError(val pos: Pos, val errorMessage: String,cause: Throwable?=null) : Exception(
 | 
			
		||||
    """
 | 
			
		||||
        $pos: Error: $errorMessage
 | 
			
		||||
        
 | 
			
		||||
        ${pos.currentLine}
 | 
			
		||||
        ${"-".repeat(pos.column)}^
 | 
			
		||||
    """.trimIndent(),
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,5 @@
 | 
			
		||||
package net.sergeych.lyng
 | 
			
		||||
 | 
			
		||||
import net.sergeych.lyng.buildconfig.BuildConfig
 | 
			
		||||
 | 
			
		||||
val LyngVersion = BuildConfig.VERSION
 | 
			
		||||
@ -6,6 +6,12 @@ import kotlin.test.*
 | 
			
		||||
 | 
			
		||||
class ScriptTest {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun testVersion() {
 | 
			
		||||
        println("--------------------------------------------")
 | 
			
		||||
        println("version = ${LyngVersion}")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun parseNewlines() {
 | 
			
		||||
        fun check(expected: String, type: Token.Type, row: Int, col: Int, src: String, offset: Int = 0) {
 | 
			
		||||
 | 
			
		||||
@ -7,10 +7,20 @@ version = "unspecified"
 | 
			
		||||
 | 
			
		||||
repositories {
 | 
			
		||||
    mavenCentral()
 | 
			
		||||
    maven("https://maven.universablockchain.com/")
 | 
			
		||||
    maven("https://gitea.sergeych.net/api/packages/SergeychWorks/maven")
 | 
			
		||||
    mavenLocal()
 | 
			
		||||
    maven("https://gitea.sergeych.net/api/packages/SergeychWorks/maven")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
kotlin {
 | 
			
		||||
    jvm()
 | 
			
		||||
    jvm {
 | 
			
		||||
        binaries {
 | 
			
		||||
            executable {
 | 
			
		||||
                mainClass.set("net.sergeych.lyng_cli.MainKt")
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    linuxX64 {
 | 
			
		||||
        binaries {
 | 
			
		||||
            executable()
 | 
			
		||||
@ -18,11 +28,21 @@ kotlin {
 | 
			
		||||
    }
 | 
			
		||||
    sourceSets {
 | 
			
		||||
        val commonMain by getting {
 | 
			
		||||
            dependencies {
 | 
			
		||||
                implementation(project(":library"))
 | 
			
		||||
                implementation(libs.okio)
 | 
			
		||||
 | 
			
		||||
                implementation(libs.clikt)
 | 
			
		||||
 | 
			
		||||
                // optional support for rendering markdown in help messages
 | 
			
		||||
//                implementation(libs.clikt.markdown)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        val commonTest by getting {
 | 
			
		||||
            dependencies {
 | 
			
		||||
                implementation(kotlin("test-common"))
 | 
			
		||||
                implementation(kotlin("test-annotations-common"))
 | 
			
		||||
                implementation(libs.okio.fakefilesystem)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        val linuxX64Main by getting {
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,110 @@
 | 
			
		||||
package net.sergeych
 | 
			
		||||
 | 
			
		||||
import com.github.ajalt.clikt.core.CliktCommand
 | 
			
		||||
import com.github.ajalt.clikt.parameters.arguments.argument
 | 
			
		||||
import com.github.ajalt.clikt.parameters.arguments.multiple
 | 
			
		||||
import com.github.ajalt.clikt.parameters.arguments.optional
 | 
			
		||||
import com.github.ajalt.clikt.parameters.options.flag
 | 
			
		||||
import com.github.ajalt.clikt.parameters.options.option
 | 
			
		||||
import net.sergeych.lyng.*
 | 
			
		||||
import okio.FileSystem
 | 
			
		||||
import okio.Path.Companion.toPath
 | 
			
		||||
import okio.SYSTEM
 | 
			
		||||
import okio.buffer
 | 
			
		||||
import okio.use
 | 
			
		||||
 | 
			
		||||
// common code
 | 
			
		||||
 | 
			
		||||
fun commonCode() {
 | 
			
		||||
    println("Common code")
 | 
			
		||||
expect fun exit(code: Int)
 | 
			
		||||
 | 
			
		||||
val baseContext = Context().apply {
 | 
			
		||||
    addFn("exit") {
 | 
			
		||||
        exit(requireOnlyArg<ObjInt>().toInt())
 | 
			
		||||
        ObjVoid
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class LyngCLI(val launcher: (suspend () -> Unit) -> Unit) : CliktCommand() {
 | 
			
		||||
 | 
			
		||||
    override val printHelpOnEmptyArgs = true
 | 
			
		||||
 | 
			
		||||
    val version by option("-v", "--version", help = "Print version and exit").flag()
 | 
			
		||||
    val script by argument(help = "one or more scripts to execute").optional()
 | 
			
		||||
    val execute: String? by option(
 | 
			
		||||
        "-x", "--execute", help = """
 | 
			
		||||
        execute string <text>, the rest of command line is passed to Lyng as ARGV
 | 
			
		||||
        """.trimIndent()
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    val args by argument(help = "arguments for script").multiple()
 | 
			
		||||
 | 
			
		||||
    override fun help(context: com.github.ajalt.clikt.core.Context): String =
 | 
			
		||||
        """
 | 
			
		||||
            The Lyng script language interpreter, language version is $LyngVersion.
 | 
			
		||||
            
 | 
			
		||||
            Please refer form more information to the project site:
 | 
			
		||||
            https://gitea.sergeych.net/SergeychWorks/lyng
 | 
			
		||||
            
 | 
			
		||||
        """.trimIndent()
 | 
			
		||||
 | 
			
		||||
    override fun run() {
 | 
			
		||||
        when {
 | 
			
		||||
            version -> {
 | 
			
		||||
                println("Lyng language version ${LyngVersion}")
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            execute != null -> {
 | 
			
		||||
                val objargs = mutableListOf<String>()
 | 
			
		||||
                script?.let { objargs += it }
 | 
			
		||||
                objargs += args
 | 
			
		||||
                baseContext.addConst(
 | 
			
		||||
                    "ARGV", ObjList(
 | 
			
		||||
                        objargs.map { ObjString(it) }.toMutableList()
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
                launcher {
 | 
			
		||||
                    // there is no script name, it is a first argument instead:
 | 
			
		||||
                    processErrors {
 | 
			
		||||
                        baseContext.eval(execute!!)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            else -> {
 | 
			
		||||
                if (script == null) {
 | 
			
		||||
                    println(
 | 
			
		||||
                        """
 | 
			
		||||
                        
 | 
			
		||||
                        Error: no script specified.
 | 
			
		||||
                        
 | 
			
		||||
                    """.trimIndent()
 | 
			
		||||
                    )
 | 
			
		||||
                    echoFormattedHelp()
 | 
			
		||||
                } else {
 | 
			
		||||
                    baseContext.addConst("ARGV", ObjList(args.map { ObjString(it) }.toMutableList()))
 | 
			
		||||
                    launcher { executeFile(script!!) }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
suspend fun executeFile(fileName: String) {
 | 
			
		||||
    val text = FileSystem.SYSTEM.source(fileName.toPath()).use { fileSource ->
 | 
			
		||||
        fileSource.buffer().use { bs ->
 | 
			
		||||
            bs.readUtf8()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    processErrors {
 | 
			
		||||
        Compiler().compile(Source(fileName, text)).execute(baseContext)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
suspend fun processErrors(block: suspend () -> Unit) {
 | 
			
		||||
    try {
 | 
			
		||||
        block()
 | 
			
		||||
    }
 | 
			
		||||
    catch (e: ScriptError) {
 | 
			
		||||
        println("\nError executing the script:\n$e\n")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								lyng/src/jvmMain/kotlin/Common.jvm.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								lyng/src/jvmMain/kotlin/Common.jvm.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
package net.sergeych
 | 
			
		||||
 | 
			
		||||
import kotlin.system.exitProcess
 | 
			
		||||
 | 
			
		||||
actual fun exit(code: Int) {
 | 
			
		||||
    exitProcess(code)
 | 
			
		||||
}
 | 
			
		||||
@ -1,18 +0,0 @@
 | 
			
		||||
import net.sergeych.commonCode
 | 
			
		||||
 | 
			
		||||
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
 | 
			
		||||
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
 | 
			
		||||
fun main() {
 | 
			
		||||
    val name = "Kotlin"
 | 
			
		||||
    //TIP Press <shortcut actionId="ShowIntentionActions"/> with your caret at the highlighted text
 | 
			
		||||
    // to see how GIGA IDE suggests fixing it.
 | 
			
		||||
    println("Hello, native " + name + "!")
 | 
			
		||||
 | 
			
		||||
    commonCode()
 | 
			
		||||
 | 
			
		||||
    for (i in 1..5) {
 | 
			
		||||
        //TIP Press <shortcut actionId="Debug"/> to start debugging your code. We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
 | 
			
		||||
        // for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.
 | 
			
		||||
        println("i = $i")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								lyng/src/jvmMain/kotlin/net/sergeych/lyng_cli/Main.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								lyng/src/jvmMain/kotlin/net/sergeych/lyng_cli/Main.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
package net.sergeych.lyng_cli
 | 
			
		||||
 | 
			
		||||
import com.github.ajalt.clikt.core.main
 | 
			
		||||
import kotlinx.coroutines.runBlocking
 | 
			
		||||
import net.sergeych.LyngCLI
 | 
			
		||||
 | 
			
		||||
fun main(args: Array<String>) {
 | 
			
		||||
    LyngCLI({ runBlocking { it() } }).main(args)
 | 
			
		||||
}
 | 
			
		||||
@ -1,18 +1,7 @@
 | 
			
		||||
import net.sergeych.commonCode
 | 
			
		||||
import com.github.ajalt.clikt.core.main
 | 
			
		||||
import kotlinx.coroutines.runBlocking
 | 
			
		||||
import net.sergeych.LyngCLI
 | 
			
		||||
 | 
			
		||||
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
 | 
			
		||||
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
 | 
			
		||||
fun main() {
 | 
			
		||||
    val name = "Kotlin"
 | 
			
		||||
    //TIP Press <shortcut actionId="ShowIntentionActions"/> with your caret at the highlighted text
 | 
			
		||||
    // to see how GIGA IDE suggests fixing it.
 | 
			
		||||
    println("Hello, native " + name + "!")
 | 
			
		||||
 | 
			
		||||
    commonCode()
 | 
			
		||||
 | 
			
		||||
    for (i in 1..5) {
 | 
			
		||||
        //TIP Press <shortcut actionId="Debug"/> to start debugging your code. We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
 | 
			
		||||
        // for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.
 | 
			
		||||
        println("i = $i")
 | 
			
		||||
    }
 | 
			
		||||
fun main(args: Array<String>) {
 | 
			
		||||
    LyngCLI( { runBlocking { it() } }).main(args)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								lyng/src/nativeMain/kotlin/Common.native.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								lyng/src/nativeMain/kotlin/Common.native.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
package net.sergeych
 | 
			
		||||
 | 
			
		||||
import kotlin.system.exitProcess
 | 
			
		||||
 | 
			
		||||
actual fun exit(code: Int) {
 | 
			
		||||
    exitProcess(code)
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user