or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-scripting-host.mdindex.mdjsr223-integration.mdrepl-support.mdscript-caching.mdscript-compilation.mdscript-persistence.md

repl-support.mddocs/

0

# REPL Support

1

2

Legacy REPL API compatibility layer for interactive script evaluation and compilation with incremental execution capabilities.

3

4

## Capabilities

5

6

### JvmReplCompiler

7

8

REPL compilation wrapper that provides legacy REPL API compatibility for incremental script compilation.

9

10

```kotlin { .api }

11

/**

12

* REPL compiler implementation for legacy REPL APIs

13

* @param scriptCompilationConfiguration Compilation configuration for REPL scripts

14

* @param hostConfiguration Host configuration with JVM-specific settings

15

*/

16

class JvmReplCompiler(

17

val scriptCompilationConfiguration: ScriptCompilationConfiguration,

18

val hostConfiguration: ScriptingHostConfiguration = defaultJvmScriptingHostConfiguration

19

) : ReplCompilerWithoutCheck {

20

21

/**

22

* Creates new REPL compilation state

23

* @param lock Read-write lock for thread synchronization

24

* @returns New REPL stage state for compilation

25

*/

26

override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*>

27

28

/**

29

* Compiles a single REPL code line

30

* @param state Current REPL compilation state

31

* @param codeLine REPL code line to compile

32

* @returns Compilation result with compiled classes or errors

33

*/

34

override fun compile(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCompileResult

35

}

36

```

37

38

### JvmReplEvaluator

39

40

REPL evaluation wrapper that executes compiled REPL scripts with state management and history tracking.

41

42

```kotlin { .api }

43

/**

44

* REPL evaluator implementation for legacy REPL APIs

45

* @param baseScriptEvaluationConfiguration Base evaluation configuration

46

* @param scriptEvaluator Script evaluator for executing compiled scripts

47

*/

48

class JvmReplEvaluator(

49

val baseScriptEvaluationConfiguration: ScriptEvaluationConfiguration,

50

val scriptEvaluator: ScriptEvaluator = BasicJvmScriptEvaluator()

51

) : ReplEvaluator {

52

53

/**

54

* Creates new REPL evaluation state

55

* @param lock Read-write lock for thread synchronization

56

* @returns New REPL stage state for evaluation

57

*/

58

override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*>

59

60

/**

61

* Evaluates compiled REPL script classes

62

* @param state Current REPL evaluation state

63

* @param compileResult Compiled classes from REPL compiler

64

* @param scriptArgs Optional script arguments with types

65

* @param invokeWrapper Optional wrapper for function invocation

66

* @returns Evaluation result with value or error

67

*/

68

override fun eval(

69

state: IReplStageState<*>,

70

compileResult: ReplCompileResult.CompiledClasses,

71

scriptArgs: ScriptArgsWithTypes? = null,

72

invokeWrapper: InvokeWrapper? = null

73

): ReplEvalResult

74

}

75

```

76

77

**Usage Examples:**

78

79

