Make state of the default REPL compiler explicit and replaceable

restores proper object hierarchy in case the legacy REPL infrastructure
This commit is contained in:
Ilya Chernikov
2021-08-20 15:11:48 +02:00
committed by TeamCityServer
parent e7c9a46329
commit a45e31720c
9 changed files with 121 additions and 117 deletions
@@ -6,7 +6,6 @@
package kotlin.script.experimental.jvmhost.jsr223
import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.cli.common.repl.ReplCompilerWithoutCheck
import java.util.concurrent.locks.ReentrantReadWriteLock
import javax.script.ScriptContext
import javax.script.ScriptEngineFactory
@@ -63,7 +62,7 @@ class KotlinJsr223ScriptEngineImpl(
}
override val replCompiler: ReplCompilerWithoutCheck by lazy {
JvmReplCompiler(compilationConfiguration, true)
JvmReplCompiler(compilationConfiguration)
}
private val localEvaluator by lazy {
@@ -5,18 +5,16 @@
package kotlin.script.experimental.jvmhost.repl
import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.KJvmReplCompilerBase
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.JvmReplCompilerStageHistory
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.JvmReplCompilerState
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzerBase
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.write
import kotlin.script.experimental.api.*
import kotlin.script.experimental.impl.internalScriptingRunSuspend
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.script.experimental.host.withDefaultsFrom
import kotlin.script.experimental.impl.internalScriptingRunSuspend
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
import kotlin.script.experimental.jvm.util.isIncomplete
@@ -25,50 +23,28 @@ import kotlin.script.experimental.jvm.util.isIncomplete
*/
class JvmReplCompiler(
val scriptCompilationConfiguration: ScriptCompilationConfiguration,
val allowReInit: Boolean = true,
val hostConfiguration: ScriptingHostConfiguration = defaultJvmScriptingHostConfiguration,
var replCompiler: KJvmReplCompilerBase<ReplCodeAnalyzerBase> = KJvmReplCompilerBase.create(
hostConfiguration.withDefaultsFrom(defaultJvmScriptingHostConfiguration)
)
val hostConfiguration: ScriptingHostConfiguration = defaultJvmScriptingHostConfiguration
) : ReplCompilerWithoutCheck {
private val compilers = mutableListOf(replCompiler)
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> =
if (allowReInit) {
JvmReplCompilerState({ replCompiler.createReplCompilationState(it, replCompiler.initAnalyzer) }, lock)
} else {
replCompiler.state
}
JvmReplCompilerState({ KJvmReplCompilerBase.createCompilationState(it, hostConfiguration) }, lock)
override fun compile(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCompileResult = replCompiler.state.lock.write {
override fun compile(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCompileResult = state.lock.write {
val replCompilerState = state.asState(JvmReplCompilerState::class.java)
val snippet = codeLine.toSourceCode(scriptCompilationConfiguration)
if (allowReInit) {
replCompiler = compilers.find { historiesEq(it.history, replCompilerState.history) } ?: {
compilers.push(
KJvmReplCompilerBase.create(
hostConfiguration.withDefaultsFrom(defaultJvmScriptingHostConfiguration)
)
)
compilers.last()
}()
}
val replCompiler = KJvmReplCompilerBase<ReplCodeAnalyzerBase>(
hostConfiguration.withDefaultsFrom(defaultJvmScriptingHostConfiguration),
replCompilerState
)
@Suppress("DEPRECATION_ERROR")
when (val res = internalScriptingRunSuspend { replCompiler.compile(listOf(snippet), scriptCompilationConfiguration) }) {
is ResultWithDiagnostics.Success -> {
val lineId = LineId(codeLine.no, 0, snippet.hashCode())
replCompilerState.apply {
lock.write {
val compilerHistory = history as JvmReplCompilerStageHistory<*>
compilerHistory.push(lineId, replCompiler.history.last().item)
}
}
ReplCompileResult.CompiledClasses(
lineId,
replCompiler.history.map { it.id },
replCompiler.state.history.map { it.id },
snippet.name!!,
emptyList(),
res.value.get().resultField != null,
@@ -87,15 +63,6 @@ class JvmReplCompiler(
}
}
}
companion object {
fun historiesEq(history1: IReplStageHistory<*>, history2: IReplStageHistory<*>) =
history1.count() == history2.count() &&
history1.zip(history2).all {
val (it1, it2) = it
it1.item === it2.item
}
}
}
@@ -105,9 +72,11 @@ internal class SourceCodeFromReplCodeLine(
) : SourceCode {
override val text: String get() = codeLine.code
override val name: String =
"${compilationConfiguration[ScriptCompilationConfiguration.repl.makeSnippetIdentifier]!!(
compilationConfiguration, ReplSnippetIdImpl(codeLine.no, codeLine.generation, 0)
)}.${compilationConfiguration[ScriptCompilationConfiguration.fileExtension]}"
"${
compilationConfiguration[ScriptCompilationConfiguration.repl.makeSnippetIdentifier]!!(
compilationConfiguration, ReplSnippetIdImpl(codeLine.no, codeLine.generation, 0)
)
}.${compilationConfiguration[ScriptCompilationConfiguration.fileExtension]}"
override val locationId: String? = null
}