Add a handler for providing evaluation context for scripts

use it on refinement.
also some refactoring on context class and around
This commit is contained in:
Ilya Chernikov
2019-07-25 11:46:17 +02:00
parent 2a5c4a2409
commit 288fdc0952
5 changed files with 63 additions and 6 deletions
@@ -36,7 +36,7 @@ open class ScriptCompilationConfiguration(baseConfigurations: Iterable<ScriptCom
object Default : ScriptCompilationConfiguration()
override fun toString(): String {
return "ScriptCompilationConfiguration($providedProperties)"
return "ScriptCompilationConfiguration($properties)"
}
}
@@ -106,11 +106,43 @@ interface ScriptEvaluationContextDataKeys
* The container for script evaluation context data
* Used for transferring data to the evaluation refinement callbacks
*/
class ScriptEvaluationContextData(properties: Map<PropertiesCollection.Key<*>, Any>) : PropertiesCollection(properties) {
class ScriptEvaluationContextData(baseConfigurations: Iterable<ScriptEvaluationContextData>, body: Builder.() -> Unit = {}) :
PropertiesCollection(Builder(baseConfigurations).apply(body).data) {
constructor(body: Builder.() -> Unit = {}) : this(emptyList(), body)
constructor(
vararg baseConfigurations: ScriptEvaluationContextData, body: Builder.() -> Unit = {}
) : this(baseConfigurations.asIterable(), body)
class Builder internal constructor(baseConfigurations: Iterable<ScriptEvaluationContextData>) :
ScriptEvaluationContextDataKeys,
PropertiesCollection.Builder(baseConfigurations)
companion object : ScriptEvaluationContextDataKeys
}
/**
* optimized alternative to the constructor with multiple base configurations
*/
fun merge(vararg contexts: ScriptEvaluationContextData?): ScriptEvaluationContextData? {
val nonEmpty = ArrayList<ScriptEvaluationContextData>()
for (data in contexts) {
if (data != null && !data.isEmpty()) {
nonEmpty.add(data)
}
}
return when {
nonEmpty.isEmpty() -> null
nonEmpty.size == 1 -> nonEmpty.first()
else -> ScriptEvaluationContextData(nonEmpty.asIterable())
}
}
/**
* Command line arguments of the current process, could be provided by an evaluation host
*/
val ScriptEvaluationContextDataKeys.commandLineArgs by PropertiesCollection.key<List<String>>()
/**
* The facade to the script data for evaluation configuration refinement callbacks
*/
@@ -10,6 +10,7 @@ package kotlin.script.experimental.api
import java.io.Serializable
import kotlin.reflect.KClass
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.script.experimental.host.getEvaluationContext
import kotlin.script.experimental.util.PropertiesCollection
interface ScriptEvaluationConfigurationKeys
@@ -121,10 +122,14 @@ data class RefineEvaluationConfigurationData(
fun ScriptEvaluationConfiguration.refineBeforeEvaluation(
script: CompiledScript<*>,
contextData: ScriptEvaluationContextData? = null
): ResultWithDiagnostics<ScriptEvaluationConfiguration> =
simpleRefineImpl(ScriptEvaluationConfiguration.refineConfigurationBeforeEvaluate) { config, refineData ->
refineData.handler.invoke(ScriptEvaluationConfigurationRefinementContext(script, config, contextData))
): ResultWithDiagnostics<ScriptEvaluationConfiguration> {
val hostConfiguration = get(ScriptEvaluationConfiguration.hostConfiguration)
val baseContextData = hostConfiguration?.get(ScriptingHostConfiguration.getEvaluationContext)?.invoke(hostConfiguration)
val actualContextData = merge(baseContextData, contextData)
return simpleRefineImpl(ScriptEvaluationConfiguration.refineConfigurationBeforeEvaluate) { config, refineData ->
refineData.handler.invoke(ScriptEvaluationConfigurationRefinementContext(script, config, actualContextData))
}
}
/**
* The script evaluation result value