```kotlin

80

import kotlin.script.experimental.jvmhost.repl.*

81

import kotlin.script.experimental.api.*

82

import kotlin.script.experimental.jvm.util.*

83

import java.util.concurrent.locks.ReentrantReadWriteLock

84

85

// Create REPL compiler and evaluator

86

val replConfig = ScriptCompilationConfiguration {

87

dependencies(JvmDependency(kotlinStdlib))

88

compilerOptions.append("-language-version", "2.0")

89

}

90

91

val evalConfig = ScriptEvaluationConfiguration {

92

// REPL-specific evaluation configuration

93

enableScriptsInstancesSharing()

94

}

95

96

val replCompiler = JvmReplCompiler(

97

scriptCompilationConfiguration = replConfig,

98

hostConfiguration = defaultJvmScriptingHostConfiguration

99

)

100

101

val replEvaluator = JvmReplEvaluator(

102

baseScriptEvaluationConfiguration = evalConfig

103

)

104

105

// Initialize REPL states

106

val lock = ReentrantReadWriteLock()

107

val compilerState = replCompiler.createState(lock)

108

val evaluatorState = replEvaluator.createState(lock)

109

110

// Interactive REPL session

111

val replLines = listOf(

112

"val x = 42",

113

"val y = x * 2",

114

"data class Person(val name: String, val age: Int)",

115

"val person = Person(\"Alice\", 30)",

116

"println(\"Person: \$person, y = \$y\")",

117

"person.age + y"

118

)

119

120

replLines.forEachIndexed { index, code ->

121

println("[$index] $code")

122

123

// Compile line

124

val codeLine = ReplCodeLine(index, 0, code)

125

val compileResult = replCompiler.compile(compilerState, codeLine)

126

127

when (compileResult) {

128

is ReplCompileResult.CompiledClasses -> {

129

println(" Compiled successfully")

130

131

// Evaluate compiled code

132

val evalResult = replEvaluator.eval(evaluatorState, compileResult)

133

134

when (evalResult) {

135

is ReplEvalResult.ValueResult -> {

136

println(" Result: ${evalResult.value} : ${evalResult.type}")

137

}

138

is ReplEvalResult.UnitResult -> {

139

println(" Executed successfully")

140

}

141

is ReplEvalResult.Error -> {

142

println(" Evaluation error: ${evalResult.error.message}")

143

}

144

is ReplEvalResult.Incomplete -> {

145

println(" Incomplete input")

146

}

147

}

148

}

149

is ReplCompileResult.Error -> {

150

println(" Compilation error: ${compileResult.message}")

151

}

152

is ReplCompileResult.Incomplete -> {

153

println(" Incomplete input - expecting more")

154

}

155

}

156

println()

157

}

158

```

159

160

### JvmReplEvaluatorState

161

162

REPL evaluator state implementation that manages execution history and supports script instance sharing.

163

164

```kotlin { .api }

165

/**

166

* REPL evaluator state with history management

167

* @param scriptEvaluationConfiguration Evaluation configuration for REPL scripts

168

* @param lock Read-write lock for thread synchronization

169

*/

170

open class JvmReplEvaluatorState(

171

val scriptEvaluationConfiguration: ScriptEvaluationConfiguration,

172

lock: ReentrantReadWriteLock

173

) : IReplStageState<Any> {

174

175

/** History of evaluated script instances and their results */

176

val history: IReplStageHistory<Pair<KClass<*>?, Any?>>

177

178

/** Current generation/version of the REPL state */

179

val currentGeneration: Int

180

}

181

```

182

183

### ReplStageHistoryWithReplace

184

185

Enhanced REPL history implementation that supports replacing and updating previous evaluations.

186

187

```kotlin { .api }

188

/**

189

* REPL stage history with replacement capabilities

190

* @param lock Read-write lock for thread synchronization

191

*/

192

open class ReplStageHistoryWithReplace<T>(lock: ReentrantReadWriteLock) : IReplStageHistory<T> {

193

194

/**

195

* Replaces an existing history entry

196

* @param id Line identifier to replace

197

* @param item New item to replace with

198

* @returns True if replacement succeeded, false if not found

199

*/

200

fun replace(id: ILineId, item: T): Boolean

201

202

/**

203

* Replaces existing entry or pushes new one if not found

204

* @param id Line identifier

205

* @param item Item to replace or add

206

*/

207

fun replaceOrPush(id: ILineId, item: T)

208

209

/**

210

* Gets sequence of items that were evaluated before the given line

211

* @param id Line identifier to get previous items for

212

* @returns Sequence of previous items in order

213

*/

214

fun previousItems(id: ILineId): Sequence<T>

215

}

216

```

217

218

**Advanced REPL Example with History Management:**

219

220

