Fix evaluation part of the scripting API - mostly renaming

This commit is contained in:
Ilya Chernikov
2018-08-31 13:36:56 +02:00
parent 539e0f4961
commit 1e85a26b62
4 changed files with 37 additions and 36 deletions
@@ -130,5 +130,5 @@ interface CompiledScript<out ScriptBase : Any> {
val compilationConfiguration: ScriptCompilationConfiguration
suspend fun instantiate(scriptEvaluationConfiguration: ScriptEvaluationConfiguration?): ResultWithDiagnostics<ScriptBase>
suspend fun getClass(scriptEvaluationConfiguration: ScriptEvaluationConfiguration?): ResultWithDiagnostics<KClass<*>>
}
@@ -20,7 +20,7 @@ class ScriptEvaluationConfiguration(baseEvaluationEnvironments: Iterable<ScriptE
) : this(baseConfigurations.asIterable(), body)
class Builder internal constructor(baseEvaluationEnvironments: Iterable<ScriptEvaluationConfiguration>) :
ScriptCompilationConfigurationKeys,
ScriptEvaluationConfigurationKeys,
PropertiesCollection.Builder(baseEvaluationEnvironments)
companion object : ScriptEvaluationConfigurationKeys
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.script.KotlinScriptDefinition
import org.jetbrains.kotlin.script.util.KotlinJars
import java.io.File
import java.net.URLClassLoader
import kotlin.reflect.KClass
import kotlin.script.experimental.api.*
import kotlin.script.experimental.dependencies.DependenciesResolver
import kotlin.script.experimental.host.ScriptingHostConfiguration
@@ -56,24 +57,22 @@ class KJvmCompiledScript<out ScriptBase : Any>(
private val scriptClassFQName: String
) : CompiledScript<ScriptBase> {
override suspend fun instantiate(scriptEvaluationConfiguration: ScriptEvaluationConfiguration?): ResultWithDiagnostics<ScriptBase> =
try {
val baseClassLoader = scriptEvaluationConfiguration?.get(JvmScriptEvaluationEnvironment.baseClassLoader)
?: Thread.currentThread().contextClassLoader
val dependencies = compilationConfiguration[ScriptCompilationConfiguration.dependencies]
?.flatMap { (it as? JvmDependency)?.classpath?.map { it.toURI().toURL() } ?: emptyList() }
// TODO: previous dependencies and classloaders should be taken into account here
val classLoaderWithDeps =
if (dependencies == null) baseClassLoader
else URLClassLoader(dependencies.toTypedArray(), baseClassLoader)
val classLoader = GeneratedClassLoader(generationState.factory, classLoaderWithDeps)
override suspend fun getClass(scriptEvaluationConfiguration: ScriptEvaluationConfiguration?): ResultWithDiagnostics<KClass<*>> = try {
val baseClassLoader = scriptEvaluationConfiguration?.get(JvmScriptEvaluationEnvironment.baseClassLoader)
?: Thread.currentThread().contextClassLoader
val dependencies = compilationConfiguration[ScriptCompilationConfiguration.dependencies]
?.flatMap { (it as? JvmDependency)?.classpath?.map { it.toURI().toURL() } ?: emptyList() }
// TODO: previous dependencies and classloaders should be taken into account here
val classLoaderWithDeps =
if (dependencies == null) baseClassLoader
else URLClassLoader(dependencies.toTypedArray(), baseClassLoader)
val classLoader = GeneratedClassLoader(generationState.factory, classLoaderWithDeps)
val clazz = classLoader.loadClass(scriptClassFQName)
(clazz as? ScriptBase)?.asSuccess()
?: ResultWithDiagnostics.Failure("Compiled class expected to be a subclass of the <ScriptBase>, but got ${clazz.javaClass.name}".asErrorDiagnostics())
} catch (e: Throwable) {
ResultWithDiagnostics.Failure(ScriptDiagnostic("Unable to instantiate class $scriptClassFQName", exception = e))
}
val clazz = classLoader.loadClass(scriptClassFQName).kotlin
clazz.asSuccess()
} catch (e: Throwable) {
ResultWithDiagnostics.Failure(ScriptDiagnostic("Unable to instantiate class $scriptClassFQName", exception = e))
}
}
class KJvmCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) : KJvmCompilerProxy {
@@ -26,30 +26,32 @@ open class BasicJvmScriptEvaluator : ScriptEvaluator {
scriptEvaluationConfiguration: ScriptEvaluationConfiguration?
): ResultWithDiagnostics<EvaluationResult> =
try {
val obj = compiledScript.instantiate(scriptEvaluationConfiguration)
when (obj) {
is ResultWithDiagnostics.Failure -> obj
val res = compiledScript.getClass(scriptEvaluationConfiguration)
when (res) {
is ResultWithDiagnostics.Failure -> res
is ResultWithDiagnostics.Success -> {
// in the future, when (if) we'll stop to compile everything into constructor
// run as SAM
// return res
val scriptObject = obj.value
if (scriptObject !is Class<*>)
ResultWithDiagnostics.Failure(ScriptDiagnostic("expecting class in this implementation, got ${scriptObject?.javaClass}"))
else {
val receivers = scriptEvaluationConfiguration?.get(ScriptEvaluationConfiguration.implicitReceivers)
val instance = if (receivers == null) {
scriptObject.getConstructor().newInstance()
} else {
scriptObject.getConstructor(Array<Any>::class.java).newInstance(receivers.toTypedArray())
}
// TODO: fix result value
ResultWithDiagnostics.Success(EvaluationResult(ResultValue.Value("", instance, ""), scriptEvaluationConfiguration))
val scriptClass = res.value
val args = ArrayList<Any?>()
scriptEvaluationConfiguration?.get(ScriptEvaluationConfiguration.contextVariables)?.forEach {
args.add(it.value)
}
scriptEvaluationConfiguration?.get(ScriptEvaluationConfiguration.implicitReceivers)?.let {
args.addAll(it)
}
scriptEvaluationConfiguration?.get(ScriptEvaluationConfiguration.constructorArgs)?.let {
args.addAll(it)
}
val ctor = scriptClass.java.constructors.first()
val instance = ctor.newInstance(*args.toArray())
// TODO: fix result value
ResultWithDiagnostics.Success(EvaluationResult(ResultValue.Value("", instance, ""), scriptEvaluationConfiguration))
}
}
} catch (e: Throwable) {
ResultWithDiagnostics.Failure(e.asDiagnostics())
ResultWithDiagnostics.Failure(e.asDiagnostics("Error evaluating script"))
}
}