From 88b841bb9863fe667e3ebb536bca4537f43cfa59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Sun, 15 Mar 2020 00:12:43 +0100 Subject: [PATCH] Add support for passing custom parameters to script --- .../io/smnp/type/enumeration/DataType.kt | 2 +- .../main/kotlin/io/smnp/type/model/Value.kt | 14 +++++++++++ app/src/main/kotlin/io/smnp/SMNP.kt | 16 ++++++++----- .../io/smnp/cli/model/entity/Arguments.kt | 19 ++++++++++++++- .../io/smnp/interpreter/DefaultInterpreter.kt | 23 ++++++++----------- 5 files changed, 52 insertions(+), 22 deletions(-) diff --git a/api/src/main/kotlin/io/smnp/type/enumeration/DataType.kt b/api/src/main/kotlin/io/smnp/type/enumeration/DataType.kt index 0bad182..5fdfc39 100644 --- a/api/src/main/kotlin/io/smnp/type/enumeration/DataType.kt +++ b/api/src/main/kotlin/io/smnp/type/enumeration/DataType.kt @@ -4,7 +4,7 @@ import io.smnp.data.entity.Note import io.smnp.type.model.Value import kotlin.reflect.KClass -enum class DataType(val kotlinType: KClass, val stringifier: (Any) -> String) { +enum class DataType(private val kotlinType: KClass, val stringifier: (Any) -> String) { INT(Int::class, { it.toString() }), FLOAT(Float::class, { it.toString() }), STRING(String::class, { it.toString() }), diff --git a/api/src/main/kotlin/io/smnp/type/model/Value.kt b/api/src/main/kotlin/io/smnp/type/model/Value.kt index e35afa1..61bdd0b 100644 --- a/api/src/main/kotlin/io/smnp/type/model/Value.kt +++ b/api/src/main/kotlin/io/smnp/type/model/Value.kt @@ -41,6 +41,20 @@ data class Value(val type: DataType, val value: Any, val properties: Map void() + is Int -> int(obj) + is Float -> float(obj) + is Boolean -> bool(obj) + is String -> string(obj) + is Note -> note(obj) + is List<*> -> list((obj as List).map { wrap(it) }) + is Map<*, *> -> map((obj as Map).map { (k, v) -> wrap(k) to wrap(v) }.toMap()) + else -> throw ShouldNeverReachThisLineException() + } + } + fun float(value: Float): Value { return Value( DataType.FLOAT, diff --git a/app/src/main/kotlin/io/smnp/SMNP.kt b/app/src/main/kotlin/io/smnp/SMNP.kt index 19ec089..ba9a365 100644 --- a/app/src/main/kotlin/io/smnp/SMNP.kt +++ b/app/src/main/kotlin/io/smnp/SMNP.kt @@ -7,22 +7,26 @@ import io.smnp.cli.model.enumeration.ModulesPrintMode import io.smnp.environment.DefaultEnvironment import io.smnp.ext.DefaultModuleRegistry import io.smnp.interpreter.DefaultInterpreter +import io.smnp.type.model.Value fun main(args: Array): Unit = mainBody { ArgParser(args).parseInto(::Arguments).run { val interpreter = DefaultInterpreter() + val environment = DefaultEnvironment() + + environment.setVariable("__param__", Value.wrap(parameters.toMap())) when { - file != null -> interpreter.run(file!!, printTokens, printAst, dryRun) - code != null -> interpreter.run(code!!, printTokens, printAst, dryRun) + file != null -> interpreter.run(file!!, environment, printTokens, printAst, dryRun) + code != null -> interpreter.run(code!!, environment, printTokens, printAst, dryRun) else -> null - }?.let { it as DefaultEnvironment }?.let { environment -> + }?.let { it as DefaultEnvironment }?.let { disposedEnvironment -> if(loadedModules != null) { println("Loaded modules:") when (loadedModules) { - ModulesPrintMode.LIST -> environment.modules.forEach { println(it) } - ModulesPrintMode.TREE -> environment.printModules(false) - ModulesPrintMode.CONTENT -> environment.printModules(true) + ModulesPrintMode.LIST -> disposedEnvironment.modules.forEach { println(it) } + ModulesPrintMode.TREE -> disposedEnvironment.printModules(false) + ModulesPrintMode.CONTENT -> disposedEnvironment.printModules(true) } } } diff --git a/app/src/main/kotlin/io/smnp/cli/model/entity/Arguments.kt b/app/src/main/kotlin/io/smnp/cli/model/entity/Arguments.kt index 28a09cb..1b0a30c 100644 --- a/app/src/main/kotlin/io/smnp/cli/model/entity/Arguments.kt +++ b/app/src/main/kotlin/io/smnp/cli/model/entity/Arguments.kt @@ -17,6 +17,23 @@ class Arguments(parser: ArgParser) { "prints loaded modules as list of canonical names of each one. The 'tree' option organises modules into the tree model " + "and then prints them. The 'content' option is the same as tree, however, prints also contained functions and methods." ) { ModulesPrintMode.valueOf(this.toUpperCase()) }.default(null) + val parameters by parser.adding( + "-P", "--parameter", help = "define parameter to be consumed in script. Default syntax for parameter " + + "is 'key=value' (whitespaces around '=' are not allowed). In this case value will be of string type. " + + "However, it is also possible to pass parameter without any value. In this case, value will be of bool type. " + + "The parameters are available through global-accessible variable of map type and of '__param__' name." + ) { + this.split("=").let { + when (it.size) { + 1 -> it[0] to true + else -> it[0] to it.subList(1, it.size).joinToString("=") + } + } + } + val code by parser.storing("-c", "--code", help = "inline code to be executed").default(null) - val file by parser.positional("SOURCE", help = "file with SMNP language code to be executed") { File(this) }.default(null) + val file by parser.positional( + "SOURCE", + help = "file with SMNP language code to be executed" + ) { File(this) }.default(null) } \ No newline at end of file diff --git a/app/src/main/kotlin/io/smnp/interpreter/DefaultInterpreter.kt b/app/src/main/kotlin/io/smnp/interpreter/DefaultInterpreter.kt index 7a64545..83106c3 100644 --- a/app/src/main/kotlin/io/smnp/interpreter/DefaultInterpreter.kt +++ b/app/src/main/kotlin/io/smnp/interpreter/DefaultInterpreter.kt @@ -18,17 +18,18 @@ class DefaultInterpreter : Interpreter { fun run( code: String, + environment: Environment = DefaultEnvironment(), printTokens: Boolean = false, printAst: Boolean = false, dryRun: Boolean = false ): Environment { val lines = code.split("\n") - return run(lines, printTokens, printAst, dryRun) + return run(lines, environment, printTokens, printAst, dryRun) } - private fun run(lines: List, printTokens: Boolean, printAst: Boolean, dryRun: Boolean): Environment { + private fun run(lines: List, environment: Environment, printTokens: Boolean, printAst: Boolean, dryRun: Boolean): Environment { try { - return tryToRun(lines, printTokens, printAst, dryRun) + return tryToRun(lines, environment, printTokens, printAst, dryRun) } catch (e: SmnpException) { printError(e) exitProcess(1) @@ -40,8 +41,9 @@ class DefaultInterpreter : Interpreter { err.println(e.message) } - private fun tryToRun(lines: List, printTokens: Boolean, printAst: Boolean, dryRun: Boolean): Environment { - val environment = createEnvironment() + private fun tryToRun(lines: List, environment: Environment, printTokens: Boolean, printAst: Boolean, dryRun: Boolean): Environment { + environment.loadModule("smnp.lang") + val tokens = tokenizer.tokenize(lines) val ast = parser.parse(tokens) @@ -59,16 +61,9 @@ class DefaultInterpreter : Interpreter { return environment } - private fun createEnvironment(): Environment { - val environment = DefaultEnvironment() - environment.loadModule("smnp.lang") - - return environment - } - - fun run(file: File, printTokens: Boolean = false, printAst: Boolean = false, dryRun: Boolean = false): Environment { + fun run(file: File, environment: Environment = DefaultEnvironment(), printTokens: Boolean = false, printAst: Boolean = false, dryRun: Boolean = false): Environment { val lines = file.readLines() - return run(lines, printTokens, printAst, dryRun) + return run(lines, environment, printTokens, printAst, dryRun) } override fun run(code: String) = run(code, printTokens = false, printAst = false, dryRun = false)