```kotlin

221

import kotlin.script.experimental.jvmhost.repl.*

222

223

// Create REPL with custom history management

224

class InteractiveReplSession {

225

private val lock = ReentrantReadWriteLock()

226

private val replCompiler = JvmReplCompiler(

227

ScriptCompilationConfiguration {

228

dependencies(JvmDependency(kotlinStdlib))

229

// Enable script instance sharing for REPL

230

refineConfiguration {

231

onAnnotations { context ->

232

ScriptCompilationConfiguration(context.compilationConfiguration) {

233

implicitReceivers(String::class) // Example: implicit string receiver

234

}.asSuccess()

235

}

236

}

237

}

238

)

239

240

private val replEvaluator = JvmReplEvaluator(

241

ScriptEvaluationConfiguration {

242

enableScriptsInstancesSharing()

243

// Provide previous results as context

244

providedProperties("results" to List::class)

245

}

246

)

247

248

private val compilerState = replCompiler.createState(lock)

249

private val evaluatorState = replEvaluator.createState(lock)

250

private val results = mutableListOf<Any?>()

251

252

fun evalLine(lineNumber: Int, code: String): ReplEvalResult {

253

val codeLine = ReplCodeLine(lineNumber, 0, code)

254

255

// Compile

256

val compileResult = replCompiler.compile(compilerState, codeLine)

257

258

return when (compileResult) {

259

is ReplCompileResult.CompiledClasses -> {

260

// Evaluate with context

261

val evalResult = replEvaluator.eval(evaluatorState, compileResult)

262

263

// Store result for future reference

264

when (evalResult) {

265

is ReplEvalResult.ValueResult -> {

266

results.add(evalResult.value)

267

}

268

is ReplEvalResult.UnitResult -> {

269

results.add(Unit)

270

}

271

else -> {

272

results.add(null)

273

}

274

}

275

276

evalResult

277

}

278

is ReplCompileResult.Error -> {

279

ReplEvalResult.Error.CompileTime(

280

"Compilation failed: ${compileResult.message}"

281

)

282

}

283

is ReplCompileResult.Incomplete -> {

284

ReplEvalResult.Incomplete()

285

}

286

}

287

}

288

289

fun replaceLineAndReevaluate(lineNumber: Int, newCode: String): List<ReplEvalResult> {

290

// This would require more sophisticated state management

291

// to re-evaluate dependent lines after replacement

292

val results = mutableListOf<ReplEvalResult>()

293

294

// Replace the specific line

295

val newResult = evalLine(lineNumber, newCode)

296

results.add(newResult)

297

298

// Re-evaluate subsequent lines that might depend on this change

299

// This is a simplified example - real implementation would need

300

// dependency tracking and selective re-evaluation

301

302

return results

303

}

304

305

fun getHistory(): List<Any?> = results.toList()

306

307

fun getCurrentGeneration(): Int {

308

return (evaluatorState as? JvmReplEvaluatorState)?.currentGeneration ?: 0

309

}

310

}

311

312

// Usage example

313

val replSession = InteractiveReplSession()

314

315

// Interactive session

316

val inputs = listOf(

317

"val numbers = listOf(1, 2, 3, 4, 5)",

318

"val doubled = numbers.map { it * 2 }",

319

"println(\"Original: \$numbers\")",

320

"println(\"Doubled: \$doubled\")",

321

"doubled.sum()"

322

)

323

324

inputs.forEachIndexed { index, input ->

325

println("> $input")

326

327

val result = replSession.evalLine(index, input)

328

when (result) {

329

is ReplEvalResult.ValueResult -> {

330

println(" = ${result.value} : ${result.type}")

331

}

332

is ReplEvalResult.UnitResult -> {

333

println(" (executed)")

334

}

335

is ReplEvalResult.Error -> {

336

println(" Error: ${result.message}")

337

}

338

is ReplEvalResult.Incomplete -> {

339

println(" (incomplete)")

340

}

341

}

342

}

343

344

println("\nSession history: ${replSession.getHistory()}")

345

println("Generation: ${replSession.getCurrentGeneration()}")

346

```

347

348

## Source Code Integration

349

350

Utility classes for converting between REPL code lines and standard source code representations.

351

352

### SourceCodeFromReplCodeLine

353

354

```kotlin { .api }

355

/**

356

* Internal source code implementation from REPL code line

357

* @param codeLine REPL code line to wrap

358

* @param compilationConfiguration Compilation configuration for context

359

*/

360

internal class SourceCodeFromReplCodeLine(

361

val codeLine: ReplCodeLine,

362

compilationConfiguration: ScriptCompilationConfiguration

363

) : SourceCode {

364

365

/** Script text content from REPL line */

366

override val text: String

367

368

/** Script name derived from REPL line identifier */

369

override val name: String

370

371

/** Location identifier for error reporting */

372

override val locationId: String?

373

}

374

```

375

376

### REPL Extension Functions

377

378

