0
# REPL Client
1
2
Interactive Kotlin compilation and evaluation through the daemon with state management and history tracking. Provides a complete REPL (Read-Eval-Print Loop) implementation for interactive Kotlin development.
3
4
## Capabilities
5
6
### KotlinRemoteReplCompilerClient
7
8
Main REPL client class that provides interactive compilation capabilities through the daemon.
9
10
```kotlin { .api }
11
/**
12
* Remote REPL compiler client for interactive Kotlin compilation
13
* @param compileService The daemon service to use
14
* @param clientAliveFlagFile File indicating client is alive (optional)
15
* @param targetPlatform Target platform for compilation
16
* @param args Compiler arguments and configuration
17
* @param messageCollector Handles compiler messages
18
* @param templateClasspath Classpath for REPL template
19
* @param templateClassName Name of the REPL template class
20
* @param port Port for service communication
21
*/
22
class KotlinRemoteReplCompilerClient(
23
protected val compileService: CompileService,
24
clientAliveFlagFile: File?,
25
targetPlatform: CompileService.TargetPlatform,
26
args: Array<out String>,
27
messageCollector: MessageCollector,
28
templateClasspath: List<File>,
29
templateClassName: String,
30
port: Int = SOCKET_ANY_FREE_PORT
31
) : ReplCompiler {
32
val services: BasicCompilerServicesWithResultsFacadeServer
33
val sessionId: Int
34
}
35
```
36
37
**Usage Example:**
38
39
```kotlin
40
import org.jetbrains.kotlin.daemon.client.KotlinRemoteReplCompilerClient
41
import org.jetbrains.kotlin.daemon.common.*
42
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
43
import java.io.File
44
45
val compileService = KotlinCompilerClient.connectToCompileService(...)
46
val messageCollector = PrintingMessageCollector(System.out, null, false)
47
val templateClasspath = listOf(File("/path/to/kotlin-stdlib.jar"))
48
49
val replClient = KotlinRemoteReplCompilerClient(
50
compileService = compileService,
51
clientAliveFlagFile = File("/tmp/repl-client.flag"),
52
targetPlatform = CompileService.TargetPlatform.JVM,
53
args = arrayOf("-classpath", "/path/to/libs/*"),
54
messageCollector = messageCollector,
55
templateClasspath = templateClasspath,
56
templateClassName = "kotlin.script.templates.standard.ScriptTemplateWithArgs"
57
)
58
59
try {
60
// Create REPL state
61
val lock = ReentrantReadWriteLock()
62
val state = replClient.createState(lock)
63
64
// Evaluate REPL lines
65
val codeLine1 = ReplCodeLine(0, 0, "val x = 42")
66
val checkResult1 = replClient.check(state, codeLine1)
67
68
if (checkResult1 is ReplCheckResult.Ok) {
69
val compileResult1 = replClient.compile(state, codeLine1)
70
println("Result: $compileResult1")
71
}
72
73
val codeLine2 = ReplCodeLine(1, 1, "println(\"x = \$x\")")
74
val checkResult2 = replClient.check(state, codeLine2)
75
76
if (checkResult2 is ReplCheckResult.Ok) {
77
val compileResult2 = replClient.compile(state, codeLine2)
78
println("Result: $compileResult2")
79
}
80
81
} finally {
82
replClient.dispose()
83
}
84
```
85
86
### REPL State Management
87
88
Creates and manages REPL execution state with thread-safe access.
89
90
```kotlin { .api }
91
/**
92
* Create a new REPL state for managing compilation context
93
* @param lock Read-write lock for thread-safe state access
94
* @return REPL state instance
95
*/
96
fun createState(lock: ReentrantReadWriteLock): IReplStageState<*>
97
```
98
99
### Code Checking
100
101
Checks REPL code lines for syntax and semantic errors without compilation.
102
103
```kotlin { .api }
104
/**
105
* Check a REPL code line for errors without compiling
106
* @param state The REPL state to check against
107
* @param codeLine The code line to check
108
* @return Check result indicating success or failure with diagnostics
109
*/
110
fun check(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCheckResult
111
```
112
113
### Code Compilation
114
115
Compiles and executes REPL code lines within the managed state.
116
117
```kotlin { .api }
118
/**
119
* Compile and execute a REPL code line
120
* @param state The REPL state for compilation context
121
* @param codeLine The code line to compile
122
* @return Compilation result with execution outcome
123
*/
124
fun compile(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCompileResult
125
```
126
127
### Resource Cleanup
128
129
Properly disposes of REPL resources and releases daemon session.
130
131
```kotlin { .api }
132
/**
133
* Dispose REPL client and free resources
134
* Should be called at the end of REPL lifetime
135
*/
136
fun dispose()
137
```
138
139
## REPL State Classes
140
141
### RemoteReplCompilerState
142
143
Manages REPL compilation state with history and generation tracking.
144
145
```kotlin { .api }
146
/**
147
* Remote REPL compiler state implementation
148
* @param replStateFacade Interface to the remote REPL state
149
* @param lock Thread synchronization lock
150
*/
151
class RemoteReplCompilerState(
152
internal val replStateFacade: ReplStateFacade,
153
override val lock: ReentrantReadWriteLock = ReentrantReadWriteLock()
154
) : IReplStageState<Unit> {
155
override val currentGeneration: Int
156
override val history: IReplStageHistory<Unit>
157
}
158
```
159
160
### RemoteReplCompilerStateHistory
161
162
Manages REPL execution history with navigation and reset capabilities.
163
164
```kotlin { .api }
165
/**
166
* REPL state history management
167
* @param state The REPL state this history belongs to
168
*/
169
class RemoteReplCompilerStateHistory(
170
private val state: RemoteReplCompilerState
171
) : IReplStageHistory<Unit>, AbstractList<ReplHistoryRecord<Unit>>() {
172
override val size: Int
173
val currentGeneration: AtomicInteger
174
override val lock: ReentrantReadWriteLock
175
}
176
```
177
178
#### History Operations
179
180
```kotlin { .api }
181
/**
182
* Get history record at index
183
* @param index The history index
184
* @return History record at the specified index
185
*/
186
fun get(index: Int): ReplHistoryRecord<Unit>
187
188
/**
189
* Push new item to history (not supported for remote history)
190
* @param id Line identifier
191
* @param item History item
192
*/
193
fun push(id: ILineId, item: Unit)
194
195
/**
196
* Pop last item from history (not supported for remote history)
197
* @return Last history record or null
198
*/
199
fun pop(): ReplHistoryRecord<Unit>?
200
201
/**
202
* Reset history to initial state
203
* @return Iterable of removed line IDs
204
*/
205
fun reset(): Iterable<ILineId>
206
207
/**
208
* Reset history to specific line ID
209
* @param id Target line ID to reset to
210
* @return Iterable of removed line IDs
211
*/
212
fun resetTo(id: ILineId): Iterable<ILineId>
213
```
214
215
## Usage Patterns
216
217
### Basic REPL Session
218
219
```kotlin
220
val replClient = KotlinRemoteReplCompilerClient(...)
221
val lock = ReentrantReadWriteLock()
222
val state = replClient.createState(lock)
223
224
try {
225
var lineNumber = 0
226
227
// Read-eval-print loop
228
while (true) {
229
print("kotlin> ")
230
val input = readLine() ?: break
231
232
if (input.trim() == ":quit") break
233
234
val codeLine = ReplCodeLine(lineNumber++, lineNumber, input)
235
236
// Check syntax first
237
when (val checkResult = replClient.check(state, codeLine)) {
238
is ReplCheckResult.Ok -> {
239
// Compile and execute
240
when (val compileResult = replClient.compile(state, codeLine)) {
241
is ReplCompileResult.Ok -> {
242
// Print result if available
243
compileResult.data.let { data ->
244
if (data.result != null) {
245
println("res${lineNumber}: ${data.result}")
246
}
247
}
248
}
249
is ReplCompileResult.Error -> {
250
println("Compilation error: ${compileResult.message}")
251
}
252
}
253
}
254
is ReplCheckResult.Error -> {
255
println("Syntax error: ${checkResult.message}")
256
}
257
}
258
}
259
} finally {
260
replClient.dispose()
261
}
262
```
263
264
### REPL with History Management
265
266
```kotlin
267
val replClient = KotlinRemoteReplCompilerClient(...)
268
val state = replClient.createState(ReentrantReadWriteLock())
269
270
try {
271
// Execute some code
272
val lines = listOf(
273
"val x = 10",
274
"val y = 20",
275
"val sum = x + y",
276
"println(sum)"
277
)
278
279
lines.forEachIndexed { index, code ->
280
val codeLine = ReplCodeLine(index, index, code)
281
replClient.check(state, codeLine)
282
replClient.compile(state, codeLine)
283
}
284
285
// Check history
286
val history = state.history
287
println("History size: ${history.size}")
288
289
// Reset to a previous state
290
if (history.size >= 2) {
291
val secondLineId = history[1].id
292
val removedIds = history.resetTo(secondLineId)
293
println("Removed lines: $removedIds")
294
}
295
296
} finally {
297
replClient.dispose()
298
}
299
```
300
301
### REPL with Error Handling
302
303
```kotlin
304
class ReplErrorHandler(private val replClient: KotlinRemoteReplCompilerClient) {
305
fun evaluateLine(state: IReplStageState<*>, code: String, lineId: Int): String {
306
val codeLine = ReplCodeLine(lineId, lineId, code)
307
308
return try {
309
when (val checkResult = replClient.check(state, codeLine)) {
310
is ReplCheckResult.Ok -> {
311
when (val compileResult = replClient.compile(state, codeLine)) {
312
is ReplCompileResult.Ok -> {
313
compileResult.data.result?.toString() ?: "OK"
314
}
315
is ReplCompileResult.Error -> {
316
"Compilation Error: ${compileResult.message}"
317
}
318
else -> "Unknown compilation result: $compileResult"
319
}
320
}
321
is ReplCheckResult.Error -> {
322
"Check Error: ${checkResult.message}"
323
}
324
else -> "Unknown check result: $checkResult"
325
}
326
} catch (e: Exception) {
327
"Exception: ${e.message}"
328
}
329
}
330
}
331
332
val errorHandler = ReplErrorHandler(replClient)
333
val result = errorHandler.evaluateLine(state, "val invalid syntax", 0)
334
println(result)
335
```