Following my previous question, I’ve decided to use the kotlin.script.experimental.api.*
instead of the JSR api.
Basically what I am trying to do is the following:
- I’ve developed a library (DSL) that allows json transformations on a given input (basically it can be used to transform a JSON from one format to another);
- I want to be able to run the DSL Transformation as scripts so I can dynamically change them, without the need of having the code compiled.
I’ve come-up with those solution at this point:
package net.andreinc.mapneat.scripting
import net.andreinc.mapneat.scripting.KotlinScriptRunner.evalScript
import org.apache.logging.log4j.kotlin.Logging
import kotlin.reflect.KClass
import kotlin.script.experimental.api.*
import kotlin.script.experimental.host.toScriptSource
import kotlin.script.experimental.jvm.dependenciesFromCurrentContext
import kotlin.script.experimental.jvm.jvm
import kotlin.script.experimental.jvmhost.BasicJvmScriptingHostdata class ProvidedProperty(val name: String, val type: KClass<>, val value: Any?) {
constructor(name: String, type: Class<>, value: Any?) : this(name, type.kotlin, value)
}object KotlinScriptRunner : Logging {
fun evalScript(scriptFile: SourceCode, props: List<ProvidedProperty>): ResultWithDiagnostics<EvaluationResult> { val compileConfig = ScriptCompilationConfiguration { jvm { dependenciesFromCurrentContext(wholeClasspath = true) defaultImports( "net.andreinc.mapneat.dsl.*", "net.andreinc.mapneat.operation.*" ) } providedProperties(*(props.map { it.name to KotlinType(it.type) }.toTypedArray())) } val evaluationConfig = ScriptEvaluationConfiguration { providedProperties(*(props.map { it.name to it.value }.toTypedArray())) } return BasicJvmScriptingHost().eval(scriptFile, compileConfig, evaluationConfig) }
}
fun main() {
val script1 = """ println(a) println(b) a+b """ val props1 = listOf( ProvidedProperty("a", Int::class, 2), ProvidedProperty("b", Int::class, 3) ) println(evalScript(script1.toScriptSource(), props1)) val script2 = """ println(c) json("{}") { "name" /= "Andrei" "value" /= c }.getPrettyString() """ val props2 = listOf( ProvidedProperty("c", Int::class, 3) ) println(evalScript(script2.toScriptSource(), props2))
}
If I run the previous code the output looks like this:
2
3
Success(value=EvaluationResult(returnValue=$$result: kotlin.Int = 5, configuration=kotlin.script.experimental.api.ScriptEvaluationConfiguration@6051e37e), reports=[DEBUG Loading modules: [java.se, jdk.accessibility, jdk.attach, jdk.compiler, jdk.dynalink, jdk.httpserver, jdk.jartool, jdk.javadoc, jdk.jconsole, jdk.jdi, jdk.jfr, jdk.jshell, jdk.jsobject, jdk.management, jdk.management.jfr, jdk.net, jdk.scripting.nashorn, jdk.sctp, jdk.security.auth, jdk.security.jgss, jdk.unsupported, jdk.unsupported.desktop, jdk.xml.dom, java.base, java.compiler, java.datatransfer, java.desktop, java.xml, java.instrument, java.logging, java.management, java.management.rmi, java.rmi, java.naming, java.net.http, java.prefs, java.scripting, java.security.jgss, java.security.sasl, java.sql, java.transaction.xa, java.sql.rowset, java.xml.crypto, jdk.internal.jvmstat, jdk.management.agent, jdk.jdwp.agent, jdk.internal.ed, jdk.internal.le, jdk.internal.opt], DEBUG Loading modules: [java.se, jdk.accessibility, jdk.attach, jdk.compiler, jdk.dynalink, jdk.httpserver, jdk.jartool, jdk.javadoc, jdk.jconsole, jdk.jdi, jdk.jfr, jdk.jshell, jdk.jsobject, jdk.management, jdk.management.jfr, jdk.net, jdk.scripting.nashorn, jdk.sctp, jdk.security.auth, jdk.security.jgss, jdk.unsupported, jdk.unsupported.desktop, jdk.xml.dom, java.base, java.compiler, java.datatransfer, java.desktop, java.xml, java.instrument, java.logging, java.management, java.management.rmi, java.rmi, java.naming, java.net.http, java.prefs, java.scripting, java.security.jgss, java.security.sasl, java.sql, java.transaction.xa, java.sql.rowset, java.xml.crypto, jdk.internal.jvmstat, jdk.management.agent, jdk.jdwp.agent, jdk.internal.ed, jdk.internal.le, jdk.internal.opt]])
3
15:55:14.160 [main] INFO net.andreinc.mapneat.dsl.MapNeat - Transformation(id=a87079e1-da2e-4d52-af7b-e95b0cfa5253, parentId=null) INPUT = {}
15:55:14.170 [main] INFO net.andreinc.mapneat.operation.Assign - (transformationId=a87079e1-da2e-4d52-af7b-e95b0cfa5253) "name" ASSIGN(/=) "Andrei"
Success(value=EvaluationResult(returnValue=java.lang.NoSuchMethodError: 'int Script.access$getC$p(Script)', configuration=kotlin.script.experimental.api.ScriptEvaluationConfiguration@3929b7f6), reports=[DEBUG Loading modules: [java.se, jdk.accessibility, jdk.attach, jdk.compiler, jdk.dynalink, jdk.httpserver, jdk.jartool, jdk.javadoc, jdk.jconsole, jdk.jdi, jdk.jfr, jdk.jshell, jdk.jsobject, jdk.management, jdk.management.jfr, jdk.net, jdk.scripting.nashorn, jdk.sctp, jdk.security.auth, jdk.security.jgss, jdk.unsupported, jdk.unsupported.desktop, jdk.xml.dom, java.base, java.compiler, java.datatransfer, java.desktop, java.xml, java.instrument, java.logging, java.management, java.management.rmi, java.rmi, java.naming, java.net.http, java.prefs, java.scripting, java.security.jgss, java.security.sasl, java.sql, java.transaction.xa, java.sql.rowset, java.xml.crypto, jdk.internal.jvmstat, jdk.management.agent, jdk.jdwp.agent, jdk.internal.ed, jdk.internal.le, jdk.internal.opt], DEBUG Loading modules: [java.se, jdk.accessibility, jdk.attach, jdk.compiler, jdk.dynalink, jdk.httpserver, jdk.jartool, jdk.javadoc, jdk.jconsole, jdk.jdi, jdk.jfr, jdk.jshell, jdk.jsobject, jdk.management, jdk.management.jfr, jdk.net, jdk.scripting.nashorn, jdk.sctp, jdk.security.auth, jdk.security.jgss, jdk.unsupported, jdk.unsupported.desktop, jdk.xml.dom, java.base, java.compiler, java.datatransfer, java.desktop, java.xml, java.instrument, java.logging, java.management, java.management.rmi, java.rmi, java.naming, java.net.http, java.prefs, java.scripting, java.security.jgss, java.security.sasl, java.sql, java.transaction.xa, java.sql.rowset, java.xml.crypto, jdk.internal.jvmstat, jdk.management.agent, jdk.jdwp.agent, jdk.internal.ed, jdk.internal.le, jdk.internal.opt]])
As you can for script1
from the evaluation result I can retrieve the last value (after computing a
+b
= 5
).
But for the second script I am encountering the following problem: Success(value=EvaluationResult(returnValue=java.lang.NoSuchMethodError: 'int Script.access$getC$p(Script)...and so on'
My question is:
- How can I retrieve the value from the second script ?
- Why it’s not working just like for the first script ? I have done something very similar in both cases.