```kotlin { .api }

379

/**

380

* Converts REPL code line to source code for compilation

381

* @param compilationConfiguration Compilation configuration for context

382

* @returns SourceCode representation of the REPL line

383

*/

384

internal fun ReplCodeLine.toSourceCode(

385

compilationConfiguration: ScriptCompilationConfiguration

386

): SourceCode

387

```

388

389

## Internal Utility Classes

390

391

The REPL support includes several internal utility classes for bridging between REPL-specific types and standard scripting API types.

392

393

### SourceCodeFromReplCodeLine

394

395

```kotlin { .api }

396

/**

397

* Internal source code implementation that wraps REPL code lines

398

* @param codeLine The REPL code line to wrap

399

* @param compilationConfiguration Compilation configuration for context

400

*/

401

internal class SourceCodeFromReplCodeLine(

402

val codeLine: ReplCodeLine,

403

compilationConfiguration: ScriptCompilationConfiguration

404

) : SourceCode {

405

406

/** Script text content from the REPL line */

407

override val text: String

408

409

/** Script name derived from REPL line identifier and sequence number */

410

override val name: String

411

412

/** Location identifier for error reporting and source tracking */

413

override val locationId: String?

414

}

415

```

416

417

**Note**: This class is internal to the REPL implementation and is used to bridge between REPL-specific `ReplCodeLine` objects and the standard `SourceCode` interface used by the compilation system.

418

419

**Source Code Integration Example:**

420

421

```kotlin

422

import kotlin.script.experimental.jvmhost.repl.*

423

424

// Custom REPL implementation with source code tracking

425

class SourceTrackingRepl {

426

private val sourceHistory = mutableMapOf<Int, SourceCode>()

427

428

fun compileWithSourceTracking(

429

compiler: JvmReplCompiler,

430

state: IReplStageState<*>,

431

lineNumber: Int,

432

code: String

433

): ReplCompileResult {

434

val codeLine = ReplCodeLine(lineNumber, 0, code)

435

436

// Convert to source code for tracking

437

val sourceCode = codeLine.toSourceCode(compiler.scriptCompilationConfiguration)

438

sourceHistory[lineNumber] = sourceCode

439

440

// Compile normally

441

val result = compiler.compile(state, codeLine)

442

443

// Log compilation with source information

444

when (result) {

445

is ReplCompileResult.CompiledClasses -> {

446

println("Compiled line $lineNumber: ${sourceCode.name}")

447

println(" Source location: ${sourceCode.locationId}")

448

println(" Text length: ${sourceCode.text.length} characters")

449

}

450

is ReplCompileResult.Error -> {

451

println("Compilation failed for line $lineNumber")

452

println(" Source: ${sourceCode.name}")

453

println(" Error: ${result.message}")

454

}

455

}

456

457

return result

458

}

459

460

fun getSourceForLine(lineNumber: Int): SourceCode? {

461

return sourceHistory[lineNumber]

462

}

463

464

fun getAllSources(): Map<Int, SourceCode> {

465

return sourceHistory.toMap()

466

}

467

}

468

469

// Usage

470

val sourceTracker = SourceTrackingRepl()

471

val compiler = JvmReplCompiler(ScriptCompilationConfiguration.Default)

472

val state = compiler.createState(ReentrantReadWriteLock())

473

474

// Compile with source tracking

475

val result = sourceTracker.compileWithSourceTracking(

476

compiler, state, 1, "val greeting = \"Hello, REPL!\""

477

)

478

479

// Access source information

480

val source = sourceTracker.getSourceForLine(1)

481

println("Source name: ${source?.name}")

482

println("Source location: ${source?.locationId}")

483

```

484

485

## Integration with Modern Scripting API

486

487

The REPL support provides bridge functionality between legacy REPL APIs and modern Kotlin scripting infrastructure.

488

489

### Migration from Legacy REPL

490

491

