Implement JSR-223 functionality on top of the "new" REPL
This commit is contained in:
+34
-10
@@ -33,19 +33,24 @@ class JvmReplEvaluator(
|
||||
invokeWrapper: InvokeWrapper?
|
||||
): ReplEvalResult = state.lock.write {
|
||||
val evalState = state.asState(JvmReplEvaluatorState::class.java)
|
||||
val history = evalState.history as ReplStageHistoryWithReplace
|
||||
val compiledScript = (compileResult.data as? KJvmCompiledScript<*>)
|
||||
?: return ReplEvalResult.Error.CompileTime("Unable to access compiled script: ${compileResult.data}")
|
||||
|
||||
val lastSnippetInstance = evalState.history.peek()?.item
|
||||
val lastSnippetInstance = history.peek()?.item
|
||||
val historyBeforeSnippet = history.previousItems(compileResult.lineId)
|
||||
val currentConfiguration = ScriptEvaluationConfiguration(baseScriptEvaluationConfiguration) {
|
||||
if (evalState.history.isNotEmpty()) {
|
||||
previousSnippets.put(evalState.history.map { it.item })
|
||||
if (historyBeforeSnippet.any()) {
|
||||
previousSnippets.put(historyBeforeSnippet.toList())
|
||||
}
|
||||
if (lastSnippetInstance != null) {
|
||||
jvm {
|
||||
baseClassLoader(lastSnippetInstance::class.java.classLoader)
|
||||
}
|
||||
}
|
||||
if (scriptArgs != null) {
|
||||
constructorArgs(*scriptArgs.scriptArgs)
|
||||
}
|
||||
}
|
||||
|
||||
val res = runBlocking { scriptEvaluator(compiledScript, currentConfiguration) }
|
||||
@@ -53,7 +58,7 @@ class JvmReplEvaluator(
|
||||
when (res) {
|
||||
is ResultWithDiagnostics.Success -> when (val retVal = res.value.returnValue) {
|
||||
is ResultValue.Value -> {
|
||||
evalState.history.push(compileResult.lineId, retVal.scriptInstance)
|
||||
history.replaceOrPush(compileResult.lineId, retVal.scriptInstance)
|
||||
// TODO: the latter check is temporary while the result is used to return the instance too
|
||||
if (retVal.type.isNotBlank())
|
||||
ReplEvalResult.ValueResult(retVal.name, retVal.value, retVal.type)
|
||||
@@ -61,12 +66,12 @@ class JvmReplEvaluator(
|
||||
ReplEvalResult.UnitResult()
|
||||
}
|
||||
is ResultValue.UnitValue -> {
|
||||
evalState.history.push(compileResult.lineId, retVal.scriptInstance)
|
||||
history.replaceOrPush(compileResult.lineId, retVal.scriptInstance)
|
||||
ReplEvalResult.UnitResult()
|
||||
}
|
||||
else -> throw IllegalStateException("Expecting value with script instance, got $retVal")
|
||||
}
|
||||
else -> ReplEvalResult.Error.Runtime(res.reports.joinToString("\n") { it.message })
|
||||
else -> ReplEvalResult.Error.Runtime(res.reports.joinToString("\n") { it.message + (it.exception?.let { e -> ": $e" } ?: "") })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,10 +80,29 @@ open class JvmReplEvaluatorState(
|
||||
scriptEvaluationConfiguration: ScriptEvaluationConfiguration,
|
||||
override val lock: ReentrantReadWriteLock = ReentrantReadWriteLock()
|
||||
) : IReplStageState<Any> {
|
||||
|
||||
override val history: IReplStageHistory<Any> = BasicReplStageHistory(lock)
|
||||
override val history: IReplStageHistory<Any> = ReplStageHistoryWithReplace(lock)
|
||||
|
||||
override val currentGeneration: Int get() = (history as BasicReplStageHistory<*>).currentGeneration.get()
|
||||
|
||||
val topClassLoader: ClassLoader = scriptEvaluationConfiguration[ScriptEvaluationConfiguration.jvm.baseClassLoader]!!
|
||||
}
|
||||
|
||||
open class ReplStageHistoryWithReplace<T>(lock: ReentrantReadWriteLock = ReentrantReadWriteLock()) : BasicReplStageHistory<T>(lock) {
|
||||
|
||||
fun replace(id: ILineId, item: T): Boolean = lock.write {
|
||||
for (idx in indices) {
|
||||
if (get(idx).id == id) {
|
||||
set(idx, ReplHistoryRecord(id, item))
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun replaceOrPush(id: ILineId, item: T) {
|
||||
if (!replace(id, item)) {
|
||||
tryResetTo(id)
|
||||
push(id, item)
|
||||
}
|
||||
}
|
||||
|
||||
fun previousItems(id: ILineId): Sequence<T> = asSequence().takeWhile { it.id.no < id.no }.map { it.item }
|
||||
}
|
||||
Reference in New Issue
Block a user