Add REPL interfaces to scripting API
This commit is contained in:
@@ -22,7 +22,15 @@ object ScriptEvaluationEnvironmentParams {
|
|||||||
|
|
||||||
typealias ScriptEvaluationEnvironment = ChainedPropertyBag
|
typealias ScriptEvaluationEnvironment = ChainedPropertyBag
|
||||||
|
|
||||||
data class EvaluationResult(val returnValue: Any?, val environment: ScriptEvaluationEnvironment)
|
sealed class ResultValue {
|
||||||
|
class Value(val name: String, val value: Any?, val type: String) : ResultValue() {
|
||||||
|
override fun toString(): String = "$name: $type = $value"
|
||||||
|
}
|
||||||
|
|
||||||
|
object Unit : ResultValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
data class EvaluationResult(val returnValue: ResultValue, val environment: ScriptEvaluationEnvironment)
|
||||||
|
|
||||||
interface ScriptEvaluator {
|
interface ScriptEvaluator {
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import kotlin.script.experimental.api.*
|
|||||||
|
|
||||||
abstract class BasicScriptingHost(
|
abstract class BasicScriptingHost(
|
||||||
val compiler: ScriptCompiler,
|
val compiler: ScriptCompiler,
|
||||||
// TODO: does it belong here or to the definition?
|
|
||||||
val evaluator: ScriptEvaluator
|
val evaluator: ScriptEvaluator
|
||||||
) {
|
) {
|
||||||
open fun <T> runInCoroutineContext(block: suspend CoroutineScope.() -> T): T = runBlocking { block() }
|
open fun <T> runInCoroutineContext(block: suspend CoroutineScope.() -> T): T = runBlocking { block() }
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kotlin.script.experimental.repl
|
||||||
|
|
||||||
|
import kotlin.script.experimental.api.*
|
||||||
|
|
||||||
|
interface ReplSnippetChecker {
|
||||||
|
|
||||||
|
suspend operator fun invoke(
|
||||||
|
snippet: ReplSnippetSource,
|
||||||
|
state: ReplStageState<*>,
|
||||||
|
scriptDefinition: ScriptDefinition,
|
||||||
|
additionalConfiguration: ScriptCompileConfiguration? = null // overrides properties from definition
|
||||||
|
): ResultWithDiagnostics<Unit>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ReplSnippetCompiler {
|
||||||
|
|
||||||
|
suspend operator fun invoke(
|
||||||
|
snippet: ReplSnippetSource,
|
||||||
|
state: ReplStageState<*>,
|
||||||
|
scriptDefinition: ScriptDefinition,
|
||||||
|
additionalConfiguration: ScriptCompileConfiguration? = null // overrides properties from definition
|
||||||
|
): ResultWithDiagnostics<CompiledReplSnippet<*>>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CompiledReplSnippet<ScriptBase : Any> : CompiledScript<ScriptBase>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kotlin.script.experimental.repl
|
||||||
|
|
||||||
|
import kotlin.script.experimental.api.ScriptSource
|
||||||
|
|
||||||
|
interface ReplSnippetSource : ScriptSource, ReplSnippetId
|
||||||
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kotlin.script.experimental.repl
|
||||||
|
|
||||||
|
import kotlin.script.experimental.api.EvaluationResult
|
||||||
|
import kotlin.script.experimental.api.ResultWithDiagnostics
|
||||||
|
import kotlin.script.experimental.util.ChainedPropertyBag
|
||||||
|
|
||||||
|
|
||||||
|
object ReplEvaluationEnvironmentParams {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias ReplEvaluationEnvironment = ChainedPropertyBag
|
||||||
|
|
||||||
|
interface ReplSnippetEvaluator {
|
||||||
|
|
||||||
|
suspend operator fun invoke(
|
||||||
|
compiledSnippet: CompiledReplSnippet<*>,
|
||||||
|
replEvaluationEnvironment: ReplEvaluationEnvironment
|
||||||
|
): ResultWithDiagnostics<EvaluationResult>
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kotlin.script.experimental.repl
|
||||||
|
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
|
import kotlin.concurrent.read
|
||||||
|
import kotlin.concurrent.write
|
||||||
|
|
||||||
|
const val REPL_CODE_LINE_FIRST_NO = 1
|
||||||
|
const val REPL_CODE_LINE_FIRST_GEN = 1
|
||||||
|
|
||||||
|
interface ReplSnippetId : Comparable<ReplSnippetId> {
|
||||||
|
val no: Int
|
||||||
|
val generation: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ReplHistoryRecord<out T>(val id: ReplSnippetId, val item: T)
|
||||||
|
|
||||||
|
interface IReplStageHistory<T> : List<ReplHistoryRecord<T>> {
|
||||||
|
|
||||||
|
fun peek(): ReplHistoryRecord<T>? = lock.read { lastOrNull() }
|
||||||
|
|
||||||
|
fun push(id: ReplSnippetId, item: T)
|
||||||
|
|
||||||
|
fun pop(): ReplHistoryRecord<T>?
|
||||||
|
|
||||||
|
fun verifiedPop(id: ReplSnippetId): ReplHistoryRecord<T>? = lock.write {
|
||||||
|
if (lastOrNull()?.id == id) pop()
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reset(): Iterable<ReplSnippetId>
|
||||||
|
|
||||||
|
fun resetTo(id: ReplSnippetId): Iterable<ReplSnippetId>
|
||||||
|
|
||||||
|
val lock: ReentrantReadWriteLock
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ReplStageState<T> {
|
||||||
|
val history: IReplStageHistory<T>
|
||||||
|
|
||||||
|
val lock: ReentrantReadWriteLock
|
||||||
|
|
||||||
|
val currentGeneration: Int
|
||||||
|
|
||||||
|
fun getNextLineNo(): Int =
|
||||||
|
history.peek()?.id?.no?.let { it + 1 } ?: REPL_CODE_LINE_FIRST_NO // TODO: it should be more robust downstream (e.g. use atomic)
|
||||||
|
|
||||||
|
fun <StateT : ReplStageState<*>> asState(target: Class<out StateT>): StateT =
|
||||||
|
if (target.isAssignableFrom(this::class.java)) this as StateT
|
||||||
|
else throw IllegalArgumentException("$this is not an expected instance of IReplStageState")
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kotlin.script.experimental.repl
|
||||||
|
|
||||||
|
import kotlinx.coroutines.experimental.CoroutineScope
|
||||||
|
import kotlinx.coroutines.experimental.runBlocking
|
||||||
|
import kotlin.script.experimental.api.EvaluationResult
|
||||||
|
import kotlin.script.experimental.api.ResultWithDiagnostics
|
||||||
|
import kotlin.script.experimental.api.ScriptCompileConfiguration
|
||||||
|
import kotlin.script.experimental.api.ScriptDefinition
|
||||||
|
import kotlin.script.experimental.util.ChainedPropertyBag
|
||||||
|
import kotlin.script.experimental.util.typedKey
|
||||||
|
|
||||||
|
interface ReplCommandProcessor {
|
||||||
|
suspend operator fun invoke(
|
||||||
|
command: String,
|
||||||
|
state: ReplStageState<*>
|
||||||
|
): ResultWithDiagnostics<EvaluationResult>
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ReplCommand(val commandName: String, val processor: ReplCommandProcessor)
|
||||||
|
|
||||||
|
object ReplHostEnvironmentParams {
|
||||||
|
|
||||||
|
val replCommands by typedKey<List<ReplCommand>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias ReplHostEnvironment = ChainedPropertyBag
|
||||||
|
|
||||||
|
abstract class ReplHost(
|
||||||
|
val environment: ReplHostEnvironment,
|
||||||
|
val checker: ReplSnippetChecker,
|
||||||
|
val compiler: ReplSnippetCompiler,
|
||||||
|
val evaluator: ReplSnippetEvaluator
|
||||||
|
) {
|
||||||
|
open fun <T> runInCoroutineContext(block: suspend CoroutineScope.() -> T): T = runBlocking { block() }
|
||||||
|
|
||||||
|
abstract fun eval(
|
||||||
|
snippet: ReplSnippetSource,
|
||||||
|
state: ReplStageState<*>,
|
||||||
|
scriptDefinition: ScriptDefinition,
|
||||||
|
additionalConfiguration: ScriptCompileConfiguration? = null, // overrides properties from definition
|
||||||
|
replEvaluationEnvironment: ReplEvaluationEnvironment
|
||||||
|
): ResultWithDiagnostics<EvaluationResult>
|
||||||
|
}
|
||||||
+2
-1
@@ -32,7 +32,8 @@ open class BasicJvmScriptEvaluator() : ScriptEvaluator {
|
|||||||
scriptObject.getConstructor(Array<Any>::class.java).newInstance(receivers.toTypedArray())
|
scriptObject.getConstructor(Array<Any>::class.java).newInstance(receivers.toTypedArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultWithDiagnostics.Success(EvaluationResult(instance, scriptEvaluationEnvironment))
|
// TODO: fix result value
|
||||||
|
ResultWithDiagnostics.Success(EvaluationResult(ResultValue.Value("", instance, ""), scriptEvaluationEnvironment))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user