Add support for passing custom parameters to script

This commit is contained in:
2020-03-15 00:12:43 +01:00
parent 4ce35ce34c
commit 88b841bb98
5 changed files with 52 additions and 22 deletions

View File

@@ -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<out Any>, val stringifier: (Any) -> String) {
enum class DataType(private val kotlinType: KClass<out Any>, val stringifier: (Any) -> String) {
INT(Int::class, { it.toString() }),
FLOAT(Float::class, { it.toString() }),
STRING(String::class, { it.toString() }),

View File

@@ -41,6 +41,20 @@ data class Value(val type: DataType, val value: Any, val properties: Map<String,
return Value(DataType.INT, value)
}
fun wrap(obj: Any): Value {
return when(obj) {
is Unit -> 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<Any>).map { wrap(it) })
is Map<*, *> -> map((obj as Map<Any, Any>).map { (k, v) -> wrap(k) to wrap(v) }.toMap())
else -> throw ShouldNeverReachThisLineException()
}
}
fun float(value: Float): Value {
return Value(
DataType.FLOAT,

View File

@@ -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<String>): 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)
}
}
}

View File

@@ -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<ModulesPrintMode?>(null)
val code by parser.storing("-c", "--code", help = "inline code to be executed").default<String?>(null)
val file by parser.positional("SOURCE", help = "file with SMNP language code to be executed") { File(this) }.default<File?>(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<String?>(null)
val file by parser.positional(
"SOURCE",
help = "file with SMNP language code to be executed"
) { File(this) }.default<File?>(null)
}

View File

@@ -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<String>, printTokens: Boolean, printAst: Boolean, dryRun: Boolean): Environment {
private fun run(lines: List<String>, 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<String>, printTokens: Boolean, printAst: Boolean, dryRun: Boolean): Environment {
val environment = createEnvironment()
private fun tryToRun(lines: List<String>, 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)