Core interfaces and data structures for Kotlin script compilation, evaluation, and IDE integration
—
Specialized interfaces for interactive Read-Eval-Print Loop functionality with snippet management, code analysis, completion, and evaluation. Provides the foundation for building interactive Kotlin scripting environments.
Specialized compiler interface for compiling individual REPL snippets with incremental compilation support.
/**
* Compiler interface specialized for REPL snippet compilation
*/
interface ReplCompiler<CompiledSnippetT : Any> {
/**
* Compile a REPL snippet
* @param snippet Source code snippet to compile
* @param configuration Compilation configuration for the snippet
* @return Result containing compiled snippet or compilation errors
*/
suspend fun compile(
snippet: SourceCode,
configuration: ScriptCompilationConfiguration
): ResultWithDiagnostics<CompiledSnippetT>
}Evaluator interface specialized for executing compiled REPL snippets with state management.
/**
* Evaluator interface specialized for REPL snippet evaluation
*/
interface ReplEvaluator<CompiledSnippetT : Any, EvaluatedSnippetT : Any> {
/**
* Evaluate a compiled REPL snippet
* @param snippet Compiled snippet to evaluate
* @param configuration Evaluation configuration
* @return Result containing evaluated snippet or evaluation errors
*/
suspend fun eval(
snippet: CompiledSnippetT,
configuration: ScriptEvaluationConfiguration
): ResultWithDiagnostics<EvaluatedSnippetT>
}Represents an evaluated REPL snippet with access to its compilation and evaluation state.
/**
* Represents an evaluated REPL snippet
*/
interface EvaluatedSnippet {
/** The compiled snippet that was evaluated */
val compiledSnippet: CompiledSnippet
/** Configuration used during evaluation */
val configuration: ScriptEvaluationConfiguration
/** Result of the evaluation */
val result: ResultValue
}System for uniquely identifying REPL snippets with sequence numbers and generations.
/**
* Unique identifier for REPL snippets
*/
interface ReplSnippetId {
/** Sequence number of the snippet */
val no: Int
/** Generation number for versioning */
val generation: Int
}
/**
* Implementation of REPL snippet identifier
*/
data class ReplSnippetIdImpl(
override val no: Int,
override val generation: Int
) : ReplSnippetId
/**
* Constants for REPL snippet numbering
*/
const val REPL_SNIPPET_FIRST_NO = 1
const val REPL_SNIPPET_FIRST_GEN = 1Interfaces for REPL code analysis and intelligent code completion.
/**
* Interface for analyzing REPL code
*/
interface ReplCodeAnalyzer {
/**
* Analyze REPL code snippet
* @param snippet Code snippet to analyze
* @param cursor Cursor position within the snippet
* @param configuration Analysis configuration
* @return Analysis results
*/
suspend fun analyze(
snippet: SourceCode,
cursor: SourceCode.Position,
configuration: ScriptCompilationConfiguration
): ResultWithDiagnostics<ReplAnalyzerResult>
}
/**
* Interface for providing code completion in REPL
*/
interface ReplCompleter {
/**
* Get code completion suggestions
* @param snippet Code snippet for completion
* @param cursor Cursor position for completion
* @param configuration Compilation configuration
* @return Sequence of completion variants
*/
suspend fun complete(
snippet: SourceCode,
cursor: SourceCode.Position,
configuration: ScriptCompilationConfiguration
): ResultWithDiagnostics<ReplCompletionResult>
}Data structures for representing code completion suggestions.
/**
* Type alias for completion results
*/
typealias ReplCompletionResult = Sequence<SourceCodeCompletionVariant>
/**
* Individual completion suggestion
*/
data class SourceCodeCompletionVariant(
val text: String,
val displayText: String,
val tail: String = "",
val icon: String = "",
val deprecationLevel: DeprecationLevel? = null
)Specialized configuration keys for REPL compilation and host settings.
/**
* Configuration keys specific to REPL compilation
*/
interface ReplScriptCompilationConfigurationKeys {
val makeSnippetIdentifier: PropertiesCollection.Key<MakeSnippetIdentifier>
val snippetIdKey: PropertiesCollection.Key<String>
}
/**
* Configuration keys for REPL scripting host
*/
interface ReplScriptingHostConfigurationKeys {
val replCompiler: PropertiesCollection.Key<ReplCompiler<*>>
val replEvaluator: PropertiesCollection.Key<ReplEvaluator<*, *>>
val replCodeAnalyzer: PropertiesCollection.Key<ReplCodeAnalyzer>
val replCompleter: PropertiesCollection.Key<ReplCompleter>
}
/**
* Keys for REPL analyzer results
*/
interface ReplAnalyzerResultKeys {
val isComplete: PropertiesCollection.Key<Boolean>
val completions: PropertiesCollection.Key<ReplCompletionResult>
val diagnostics: PropertiesCollection.Key<List<ScriptDiagnostic>>
}Convenient type aliases for REPL-related function types.
/**
* Type alias for compiled snippet (same as CompiledScript)
*/
typealias CompiledSnippet = CompiledScript
/**
* Function type for creating snippet identifiers
*/
typealias MakeSnippetIdentifier = (ReplSnippetId) -> StringContainer for REPL code analysis results.
/**
* Results of REPL code analysis
*/
class ReplAnalyzerResult : PropertiesCollectionUsage Examples:
import kotlin.script.experimental.api.*
// Basic REPL implementation example
class SimpleReplSystem {
private val compiler: ReplCompiler<CompiledSnippet> = TODO("Implementation")
private val evaluator: ReplEvaluator<CompiledSnippet, EvaluatedSnippet> = TODO("Implementation")
private val completer: ReplCompleter = TODO("Implementation")
private var snippetCounter = REPL_SNIPPET_FIRST_NO
private val evaluatedSnippets = mutableListOf<EvaluatedSnippet>()
suspend fun execute(code: String): ReplResult {
// Create snippet source
val snippet = code.toScriptSource("snippet_$snippetCounter")
// Compile the snippet
val compilationResult = compiler.compile(snippet, getCompilationConfig())
if (compilationResult is ResultWithDiagnostics.Failure) {
return ReplResult.CompilationError(compilationResult.reports)
}
val compiledSnippet = compilationResult.value
// Evaluate the snippet
val evaluationResult = evaluator.eval(compiledSnippet, getEvaluationConfig())
if (evaluationResult is ResultWithDiagnostics.Failure) {
return ReplResult.EvaluationError(evaluationResult.reports)
}
val evaluatedSnippet = evaluationResult.value
evaluatedSnippets.add(evaluatedSnippet)
snippetCounter++
return ReplResult.Success(evaluatedSnippet.result)
}
suspend fun complete(code: String, cursorPos: Int): List<String> {
val snippet = code.toScriptSource("completion")
val cursor = SourceCode.Position(1, cursorPos)
val completionResult = completer.complete(snippet, cursor, getCompilationConfig())
return if (completionResult is ResultWithDiagnostics.Success) {
completionResult.value.map { it.text }.toList()
} else {
emptyList()
}
}
}
sealed class ReplResult {
data class Success(val value: ResultValue) : ReplResult()
data class CompilationError(val diagnostics: List<ScriptDiagnostic>) : ReplResult()
data class EvaluationError(val diagnostics: List<ScriptDiagnostic>) : ReplResult()
}// Snippet identifier management
class SnippetIdManager {
private var currentNo = REPL_SNIPPET_FIRST_NO
private var currentGen = REPL_SNIPPET_FIRST_GEN
fun nextSnippetId(): ReplSnippetId {
return ReplSnippetIdImpl(currentNo++, currentGen)
}
fun resetGeneration() {
currentGen++
currentNo = REPL_SNIPPET_FIRST_NO
}
}
// Custom snippet identifier function
val customMakeSnippetIdentifier: MakeSnippetIdentifier = { snippetId ->
"Snippet_${snippetId.no}_Gen${snippetId.generation}"
}
// REPL compilation configuration
val replCompilationConfig = ScriptCompilationConfiguration {
makeSnippetIdentifier(customMakeSnippetIdentifier)
snippetIdKey("replSnippetId")
// Standard compilation settings
defaultImports("kotlin.math.*", "kotlin.collections.*")
dependencies.append(JvmDependency("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4"))
}// Custom completion provider
class CustomReplCompleter : ReplCompleter {
override suspend fun complete(
snippet: SourceCode,
cursor: SourceCode.Position,
configuration: ScriptCompilationConfiguration
): ResultWithDiagnostics<ReplCompletionResult> {
val text = snippet.text
val cursorPos = cursor.absolutePos ?: return emptySequence<SourceCodeCompletionVariant>().asSuccess()
// Simple keyword completion example
val completions = mutableListOf<SourceCodeCompletionVariant>()
// Get word at cursor
val wordStart = text.lastIndexOf(' ', cursorPos - 1) + 1
val prefix = text.substring(wordStart, cursorPos)
// Kotlin keywords that start with prefix
val keywords = listOf("fun", "val", "var", "if", "else", "when", "for", "while", "class", "interface")
keywords.filter { it.startsWith(prefix) }.forEach { keyword ->
completions.add(SourceCodeCompletionVariant(
text = keyword,
displayText = keyword,
tail = " (keyword)",
icon = "keyword"
))
}
return completions.asSequence().asSuccess()
}
}// Example REPL session flow
class InteractiveReplSession {
private val replSystem = SimpleReplSystem()
suspend fun runSession() {
println("Kotlin REPL - Enter ':quit' to exit")
while (true) {
print("kotlin> ")
val input = readLine() ?: break
when {
input == ":quit" -> break
input.startsWith(":complete ") -> {
val code = input.removePrefix(":complete ")
val completions = replSystem.complete(code, code.length)
println("Completions: ${completions.joinToString(", ")}")
}
else -> {
when (val result = replSystem.execute(input)) {
is ReplResult.Success -> {
when (val value = result.value) {
is ResultValue.Value -> println("res: ${value.value}")
is ResultValue.Unit -> println("kotlin> ")
is ResultValue.Error -> println("Error: ${value.error.message}")
is ResultValue.NotEvaluated -> println("Not evaluated")
}
}
is ReplResult.CompilationError -> {
result.diagnostics.forEach {
println("Compilation error: ${it.message}")
}
}
is ReplResult.EvaluationError -> {
result.diagnostics.forEach {
println("Evaluation error: ${it.message}")
}
}
}
}
}
}
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-kotlin--kotlin-scripting-common