```kotlin

492

// Legacy REPL usage (deprecated)

493

// val legacyRepl = KotlinJsr223JvmLocalScriptEngine()

494

495

// Modern REPL usage through compatibility layer

496

val modernReplCompiler = JvmReplCompiler(

497

ScriptCompilationConfiguration {

498

dependencies(JvmDependency(kotlinStdlib))

499

baseClass(KotlinType(Any::class))

500

}

501

)

502

503

val modernReplEvaluator = JvmReplEvaluator(

504

ScriptEvaluationConfiguration {

505

enableScriptsInstancesSharing()

506

jvm {

507

baseClassLoader(Thread.currentThread().contextClassLoader)

508

}

509

}

510

)

511

512

// Bridge to JSR-223 if needed

513

val jsr223Engine = KotlinJsr223ScriptEngineImpl(

514

factory = KotlinJsr223DefaultScriptEngineFactory(),

515

baseCompilationConfiguration = modernReplCompiler.scriptCompilationConfiguration,

516

baseEvaluationConfiguration = modernReplEvaluator.baseScriptEvaluationConfiguration

517

) { context ->

518

// Extract arguments from JSR-223 context

519

val args = context.getBindings(ScriptContext.ENGINE_SCOPE)["args"] as? Array<String>

520

args?.let { ScriptArgsWithTypes(it, arrayOf(Array<String>::class)) }

521

}

522

```

523

524

### Performance Considerations

525

526

REPL support is optimized for interactive use but has specific performance characteristics:

527

528

- **Compilation Overhead**: Each line requires separate compilation

529

- **State Management**: History tracking increases memory usage

530

- **Thread Safety**: Synchronization adds latency to operations

531

- **Dependency Resolution**: Repeated dependency loading for each line

532

533

**Performance Optimization Example:**

534

535

```kotlin

536

class OptimizedReplSession {

537

// Reuse configurations to avoid repeated setup

538

private val sharedCompilationConfig = ScriptCompilationConfiguration {

539

dependencies(JvmDependency(kotlinStdlib))

540

// Cache dependencies

541

hostConfiguration(ScriptingHostConfiguration {

542

jvm {

543

compilationCache(FileBasedScriptCache(File("repl-cache")))

544

}

545

})

546

}

547

548

// Batch compilation for related lines

549

fun compileMultipleLines(lines: List<String>): List<ReplCompileResult> {

550

val compiler = JvmReplCompiler(sharedCompilationConfig)

551

val state = compiler.createState(ReentrantReadWriteLock())

552

553

return lines.mapIndexed { index, code ->

554

val codeLine = ReplCodeLine(index, 0, code)

555

compiler.compile(state, codeLine)

556

}

557

}

558

559

// Lazy evaluation for expensive operations

560

fun evaluateWithLazyResults(

561

compileResults: List<ReplCompileResult.CompiledClasses>

562

): Sequence<ReplEvalResult> {

563

val evaluator = JvmReplEvaluator(ScriptEvaluationConfiguration.Default)

564

val state = evaluator.createState(ReentrantReadWriteLock())

565

566

return compileResults.asSequence().map { compiled ->

567

evaluator.eval(state, compiled)

568

}

569

}

570

}

571

```

572

573

## Types

574

575

### REPL Evaluation Result Types

576

577

```kotlin { .api }

578

// Imported from kotlin.script.experimental.api and related packages

579

sealed class ReplEvalResult : Serializable {

580

581

/** Successful evaluation with a returned value */

582

class ValueResult(

583

val name: String,

584

val value: Any?,

585

val type: String?,

586

val snippetInstance: Any? = null

587

) : ReplEvalResult()

588

589

/** Successful evaluation with no return value */

590

class UnitResult : ReplEvalResult()

591

592

/** Incomplete input requiring more code */

593

class Incomplete(val message: String) : ReplEvalResult()

594

595

/** History state mismatch error */

596

class HistoryMismatch(val lineNo: Int) : ReplEvalResult()

597

598

/** Evaluation errors */

599

sealed class Error(val message: String) : ReplEvalResult() {

600

/** Runtime execution error */

601

class Runtime(message: String, val cause: Throwable? = null) : Error(message)

602

603

/** Compile-time error */

604

class CompileTime(message: String, val location: CompilerMessageLocation? = null) : Error(message)

605

}

606

}

607

608

/** Compilation result for REPL code lines */

609

sealed class ReplCompileResult {

610

class CompiledClasses(

611

val lineId: ReplCodeLine.Id,

612

val data: Any,

613

val hasResult: Boolean,

614

val classpathAddendum: List<File> = emptyList()

615

) : ReplCompileResult()

616

617

class Incomplete : ReplCompileResult()

618

619

class Error(

620

val message: String,

621

val location: CompilerMessageLocation? = null

622

) : ReplCompileResult()

623

}

624

```